From 8897deff9192c5fcb2dd3a6c8bc58cc000955f20 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Tue, 4 Nov 2025 01:04:57 +0400 Subject: [PATCH] Various improvements --- .../Sources/AccountContext.swift | 48 ++++- .../Sources/SolidRoundedButtonComponent.swift | 6 + .../Sources/DatePickerNode.swift | 7 +- .../FolderInviteLinkListController.swift | 3 +- .../Sources/InviteLinkEditController.swift | 14 +- .../ItemListFolderInviteLinkItem.swift | 15 +- .../Sources/MediaPickerScreen.swift | 182 +++++++++--------- submodules/PremiumUI/BUILD | 1 + .../PremiumUI/Sources/PremiumDemoScreen.swift | 82 +++----- .../Sources/PremiumLimitScreen.swift | 71 ++++--- .../TelegramCore/Sources/Suggestions.swift | 10 + .../Components/AdminUserActionsSheet/BUILD | 2 + .../AdminUserActionsPeerComponent.swift | 2 +- .../Sources/RecentActionsSettingsSheet.swift | 38 +++- .../Sources/AvatarEditorScreen.swift | 10 +- .../Sources/BackgroundColorComponent.swift | 4 +- .../Sources/ButtonComponent.swift | 2 +- .../Sources/ChatScheduleTimeScreen.swift | 94 +++++---- .../Sources/MessagePriceItem.swift | 9 +- .../PostSuggestionsSettingsScreen.swift | 3 + .../Settings/BirthdayPickerScreen/BUILD | 2 + .../BirthdayPickerContentComponent.swift | 2 +- .../Sources/BirthdayPickerScreen.swift | 49 +++-- .../Sources/StarsStatisticsScreen.swift | 2 +- ...sTransactionsPanelContainerComponent.swift | 2 +- .../Sources/StarsTransactionsScreen.swift | 2 +- .../Stars/StarsTransferScreen/BUILD | 2 + .../Sources/StarsTransferScreen.swift | 89 ++++----- .../Sources/SharedAccountContext.swift | 52 +++++ 29 files changed, 484 insertions(+), 321 deletions(-) diff --git a/submodules/AccountContext/Sources/AccountContext.swift b/submodules/AccountContext/Sources/AccountContext.swift index 92f3338d2f..fc291ed6c0 100644 --- a/submodules/AccountContext/Sources/AccountContext.swift +++ b/submodules/AccountContext/Sources/AccountContext.swift @@ -909,8 +909,52 @@ public class MediaEditorTransitionOutExternalState { } } -public protocol CameraScreen: ViewController { +public enum CameraScreenMode { + case story + case sticker + case avatar +} + +public final class CameraScreenTransitionIn { + public weak var sourceView: UIView? + public let sourceRect: CGRect + public let sourceCornerRadius: CGFloat + public let useFillAnimation: Bool + public init( + sourceView: UIView, + sourceRect: CGRect, + sourceCornerRadius: CGFloat, + useFillAnimation: Bool + ) { + self.sourceView = sourceView + self.sourceRect = sourceRect + self.sourceCornerRadius = sourceCornerRadius + self.useFillAnimation = useFillAnimation + } +} + +public final class CameraScreenTransitionOut { + public weak var destinationView: UIView? + public let destinationRect: CGRect + public let destinationCornerRadius: CGFloat + public let completion: (() -> Void)? + + public init( + destinationView: UIView, + destinationRect: CGRect, + destinationCornerRadius: CGFloat, + completion: (() -> Void)? = nil + ) { + self.destinationView = destinationView + self.destinationRect = destinationRect + self.destinationCornerRadius = destinationCornerRadius + self.completion = completion + } +} + +public protocol CameraScreen: ViewController { + func returnFromEditor() } public protocol MediaEditorScreen: ViewController { @@ -1330,6 +1374,8 @@ public protocol SharedAccountContext: AnyObject { func makeStickerPackScreen(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)?, mainStickerPack: StickerPackReference, stickerPacks: [StickerPackReference], loadedStickerPacks: [LoadedStickerPack], actionTitle: String?, isEditing: Bool, expandIfNeeded: Bool, parentNavigationController: NavigationController?, sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)?, actionPerformed: ((Bool) -> Void)?) -> ViewController + func makeCameraScreen(context: AccountContext, mode: CameraScreenMode, cameraHolder: Any?, transitionIn: CameraScreenTransitionIn?, transitionOut: @escaping (Bool) -> CameraScreenTransitionOut?, completion: @escaping (Any, @escaping () -> Void) -> Void, transitionedOut: (() -> Void)?) -> ViewController + func makeMediaPickerScreen(context: AccountContext, hasSearch: Bool, completion: @escaping (Any) -> Void) -> ViewController func makeStoryMediaEditorScreen(context: AccountContext, source: Any?, text: String?, link: (url: String, name: String?)?, remainingCount: Int32, completion: @escaping ([MediaEditorScreenResult], MediaEditorTransitionOutExternalState, @escaping (@escaping () -> Void) -> Void) -> Void) -> ViewController diff --git a/submodules/Components/SolidRoundedButtonComponent/Sources/SolidRoundedButtonComponent.swift b/submodules/Components/SolidRoundedButtonComponent/Sources/SolidRoundedButtonComponent.swift index f6630c9ac9..e2b720cb11 100644 --- a/submodules/Components/SolidRoundedButtonComponent/Sources/SolidRoundedButtonComponent.swift +++ b/submodules/Components/SolidRoundedButtonComponent/Sources/SolidRoundedButtonComponent.swift @@ -19,6 +19,7 @@ public final class SolidRoundedButtonComponent: Component { public let height: CGFloat public let cornerRadius: CGFloat public let gloss: Bool + public let glass: Bool public let isEnabled: Bool public let iconName: String? public let animationName: String? @@ -39,6 +40,7 @@ public final class SolidRoundedButtonComponent: Component { height: CGFloat = 48.0, cornerRadius: CGFloat = 24.0, gloss: Bool = false, + glass: Bool = false, isEnabled: Bool = true, iconName: String? = nil, animationName: String? = nil, @@ -58,6 +60,7 @@ public final class SolidRoundedButtonComponent: Component { self.height = height self.cornerRadius = cornerRadius self.gloss = gloss + self.glass = glass self.isEnabled = isEnabled self.iconName = iconName self.animationName = animationName @@ -101,6 +104,9 @@ public final class SolidRoundedButtonComponent: Component { if lhs.gloss != rhs.gloss { return false } + if lhs.glass != rhs.glass { + return false + } if lhs.isEnabled != rhs.isEnabled { return false } diff --git a/submodules/DatePickerNode/Sources/DatePickerNode.swift b/submodules/DatePickerNode/Sources/DatePickerNode.swift index 253b07f92b..5db939985d 100644 --- a/submodules/DatePickerNode/Sources/DatePickerNode.swift +++ b/submodules/DatePickerNode/Sources/DatePickerNode.swift @@ -610,7 +610,12 @@ public final class DatePickerNode: ASDisplayNode { } self.theme = theme - self.backgroundColor = self.theme.backgroundColor + self.backgroundColor = theme.backgroundColor + + self.datePickerBackgroundNode.backgroundColor = theme.backgroundColor + self.monthPickerBackgroundNode.backgroundColor = theme.backgroundColor + self.timePickerBackgroundNode.backgroundColor = theme.backgroundColor + self.monthArrowNode.image = generateSmallArrowImage(color: theme.accentColor) self.previousButtonNode.setImage(generateNavigationArrowImage(color: theme.accentColor, mirror: true), for: .normal) self.nextButtonNode.setImage(generateNavigationArrowImage(color: theme.accentColor, mirror: false), for: .normal) diff --git a/submodules/InviteLinksUI/Sources/FolderInviteLinkListController.swift b/submodules/InviteLinksUI/Sources/FolderInviteLinkListController.swift index 5aebfeb694..2dd9b16a6c 100644 --- a/submodules/InviteLinksUI/Sources/FolderInviteLinkListController.swift +++ b/submodules/InviteLinksUI/Sources/FolderInviteLinkListController.swift @@ -169,7 +169,7 @@ private enum InviteLinksListEntry: ItemListNodeEntry { case let .mainLinkHeader(text): return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section) case let .mainLink(link, isGenerating): - return ItemListFolderInviteLinkItem(context: arguments.context, presentationData: presentationData, invite: link, count: 0, peers: [], displayButton: true, enableButton: !isGenerating, buttonTitle: presentationData.strings.FolderLinkScreen_LinkActionCopy, secondaryButtonTitle: link != nil ? presentationData.strings.FolderLinkScreen_LinkActionShare : nil, displayImporters: false, buttonColor: nil, sectionId: self.section, style: .blocks, copyAction: { + return ItemListFolderInviteLinkItem(context: arguments.context, presentationData: presentationData, systemStyle: .glass, invite: link, count: 0, peers: [], displayButton: true, enableButton: !isGenerating, buttonTitle: presentationData.strings.FolderLinkScreen_LinkActionCopy, secondaryButtonTitle: link != nil ? presentationData.strings.FolderLinkScreen_LinkActionShare : nil, displayImporters: false, buttonColor: nil, sectionId: self.section, style: .blocks, copyAction: { if let link { arguments.copyLink(link.link) } @@ -197,6 +197,7 @@ private enum InviteLinksListEntry: ItemListNodeEntry { case let .peer(_, peer, isSelected, disabledReasonText): return ItemListPeerItem( presentationData: presentationData, + systemStyle: .glass, dateTimeFormat: PresentationDateTimeFormat(), nameDisplayOrder: presentationData.nameDisplayOrder, context: arguments.context, diff --git a/submodules/InviteLinksUI/Sources/InviteLinkEditController.swift b/submodules/InviteLinksUI/Sources/InviteLinkEditController.swift index ceb9f8df51..2ffe94c99b 100644 --- a/submodules/InviteLinksUI/Sources/InviteLinkEditController.swift +++ b/submodules/InviteLinksUI/Sources/InviteLinkEditController.swift @@ -292,7 +292,7 @@ private enum InviteLinksEditEntry: ItemListNodeEntry { case let .titleHeader(_, text): return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section) case let .title(_, placeholder, value): - return ItemListSingleLineInputItem(context: arguments.context, presentationData: presentationData, title: NSAttributedString(), text: value, placeholder: placeholder, maxLength: 32, sectionId: self.section, textUpdated: { value in + return ItemListSingleLineInputItem(context: arguments.context, presentationData: presentationData, systemStyle: .glass, title: NSAttributedString(), text: value, placeholder: placeholder, maxLength: 32, sectionId: self.section, textUpdated: { value in arguments.updateState { state in var updatedState = state updatedState.title = value @@ -302,7 +302,7 @@ private enum InviteLinksEditEntry: ItemListNodeEntry { case let .titleInfo(_, text): return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section) case let .subscriptionFeeToggle(_, text, value, enabled): - return ItemListSwitchItem(presentationData: presentationData, title: text, value: value, enabled: enabled, sectionId: self.section, style: .blocks, updated: { value in + return ItemListSwitchItem(presentationData: presentationData, systemStyle: .glass, title: text, value: value, enabled: enabled, sectionId: self.section, style: .blocks, updated: { value in arguments.updateState { state in var updatedState = state updatedState.subscriptionEnabled = value @@ -325,7 +325,7 @@ private enum InviteLinksEditEntry: ItemListNodeEntry { title.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: 0, file: nil, custom: .stars(tinted: false)), range: NSRange(range, in: title.string)) title.addAttribute(.baselineOffset, value: -1.0, range: NSRange(range, in: title.string)) } - return ItemListSingleLineInputItem(context: arguments.context, presentationData: presentationData, title: title, text: value.flatMap { "\($0)" } ?? "", placeholder: placeholder, label: label, type: .number, spacing: 3.0, enabled: enabled, tag: InviteLinksEditEntryTag.subscriptionFee, sectionId: self.section, textUpdated: { text in + return ItemListSingleLineInputItem(context: arguments.context, presentationData: presentationData, systemStyle: .glass, title: title, text: value.flatMap { "\($0)" } ?? "", placeholder: placeholder, label: label, type: .number, spacing: 3.0, enabled: enabled, tag: InviteLinksEditEntryTag.subscriptionFee, sectionId: self.section, textUpdated: { text in arguments.updateState { state in var updatedState = state if var value = Int64(text).flatMap({ StarsAmount(value: $0, nanos: 0) }) { @@ -343,7 +343,7 @@ private enum InviteLinksEditEntry: ItemListNodeEntry { case let .subscriptionFeeInfo(_, text): return ItemListTextItem(presentationData: presentationData, text: .markdown(text), sectionId: self.section) case let .requestApproval(_, text, value, enabled): - return ItemListSwitchItem(presentationData: presentationData, title: text, value: value, enabled: enabled, sectionId: self.section, style: .blocks, updated: { value in + return ItemListSwitchItem(presentationData: presentationData, systemStyle: .glass, title: text, value: value, enabled: enabled, sectionId: self.section, style: .blocks, updated: { value in arguments.updateState { state in var updatedState = state updatedState.requestApproval = value @@ -373,7 +373,7 @@ private enum InviteLinksEditEntry: ItemListNodeEntry { } else { text = presentationData.strings.InviteLink_Create_TimeLimitExpiryDateNever } - return ItemListDisclosureItem(presentationData: presentationData, title: presentationData.strings.InviteLink_Create_TimeLimitExpiryDate, enabled: enabled, label: text, labelStyle: active ? .coloredText(theme.list.itemAccentColor) : .text, sectionId: self.section, style: .blocks, disclosureStyle: .none, action: { + return ItemListDisclosureItem(presentationData: presentationData, systemStyle: .glass, title: presentationData.strings.InviteLink_Create_TimeLimitExpiryDate, enabled: enabled, label: text, labelStyle: active ? .coloredText(theme.list.itemAccentColor) : .text, sectionId: self.section, style: .blocks, disclosureStyle: .none, action: { arguments.dismissInput() arguments.updateState { state in var updatedState = state @@ -437,7 +437,7 @@ private enum InviteLinksEditEntry: ItemListNodeEntry { } else { text = focused ? "" : presentationData.strings.InviteLink_Create_UsersLimitNumberOfUsersUnlimited } - return ItemListSingleLineInputItem(context: arguments.context, presentationData: presentationData, title: NSAttributedString(string: presentationData.strings.InviteLink_Create_UsersLimitNumberOfUsers, textColor: theme.list.itemPrimaryTextColor), text: text, placeholder: "", type: .number, alignment: .right, enabled: enabled, selectAllOnFocus: true, secondaryStyle: !customValue, tag: InviteLinksEditEntryTag.usage, sectionId: self.section, textUpdated: { updatedText in + return ItemListSingleLineInputItem(context: arguments.context, presentationData: presentationData, systemStyle: .glass, title: NSAttributedString(string: presentationData.strings.InviteLink_Create_UsersLimitNumberOfUsers, textColor: theme.list.itemPrimaryTextColor), text: text, placeholder: "", type: .number, alignment: .right, enabled: enabled, selectAllOnFocus: true, secondaryStyle: !customValue, tag: InviteLinksEditEntryTag.usage, sectionId: self.section, textUpdated: { updatedText in arguments.updateState { state in var updatedState = state if updatedText.isEmpty { @@ -472,7 +472,7 @@ private enum InviteLinksEditEntry: ItemListNodeEntry { case let .usageInfo(_, text): return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section) case let .revoke(_, text): - return ItemListActionItem(presentationData: presentationData, title: text, kind: .destructive, alignment: .center, sectionId: self.section, style: .blocks, action: { + return ItemListActionItem(presentationData: presentationData, systemStyle: .glass, title: text, kind: .destructive, alignment: .center, sectionId: self.section, style: .blocks, action: { arguments.revoke() }, tag: nil) } diff --git a/submodules/InviteLinksUI/Sources/ItemListFolderInviteLinkItem.swift b/submodules/InviteLinksUI/Sources/ItemListFolderInviteLinkItem.swift index 9691ecd2d6..e7851d06bb 100644 --- a/submodules/InviteLinksUI/Sources/ItemListFolderInviteLinkItem.swift +++ b/submodules/InviteLinksUI/Sources/ItemListFolderInviteLinkItem.swift @@ -28,6 +28,7 @@ private func actionButtonImage(color: UIColor) -> UIImage? { public class ItemListFolderInviteLinkItem: ListViewItem, ItemListItem { let context: AccountContext let presentationData: ItemListPresentationData + let systemStyle: ItemListSystemStyle let invite: ExportedChatFolderLink? let count: Int32 let peers: [EnginePeer] @@ -49,6 +50,7 @@ public class ItemListFolderInviteLinkItem: ListViewItem, ItemListItem { public init( context: AccountContext, presentationData: ItemListPresentationData, + systemStyle: ItemListSystemStyle = .legacy, invite: ExportedChatFolderLink?, count: Int32, peers: [EnginePeer], @@ -69,6 +71,7 @@ public class ItemListFolderInviteLinkItem: ListViewItem, ItemListItem { ) { self.context = context self.presentationData = presentationData + self.systemStyle = systemStyle self.invite = invite self.count = count self.peers = peers @@ -339,7 +342,7 @@ public class ItemListFolderInviteLinkItemNode: ListViewItemNode, ItemListItemNod let verticalInset: CGFloat = 16.0 let fieldHeight: CGFloat = 52.0 let fieldSpacing: CGFloat = 16.0 - let buttonHeight: CGFloat = 50.0 + let buttonHeight: CGFloat = 52.0 var height = verticalInset * 2.0 + fieldHeight + fieldSpacing + buttonHeight + 54.0 @@ -379,7 +382,7 @@ public class ItemListFolderInviteLinkItemNode: ListViewItemNode, ItemListItemNod strongSelf.topStripeNode.backgroundColor = itemSeparatorColor strongSelf.bottomStripeNode.backgroundColor = itemSeparatorColor strongSelf.backgroundNode.backgroundColor = itemBackgroundColor - strongSelf.fieldNode.image = generateStretchableFilledCircleImage(diameter: 18.0, color: item.presentationData.theme.list.itemInputField.backgroundColor) + strongSelf.fieldNode.image = generateStretchableFilledCircleImage(diameter: 26.0, color: item.presentationData.theme.list.itemInputField.backgroundColor) strongSelf.addressButtonIconNode.image = actionButtonImage(color: item.presentationData.theme.list.itemInputField.controlColor) } @@ -436,7 +439,7 @@ public class ItemListFolderInviteLinkItemNode: ListViewItemNode, ItemListItemNod strongSelf.bottomStripeNode.isHidden = hasCorners } - strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.presentationData.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil + strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.presentationData.theme, top: hasTopCorners, bottom: hasBottomCorners, glass: item.systemStyle == .glass) : nil strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight))) strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0) @@ -454,7 +457,7 @@ public class ItemListFolderInviteLinkItemNode: ListViewItemNode, ItemListItemNod strongSelf.addressButtonNode.frame = strongSelf.containerNode.bounds strongSelf.referenceContainerNode.frame = strongSelf.containerNode.bounds strongSelf.addressButtonIconNode.frame = strongSelf.containerNode.bounds - + let shareButtonNode: SolidRoundedButtonNode if let currentShareButtonNode = strongSelf.shareButtonNode { shareButtonNode = currentShareButtonNode @@ -465,7 +468,7 @@ public class ItemListFolderInviteLinkItemNode: ListViewItemNode, ItemListItemNod } else { buttonTheme = SolidRoundedButtonTheme(theme: item.presentationData.theme) } - shareButtonNode = SolidRoundedButtonNode(theme: buttonTheme, height: 50.0, cornerRadius: 11.0) + shareButtonNode = SolidRoundedButtonNode(theme: buttonTheme, glass: item.systemStyle == .glass, height: buttonHeight, cornerRadius: buttonHeight * 0.5) shareButtonNode.pressed = { [weak self] in self?.item?.shareAction?() } @@ -485,7 +488,7 @@ public class ItemListFolderInviteLinkItemNode: ListViewItemNode, ItemListItemNod } else { buttonTheme = SolidRoundedButtonTheme(theme: item.presentationData.theme) } - secondaryButtonNode = SolidRoundedButtonNode(theme: buttonTheme, height: 50.0, cornerRadius: 11.0) + secondaryButtonNode = SolidRoundedButtonNode(theme: buttonTheme, glass: item.systemStyle == .glass, height: buttonHeight, cornerRadius: buttonHeight * 0.5) secondaryButtonNode.pressed = { [weak self] in self?.item?.secondaryAction?() } diff --git a/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift b/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift index 3f8a3d13fe..b59c8fe046 100644 --- a/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift +++ b/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift @@ -2649,18 +2649,20 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att transition.updateTransformScale(node: self.moreButtonNode.iconNode, scale: moreIsVisible ? 1.0 : 0.1) } - if case .assets(_, .story) = self.subject, self.selectionCount > 0 { - let text = self.presentationData.strings.MediaPicker_CreateStory(self.selectionCount) - self.mainButtonStatePromise.set(.single(AttachmentMainButtonState(text: text, badge: nil, font: .bold, background: .color(self.presentationData.theme.actionSheet.controlAccentColor), textColor: self.presentationData.theme.list.itemCheckColors.foregroundColor, isVisible: true, progress: .none, isEnabled: true, hasShimmer: false, position: .top))) - - if self.selectionCount > 1 && self.selectionCount <= 6 { - self.secondaryButtonStatePromise.set(.single(AttachmentMainButtonState(text: self.presentationData.strings.MediaPicker_CombineIntoCollage, badge: nil, font: .regular, background: .color(.clear), textColor: self.presentationData.theme.actionSheet.controlAccentColor, isVisible: true, progress: .none, isEnabled: true, hasShimmer: false, iconName: "Media Editor/Collage", smallSpacing: true, position: .bottom))) + if case .assets(_, .story) = self.subject { + if self.selectionCount > 0 { + let text = self.presentationData.strings.MediaPicker_CreateStory(self.selectionCount) + self.mainButtonStatePromise.set(.single(AttachmentMainButtonState(text: text, badge: nil, font: .bold, background: .color(self.presentationData.theme.actionSheet.controlAccentColor), textColor: self.presentationData.theme.list.itemCheckColors.foregroundColor, isVisible: true, progress: .none, isEnabled: true, hasShimmer: false, position: .top))) + + if self.selectionCount > 1 && self.selectionCount <= 6 { + self.secondaryButtonStatePromise.set(.single(AttachmentMainButtonState(text: self.presentationData.strings.MediaPicker_CombineIntoCollage, badge: nil, font: .regular, background: .color(.clear), textColor: self.presentationData.theme.actionSheet.controlAccentColor, isVisible: true, progress: .none, isEnabled: true, hasShimmer: false, iconName: "Media Editor/Collage", smallSpacing: true, position: .bottom))) + } else { + self.secondaryButtonStatePromise.set(.single(nil)) + } } else { + self.mainButtonStatePromise.set(.single(nil)) self.secondaryButtonStatePromise.set(.single(nil)) } - } else { - self.mainButtonStatePromise.set(.single(nil)) - self.secondaryButtonStatePromise.set(.single(nil)) } } @@ -3716,46 +3718,47 @@ public func stickerMediaPickerController( } mediaPickerController.openCamera = { [weak controller] cameraHolder in let _ = controller -// guard let cameraHolder = cameraHolder as? CameraHolder else { -// return -// } -// -// var returnToCameraImpl: (() -> Void)? -// let cameraScreen = CameraScreenImpl( -// context: context, -// mode: .sticker, -// holder: cameraHolder, -// transitionIn: CameraScreenImpl.TransitionIn( -// sourceView: cameraHolder.parentView, -// sourceRect: cameraHolder.parentView.bounds, -// sourceCornerRadius: 0.0, -// useFillAnimation: false -// ), -// transitionOut: { _ in -// return CameraScreenImpl.TransitionOut( -// destinationView: cameraHolder.parentView, -// destinationRect: cameraHolder.parentView.bounds, -// destinationCornerRadius: 0.0 -// ) -// }, -// completion: { result, _, _, commit in -// completion(result, nil, .zero, nil, true, { _ in return nil }, { -// returnToCameraImpl?() -// }) -// } -// ) -// cameraScreen.transitionedOut = { [weak cameraHolder] in -// if let cameraHolder { -// cameraHolder.restore() -// } -// } -// controller?.push(cameraScreen) -// -// returnToCameraImpl = { [weak cameraScreen] in -// if let cameraScreen { -// cameraScreen.returnFromEditor() -// } -// } + guard let cameraHolder = cameraHolder as? CameraHolder else { + return + } + + var returnToCameraImpl: (() -> Void)? + + let cameraScreen = context.sharedContext.makeCameraScreen( + context: context, + mode: .sticker, + cameraHolder: cameraHolder, + transitionIn: CameraScreenTransitionIn( + sourceView: cameraHolder.parentView, + sourceRect: cameraHolder.parentView.bounds, + sourceCornerRadius: 0.0, + useFillAnimation: false + ), + transitionOut: { _ in + return CameraScreenTransitionOut( + destinationView: cameraHolder.parentView, + destinationRect: cameraHolder.parentView.bounds, + destinationCornerRadius: 0.0 + ) + }, + completion: { result, commit in + completion(result, nil, .zero, nil, true, { _ in return nil }, { + returnToCameraImpl?() + }) + }, + transitionedOut: { [weak cameraHolder] in + if let cameraHolder { + cameraHolder.restore() + } + } + ) + controller?.push(cameraScreen) + + returnToCameraImpl = { [weak cameraScreen] in + if let cameraScreen = cameraScreen as? CameraScreen { + cameraScreen.returnFromEditor() + } + } } present(mediaPickerController, mediaPickerController.mediaPickerContext) } @@ -3844,46 +3847,47 @@ public func avatarMediaPickerController( } mediaPickerController.openCamera = { [weak controller] cameraHolder in let _ = controller -// guard let cameraHolder = cameraHolder as? CameraHolder else { -// return -// } -// -// var returnToCameraImpl: (() -> Void)? -// let cameraScreen = CameraScreenImpl( -// context: context, -// mode: .avatar, -// holder: cameraHolder, -// transitionIn: CameraScreenImpl.TransitionIn( -// sourceView: cameraHolder.parentView, -// sourceRect: cameraHolder.parentView.bounds, -// sourceCornerRadius: 0.0, -// useFillAnimation: false -// ), -// transitionOut: { _ in -// return CameraScreenImpl.TransitionOut( -// destinationView: cameraHolder.parentView, -// destinationRect: cameraHolder.parentView.bounds, -// destinationCornerRadius: 0.0 -// ) -// }, -// completion: { result, _, _, commit in -// completion(result, nil, .zero, nil, true, { _ in return nil }, { -// returnToCameraImpl?() -// }) -// } -// ) -// cameraScreen.transitionedOut = { [weak cameraHolder] in -// if let cameraHolder { -// cameraHolder.restore() -// } -// } -// controller?.push(cameraScreen) -// -// returnToCameraImpl = { [weak cameraScreen] in -// if let cameraScreen { -// cameraScreen.returnFromEditor() -// } -// } + guard let cameraHolder = cameraHolder as? CameraHolder else { + return + } + + var returnToCameraImpl: (() -> Void)? + + let cameraScreen = context.sharedContext.makeCameraScreen( + context: context, + mode: .avatar, + cameraHolder: cameraHolder, + transitionIn: CameraScreenTransitionIn( + sourceView: cameraHolder.parentView, + sourceRect: cameraHolder.parentView.bounds, + sourceCornerRadius: 0.0, + useFillAnimation: false + ), + transitionOut: { _ in + return CameraScreenTransitionOut( + destinationView: cameraHolder.parentView, + destinationRect: cameraHolder.parentView.bounds, + destinationCornerRadius: 0.0 + ) + }, + completion: { result, commit in + completion(result, nil, .zero, nil, true, { _ in return nil }, { + returnToCameraImpl?() + }) + }, + transitionedOut: { [weak cameraHolder] in + if let cameraHolder { + cameraHolder.restore() + } + } + ) + controller?.push(cameraScreen) + + returnToCameraImpl = { [weak cameraScreen] in + if let cameraScreen = cameraScreen as? CameraScreen { + cameraScreen.returnFromEditor() + } + } } present(mediaPickerController, mediaPickerController.mediaPickerContext) } diff --git a/submodules/PremiumUI/BUILD b/submodules/PremiumUI/BUILD index 6254850f9e..a1eb569162 100644 --- a/submodules/PremiumUI/BUILD +++ b/submodules/PremiumUI/BUILD @@ -121,6 +121,7 @@ swift_library( "//submodules/TelegramUI/Components/ScrollComponent", "//submodules/TelegramUI/Components/Premium/PremiumStarComponent", "//submodules/TelegramUI/Components/Premium/PremiumCoinComponent", + "//submodules/TelegramUI/Components/GlassBarButtonComponent", ], visibility = [ "//visibility:public", diff --git a/submodules/PremiumUI/Sources/PremiumDemoScreen.swift b/submodules/PremiumUI/Sources/PremiumDemoScreen.swift index 5d5771dc07..9ff8e1b6b8 100644 --- a/submodules/PremiumUI/Sources/PremiumDemoScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumDemoScreen.swift @@ -17,6 +17,7 @@ import SolidRoundedButtonComponent import BlurredBackgroundComponent import Markdown import TelegramUIPreferences +import GlassBarButtonComponent public final class PremiumGradientBackgroundComponent: Component { public let colors: [UIColor] @@ -519,7 +520,6 @@ private final class DemoSheetContent: CombinedComponent { final class State: ComponentState { private let context: AccountContext - var cachedCloseImage: UIImage? var isPremium: Bool? var reactions: [AvailableReactions.Reaction]? @@ -682,7 +682,7 @@ private final class DemoSheetContent: CombinedComponent { } static var body: Body { - let closeButton = Child(Button.self) + let closeButton = Child(GlassBarButtonComponent.self) let background = Child(PremiumGradientBackgroundComponent.self) let pager = Child(DemoPagerComponent.self) let button = Child(SolidRoundedButtonComponent.self) @@ -695,9 +695,7 @@ private final class DemoSheetContent: CombinedComponent { let strings = environment.strings let state = context.state - - let sideInset: CGFloat = 16.0 + environment.safeInsets.left - + let background = background.update( component: PremiumGradientBackgroundComponent(colors: [ UIColor(rgb: 0x0077ff), @@ -711,15 +709,7 @@ private final class DemoSheetContent: CombinedComponent { context.add(background .position(CGPoint(x: context.availableSize.width / 2.0, y: background.size.height / 2.0)) ) - - let closeImage: UIImage - if let image = state.cachedCloseImage { - closeImage = image - } else { - closeImage = generateCloseButtonImage(backgroundColor: .clear, foregroundColor: UIColor(rgb: 0xffffff))! - state.cachedCloseImage = closeImage - } - + var isStandalone = false if case .other = component.source { isStandalone = true @@ -1140,38 +1130,30 @@ private final class DemoSheetContent: CombinedComponent { .position(CGPoint(x: context.availableSize.width / 2.0, y: pager.size.height / 2.0)) ) } - + let closeButton = closeButton.update( - component: Button( - content: AnyComponent(ZStack([ - AnyComponentWithIdentity( - id: "background", - component: AnyComponent( - BlurredBackgroundComponent( - color: UIColor(rgb: 0x888888, alpha: 0.1) - ) - ) - ), - AnyComponentWithIdentity( - id: "icon", - component: AnyComponent( - Image(image: closeImage) - ) - ), - ])), - action: { [weak component] in - component?.dismiss() + component: GlassBarButtonComponent( + size: CGSize(width: 40.0, height: 40.0), + backgroundColor: theme.rootController.navigationBar.glassBarButtonBackgroundColor, + isDark: theme.overallDarkAppearance, + state: .glass, + component: AnyComponentWithIdentity(id: "close", component: AnyComponent( + BundleIconComponent( + name: "Navigation/Close", + tintColor: theme.rootController.navigationBar.glassBarButtonForegroundColor + ) + )), + action: { _ in + component.dismiss() } ), - availableSize: CGSize(width: 30.0, height: 30.0), + availableSize: CGSize(width: 40.0, height: 40.0), transition: .immediate ) context.add(closeButton - .position(CGPoint(x: context.availableSize.width - environment.safeInsets.left - closeButton.size.width, y: 28.0)) - .clipsToBounds(true) - .cornerRadius(15.0) + .position(CGPoint(x: 16.0 + closeButton.size.width / 2.0, y: 16.0 + closeButton.size.height / 2.0)) ) - + var measuredTextHeight: CGFloat? var text: String switch component.subject { @@ -1309,6 +1291,7 @@ private final class DemoSheetContent: CombinedComponent { } } + let bottomInsets = ContainerViewLayout.concentricInsets(bottomInset: environment.safeInsets.bottom, innerDiameter: 52.0, sideInset: 30.0) let button = button.update( component: SolidRoundedButtonComponent( title: buttonText, @@ -1324,9 +1307,10 @@ private final class DemoSheetContent: CombinedComponent { ), font: .bold, fontSize: 17.0, - height: 50.0, - cornerRadius: 11.0, + height: 52.0, + cornerRadius: 26.0, gloss: state.isPremium != true, + glass: true, animationName: isStandalone ? buttonAnimationName : nil, iconPosition: .right, iconSpacing: 4.0, @@ -1340,7 +1324,7 @@ private final class DemoSheetContent: CombinedComponent { } } ), - availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0, height: 50.0), + availableSize: CGSize(width: context.availableSize.width - bottomInsets.left - bottomInsets.right, height: 52.0), transition: context.transition ) @@ -1358,19 +1342,12 @@ private final class DemoSheetContent: CombinedComponent { } } - let buttonFrame = CGRect(origin: CGPoint(x: sideInset, y: contentHeight + 20.0), size: button.size) + let buttonFrame = CGRect(origin: CGPoint(x: bottomInsets.left, y: contentHeight + 20.0), size: button.size) context.add(button .position(CGPoint(x: buttonFrame.midX, y: buttonFrame.midY)) ) - - let bottomPanelPadding: CGFloat = 12.0 - let bottomInset: CGFloat - if case .regular = environment.metrics.widthClass { - bottomInset = bottomPanelPadding - } else { - bottomInset = environment.safeInsets.bottom > 0.0 ? environment.safeInsets.bottom + 5.0 : bottomPanelPadding - } - return CGSize(width: context.availableSize.width, height: buttonFrame.maxY + bottomInset) + + return CGSize(width: context.availableSize.width, height: buttonFrame.maxY + bottomInsets.bottom) } } } @@ -1428,6 +1405,7 @@ private final class DemoSheetComponent: CombinedComponent { }) } )), + style: .glass, backgroundColor: .color(environment.theme.actionSheet.opaqueItemBackgroundColor), followContentSizeChanges: context.component.source == .other, animateOut: animateOut diff --git a/submodules/PremiumUI/Sources/PremiumLimitScreen.swift b/submodules/PremiumUI/Sources/PremiumLimitScreen.swift index e466e69b27..e3ff83a2f8 100644 --- a/submodules/PremiumUI/Sources/PremiumLimitScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumLimitScreen.swift @@ -20,6 +20,7 @@ import AvatarNode import TextFormat import RoundedRectWithTailPath import PremiumPeerShortcutComponent +import GlassBarButtonComponent func generateCloseButtonImage(backgroundColor: UIColor, foregroundColor: UIColor) -> UIImage? { return generateImage(CGSize(width: 30.0, height: 30.0), contextGenerator: { size, context in @@ -177,7 +178,7 @@ public class PremiumLimitDisplayComponent: Component { override init(frame: CGRect) { self.container = UIView() self.container.clipsToBounds = true - self.container.layer.cornerRadius = 6.0 + self.container.layer.cornerRadius = 15.0 self.inactiveBackground = SimpleLayer() @@ -783,7 +784,6 @@ private final class LimitSheetContent: CombinedComponent { var myBoostCount: Int32 = 0 - var cachedCloseImage: (UIImage, PresentationTheme)? var cachedChevronImage: (UIImage, PresentationTheme)? init(context: AccountContext, subject: PremiumLimitScreen.Subject) { @@ -819,7 +819,7 @@ private final class LimitSheetContent: CombinedComponent { } static var body: Body { - let closeButton = Child(Button.self) + let closeButton = Child(GlassBarButtonComponent.self) let title = Child(MultilineTextComponent.self) let text = Child(BalancedTextComponent.self) let alternateText = Child(List.self) @@ -854,27 +854,29 @@ private final class LimitSheetContent: CombinedComponent { let sideInset: CGFloat = 16.0 + environment.safeInsets.left let textSideInset: CGFloat = 32.0 + environment.safeInsets.left - let closeImage: UIImage - if let (image, theme) = state.cachedCloseImage, theme === environment.theme { - closeImage = image - } else { - closeImage = generateCloseButtonImage(backgroundColor: UIColor(rgb: 0x808084, alpha: 0.1), foregroundColor: theme.actionSheet.inputClearButtonColor)! - state.cachedCloseImage = (closeImage, theme) - } - + let closeButton = closeButton.update( - component: Button( - content: AnyComponent(Image(image: closeImage)), - action: { [weak component] in - component?.dismiss() - component?.cancel() + component: GlassBarButtonComponent( + size: CGSize(width: 40.0, height: 40.0), + backgroundColor: theme.rootController.navigationBar.glassBarButtonBackgroundColor, + isDark: theme.overallDarkAppearance, + state: .generic, + component: AnyComponentWithIdentity(id: "close", component: AnyComponent( + BundleIconComponent( + name: "Navigation/Close", + tintColor: theme.rootController.navigationBar.glassBarButtonForegroundColor + ) + )), + action: { _ in + component.dismiss() + component.cancel() } ), - availableSize: CGSize(width: 30.0, height: 30.0), + availableSize: CGSize(width: 40.0, height: 40.0), transition: .immediate ) context.add(closeButton - .position(CGPoint(x: context.availableSize.width - environment.safeInsets.left - closeButton.size.width, y: 28.0)) + .position(CGPoint(x: 16.0 + closeButton.size.width / 2.0, y: 16.0 + closeButton.size.height / 2.0)) ) var boostUpdated = false @@ -1394,17 +1396,6 @@ private final class LimitSheetContent: CombinedComponent { availableSize: CGSize(width: context.availableSize.width - textSideInset * 2.0, height: context.availableSize.height), transition: .immediate ) - -// alternateTextChild = alternateText.update( -// component: BalancedTextComponent( -// text: .markdown(text: string, attributes: markdownAttributes), -// horizontalAlignment: .center, -// maximumNumberOfLines: 0, -// lineSpacing: 0.1 -// ), -// availableSize: CGSize(width: context.availableSize.width - textSideInset * 2.0, height: context.availableSize.height), -// transition: .immediate -// ) } else { textChild = text.update( component: BalancedTextComponent( @@ -1456,6 +1447,8 @@ private final class LimitSheetContent: CombinedComponent { } let isIncreaseButton = !reachedMaximumLimit && !isPremiumDisabled + + let bottomInsets = ContainerViewLayout.concentricInsets(bottomInset: environment.safeInsets.bottom, innerDiameter: 52.0, sideInset: 30.0) let button = button.update( component: SolidRoundedButtonComponent( title: actionButtonText ?? (isIncreaseButton ? strings.Premium_IncreaseLimit : strings.Common_OK), @@ -1466,9 +1459,10 @@ private final class LimitSheetContent: CombinedComponent { ), font: .bold, fontSize: 17.0, - height: 50.0, - cornerRadius: 10.0, + height: 52.0, + cornerRadius: 26.0, gloss: isIncreaseButton && actionButtonHasGloss, + glass: true, iconName: buttonIconName, animationName: isIncreaseButton ? buttonAnimationName : nil, iconPosition: buttonIconName != nil ? .left : .right, @@ -1482,7 +1476,7 @@ private final class LimitSheetContent: CombinedComponent { } } ), - availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0, height: 50.0), + availableSize: CGSize(width: context.availableSize.width - bottomInsets.left - bottomInsets.right, height: 52.0), transition: context.transition ) @@ -1501,20 +1495,20 @@ private final class LimitSheetContent: CombinedComponent { ), font: .regular, fontSize: 17.0, - height: 50.0, - cornerRadius: 10.0, + height: 52.0, + cornerRadius: 26.0, action: { if component.action() { component.dismiss() } } ), - availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0, height: 50.0), + availableSize: CGSize(width: context.availableSize.width - bottomInsets.left - bottomInsets.right, height: 52.0), transition: context.transition ) buttonOffset += 66.0 - let linkFrame = CGRect(origin: CGPoint(x: sideInset, y: textOffset + (textChild?.size ?? .zero).height + 24.0), size: linkButton.size) + let linkFrame = CGRect(origin: CGPoint(x: bottomInsets.left, y: textOffset + (textChild?.size ?? .zero).height + 24.0), size: linkButton.size) context.add(linkButton .position(CGPoint(x: linkFrame.midX, y: linkFrame.midY)) ) @@ -1525,7 +1519,7 @@ private final class LimitSheetContent: CombinedComponent { } context.add(title - .position(CGPoint(x: context.availableSize.width / 2.0, y: 28.0)) + .position(CGPoint(x: context.availableSize.width / 2.0, y: 36.0)) ) var textSize: CGSize @@ -1594,7 +1588,7 @@ private final class LimitSheetContent: CombinedComponent { .position(CGPoint(x: context.availableSize.width / 2.0, y: limit.size.height / 2.0 + 44.0 + topOffset)) ) - let buttonFrame = CGRect(origin: CGPoint(x: sideInset, y: textOffset + ceil(textSize.height / 2.0) + buttonOffset + 24.0), size: button.size) + let buttonFrame = CGRect(origin: CGPoint(x: bottomInsets.left, y: textOffset + ceil(textSize.height / 2.0) + buttonOffset + 24.0), size: button.size) context.add(button .position(CGPoint(x: buttonFrame.midX, y: buttonFrame.midY)) ) @@ -1760,6 +1754,7 @@ private final class LimitSheetComponent: CombinedComponent { openStats: context.component.openStats, openGift: context.component.openGift )), + style: .glass, backgroundColor: .color(environment.theme.actionSheet.opaqueItemBackgroundColor), followContentSizeChanges: true, externalState: sheetExternalState, diff --git a/submodules/TelegramCore/Sources/Suggestions.swift b/submodules/TelegramCore/Sources/Suggestions.swift index bb88bb98c9..e9f2866608 100644 --- a/submodules/TelegramCore/Sources/Suggestions.swift +++ b/submodules/TelegramCore/Sources/Suggestions.swift @@ -18,6 +18,8 @@ public enum ServerProvidedSuggestion: Equatable { case gracePremium case starsSubscriptionLowBalance case setupPhoto + case setupLoginEmail + case setupLoginEmailBlocking case link(id: String, url: String, title: ServerSuggestionInfo.Item.Text, subtitle: ServerSuggestionInfo.Item.Text) init?(string: String) { @@ -50,6 +52,10 @@ public enum ServerProvidedSuggestion: Equatable { self = .starsSubscriptionLowBalance case "USERPIC_SETUP": self = .setupPhoto + case "SETUP_LOGIN_EMAIL": + self = .setupLoginEmail + case "SETUP_LOGIN_EMAIL_NOSKIP": + self = .setupLoginEmailBlocking default: return nil } @@ -85,6 +91,10 @@ public enum ServerProvidedSuggestion: Equatable { return "STARS_SUBSCRIPTION_LOW_BALANCE" case .setupPhoto: return "USERPIC_SETUP" + case .setupLoginEmail: + return "SETUP_LOGIN_EMAIL" + case .setupLoginEmailBlocking: + return "SETUP_LOGIN_EMAIL_NOSKIP" case let .link(id, _, _, _): return id } diff --git a/submodules/TelegramUI/Components/AdminUserActionsSheet/BUILD b/submodules/TelegramUI/Components/AdminUserActionsSheet/BUILD index d6ef632670..ab1b9a45f7 100644 --- a/submodules/TelegramUI/Components/AdminUserActionsSheet/BUILD +++ b/submodules/TelegramUI/Components/AdminUserActionsSheet/BUILD @@ -19,6 +19,7 @@ swift_library( "//submodules/Components/ViewControllerComponent", "//submodules/Components/ComponentDisplayAdapters", "//submodules/Components/MultilineTextComponent", + "//submodules/Components/BundleIconComponent", "//submodules/TelegramPresentationData", "//submodules/AccountContext", "//submodules/AppBundle", @@ -30,6 +31,7 @@ swift_library( "//submodules/TelegramUI/Components/ListSectionComponent", "//submodules/TelegramUI/Components/ListActionItemComponent", "//submodules/TelegramUI/Components/PlainButtonComponent", + "//submodules/TelegramUI/Components/GlassBarButtonComponent", ], visibility = [ "//visibility:public", diff --git a/submodules/TelegramUI/Components/AdminUserActionsSheet/Sources/AdminUserActionsPeerComponent.swift b/submodules/TelegramUI/Components/AdminUserActionsSheet/Sources/AdminUserActionsPeerComponent.swift index 9ef7002203..69bab1e9b0 100644 --- a/submodules/TelegramUI/Components/AdminUserActionsSheet/Sources/AdminUserActionsPeerComponent.swift +++ b/submodules/TelegramUI/Components/AdminUserActionsSheet/Sources/AdminUserActionsPeerComponent.swift @@ -159,7 +159,7 @@ final class AdminUserActionsPeerComponent: Component { let contextInset: CGFloat = 0.0 - let height: CGFloat = 44.0 + let height: CGFloat = 52.0 let verticalInset: CGFloat = 1.0 let leftInset: CGFloat = 30.0 + component.sideInset var rightInset: CGFloat = contextInset * 2.0 + 8.0 + component.sideInset diff --git a/submodules/TelegramUI/Components/AdminUserActionsSheet/Sources/RecentActionsSettingsSheet.swift b/submodules/TelegramUI/Components/AdminUserActionsSheet/Sources/RecentActionsSettingsSheet.swift index b6a138bce9..a6dbc7f462 100644 --- a/submodules/TelegramUI/Components/AdminUserActionsSheet/Sources/RecentActionsSettingsSheet.swift +++ b/submodules/TelegramUI/Components/AdminUserActionsSheet/Sources/RecentActionsSettingsSheet.swift @@ -18,6 +18,8 @@ import TelegramStringFormatting import ListSectionComponent import ListActionItemComponent import PlainButtonComponent +import GlassBarButtonComponent +import BundleIconComponent private enum ActionTypeSection: Hashable, CaseIterable { case members @@ -486,19 +488,28 @@ private final class RecentActionsSettingsSheetComponent: Component { let leftButtonSize = self.leftButton.update( transition: transition, - component: AnyComponent(Button( - content: AnyComponent(Text(text: environment.strings.Common_Cancel, font: Font.regular(17.0), color: environment.theme.list.itemAccentColor)), - action: { [weak self] in + component: AnyComponent(GlassBarButtonComponent( + size: CGSize(width: 40.0, height: 40.0), + backgroundColor: environment.theme.rootController.navigationBar.glassBarButtonBackgroundColor, + isDark: environment.theme.overallDarkAppearance, + state: .generic, + component: AnyComponentWithIdentity(id: "close", component: AnyComponent( + BundleIconComponent( + name: "Navigation/Close", + tintColor: environment.theme.rootController.navigationBar.glassBarButtonForegroundColor + ) + )), + action: { [weak self] _ in guard let self, let controller = self.environment?.controller() else { return } controller.dismiss() } - ).minSize(CGSize(width: 44.0, height: 56.0))), + )), environment: {}, - containerSize: CGSize(width: 120.0, height: 100.0) + containerSize: CGSize(width: 40.0, height: 40.0) ) - let leftButtonFrame = CGRect(origin: CGPoint(x: 16.0 + environment.safeInsets.left, y: 0.0), size: leftButtonSize) + let leftButtonFrame = CGRect(origin: CGPoint(x: 16.0 + environment.safeInsets.left, y: 16.0), size: leftButtonSize) if let leftButtonView = self.leftButton.view { if leftButtonView.superview == nil { self.navigationBarContainer.addSubview(leftButtonView) @@ -582,6 +593,7 @@ private final class RecentActionsSettingsSheetComponent: Component { return AnyComponentWithIdentity(id: sectionId, component: AnyComponent(ListActionItemComponent( theme: environment.theme, + style: .glass, title: itemTitle, leftIcon: .check(ListActionItemComponent.LeftIcon.Check( isSelected: selectedCount == totalCount, @@ -661,6 +673,7 @@ private final class RecentActionsSettingsSheetComponent: Component { subItems.append(AnyComponentWithIdentity(id: actionType, component: AnyComponent(ListActionItemComponent( theme: environment.theme, + style: .glass, title: AnyComponent(VStack([ AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(MultilineTextComponent( text: .plain(NSAttributedString( @@ -702,7 +715,7 @@ private final class RecentActionsSettingsSheetComponent: Component { environment: {}, containerSize: CGSize(width: availableSize.width - leftButtonFrame.maxX * 2.0, height: 100.0) ) - let titleFrame = CGRect(origin: CGPoint(x: floor((availableSize.width - titleSize.width) * 0.5), y: floor((54.0 - titleSize.height) * 0.5)), size: titleSize) + let titleFrame = CGRect(origin: CGPoint(x: floor((availableSize.width - titleSize.width) * 0.5), y: floor((72.0 - titleSize.height) * 0.5)), size: titleSize) if let titleView = title.view { if titleView.superview == nil { self.navigationBarContainer.addSubview(titleView) @@ -728,6 +741,7 @@ private final class RecentActionsSettingsSheetComponent: Component { transition: optionsSectionTransition, component: AnyComponent(ListSectionComponent( theme: environment.theme, + style: .glass, header: AnyComponent(MultilineTextComponent( text: .plain(NSAttributedString( string: environment.strings.Channel_AdminLogFilter_FilterActionsTypeTitle, @@ -796,6 +810,7 @@ private final class RecentActionsSettingsSheetComponent: Component { } adminsSectionItems.append(AnyComponentWithIdentity(id: adminsSectionItems.count, component: AnyComponent(ListActionItemComponent( theme: environment.theme, + style: .glass, title: AnyComponent(VStack([ AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(MultilineTextComponent( text: .plain(NSAttributedString( @@ -828,6 +843,7 @@ private final class RecentActionsSettingsSheetComponent: Component { transition: transition, component: AnyComponent(ListSectionComponent( theme: environment.theme, + style: .glass, header: AnyComponent(MultilineTextComponent( text: .plain(NSAttributedString( string: environment.strings.Channel_AdminLogFilter_FilterActionsAdminsTitle, @@ -854,10 +870,12 @@ private final class RecentActionsSettingsSheetComponent: Component { contentHeight += 30.0 + let bottomInsets = ContainerViewLayout.concentricInsets(bottomInset: environment.safeInsets.bottom, innerDiameter: 52.0, sideInset: 30.0) let actionButtonSize = self.actionButton.update( transition: transition, component: AnyComponent(ButtonComponent( background: ButtonComponent.Background( + style: .glass, color: environment.theme.list.itemCheckColors.fillColor, foreground: environment.theme.list.itemCheckColors.foregroundColor, pressedColor: environment.theme.list.itemCheckColors.fillColor.withMultipliedAlpha(0.9) @@ -883,10 +901,10 @@ private final class RecentActionsSettingsSheetComponent: Component { } )), environment: {}, - containerSize: CGSize(width: availableSize.width - sideInset * 2.0, height: 50.0) + containerSize: CGSize(width: availableSize.width - bottomInsets.left - bottomInsets.right, height: 52.0) ) - let bottomPanelHeight = 8.0 + environment.safeInsets.bottom + actionButtonSize.height - let actionButtonFrame = CGRect(origin: CGPoint(x: sideInset, y: availableSize.height - bottomPanelHeight), size: actionButtonSize) + let bottomPanelHeight = actionButtonSize.height + bottomInsets.bottom + let actionButtonFrame = CGRect(origin: CGPoint(x: bottomInsets.left, y: availableSize.height - bottomPanelHeight), size: actionButtonSize) if let actionButtonView = actionButton.view { if actionButtonView.superview == nil { self.addSubview(actionButtonView) diff --git a/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/AvatarEditorScreen.swift b/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/AvatarEditorScreen.swift index 5e6b6f25fd..67727795eb 100644 --- a/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/AvatarEditorScreen.swift +++ b/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/AvatarEditorScreen.swift @@ -226,11 +226,11 @@ final class AvatarEditorScreenComponent: Component { self.backgroundContainerView = UIView() self.backgroundContainerView.clipsToBounds = true - self.backgroundContainerView.layer.cornerRadius = 10.0 + self.backgroundContainerView.layer.cornerRadius = 26.0 self.keyboardContainerView = UIView() self.keyboardContainerView.clipsToBounds = true - self.keyboardContainerView.layer.cornerRadius = 10.0 + self.keyboardContainerView.layer.cornerRadius = 26.0 self.panelBackgroundView = BlurredBackgroundView(color: .white) self.panelHostView = PagerExternalTopPanelContainer() @@ -1317,11 +1317,13 @@ final class AvatarEditorScreenComponent: Component { )))) } + let bottomInsets = ContainerViewLayout.concentricInsets(bottomInset: environment.safeInsets.bottom, innerDiameter: 52.0, sideInset: 30.0) let buttonSize = self.buttonView.update( transition: transition, component: AnyComponent( ButtonComponent( background: ButtonComponent.Background( + style: .glass, color: theme.list.itemCheckColors.fillColor, foreground: theme.list.itemCheckColors.foregroundColor, pressedColor: theme.list.itemCheckColors.fillColor.withMultipliedAlpha(0.8) @@ -1337,13 +1339,13 @@ final class AvatarEditorScreenComponent: Component { ) ), environment: {}, - containerSize: CGSize(width: availableSize.width - sideInset * 2.0, height: 50.0) + containerSize: CGSize(width: availableSize.width - bottomInsets.left - bottomInsets.right, height: 52.0) ) if let buttonView = self.buttonView.view { if buttonView.superview == nil { self.addSubview(buttonView) } - transition.setFrame(view: buttonView, frame: CGRect(origin: CGPoint(x: sideInset, y: contentHeight), size: buttonSize)) + transition.setFrame(view: buttonView, frame: CGRect(origin: CGPoint(x: bottomInsets.left, y: contentHeight), size: buttonSize)) } let bottomPanelFrame = CGRect(origin: CGPoint(x: 0.0, y: contentHeight - 4.0), size: CGSize(width: availableSize.width, height: availableSize.height - contentHeight + 4.0)) diff --git a/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/BackgroundColorComponent.swift b/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/BackgroundColorComponent.swift index dee2b7766f..f6be356b1f 100644 --- a/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/BackgroundColorComponent.swift +++ b/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/BackgroundColorComponent.swift @@ -106,7 +106,7 @@ final class BackgroundColorComponent: Component { var validIds: [AnyHashable] = [] for i in 0 ..< values.count { let position: CGFloat = sideInset + (spacing + itemSize.width) * CGFloat(i) - let itemFrame = CGRect(origin: CGPoint(x: position, y: 10.0), size: itemSize) + let itemFrame = CGRect(origin: CGPoint(x: position, y: 11.0), size: itemSize) var isVisible = false if visibleBounds.intersects(itemFrame) { isVisible = true @@ -171,7 +171,7 @@ final class BackgroundColorComponent: Component { self.component = component self.state = state - let height: CGFloat = 50.0 + let height: CGFloat = 52.0 let size = CGSize(width: availableSize.width, height: height) let scrollFrame = CGRect(origin: .zero, size: size) diff --git a/submodules/TelegramUI/Components/ButtonComponent/Sources/ButtonComponent.swift b/submodules/TelegramUI/Components/ButtonComponent/Sources/ButtonComponent.swift index cbc60c8848..7f32707a42 100644 --- a/submodules/TelegramUI/Components/ButtonComponent/Sources/ButtonComponent.swift +++ b/submodules/TelegramUI/Components/ButtonComponent/Sources/ButtonComponent.swift @@ -617,7 +617,7 @@ public final class ButtonComponent: Component { }) } - if component.background.style == .glass { + if component.background.style == .glass, component.background.color.alpha > 0.9 { let chromeView: UIImageView var chromeTransition = transition if let current = self.chromeView { diff --git a/submodules/TelegramUI/Components/ChatScheduleTimeController/Sources/ChatScheduleTimeScreen.swift b/submodules/TelegramUI/Components/ChatScheduleTimeController/Sources/ChatScheduleTimeScreen.swift index 82a8ff78b6..bf1c3d9b88 100644 --- a/submodules/TelegramUI/Components/ChatScheduleTimeController/Sources/ChatScheduleTimeScreen.swift +++ b/submodules/TelegramUI/Components/ChatScheduleTimeController/Sources/ChatScheduleTimeScreen.swift @@ -21,11 +21,20 @@ private let calendar = Calendar(identifier: .gregorian) private final class ChatScheduleTimeSheetContentComponent: Component { typealias EnvironmentType = ViewControllerComponentContainer.Environment + public class ExternalState { + public fileprivate(set) var repeatValueFrame: CGRect + + public init() { + self.repeatValueFrame = .zero + } + } + let context: AccountContext let mode: ChatScheduleTimeScreen.Mode let currentTime: Int32? let currentRepeatPeriod: Int32? let minimalTime: Int32? + let externalState: ExternalState let dismiss: () -> Void init( @@ -34,6 +43,7 @@ private final class ChatScheduleTimeSheetContentComponent: Component { currentTime: Int32?, currentRepeatPeriod: Int32?, minimalTime: Int32?, + externalState: ExternalState, dismiss: @escaping () -> Void ) { self.context = context @@ -41,6 +51,7 @@ private final class ChatScheduleTimeSheetContentComponent: Component { self.currentTime = currentTime self.currentRepeatPeriod = currentRepeatPeriod self.minimalTime = minimalTime + self.externalState = externalState self.dismiss = dismiss } @@ -133,14 +144,18 @@ private final class ChatScheduleTimeSheetContentComponent: Component { defer { self.isUpdating = false } + let environment = environment[EnvironmentType.self].value + + let themeUpdated = self.environment?.theme != environment.theme + self.environment = environment if self.component == nil { self.updateMinimumDate(currentTime: component.currentTime, minimalTime: component.minimalTime) self.repeatPeriod = component.currentRepeatPeriod } - + self.component = component self.state = state @@ -210,6 +225,10 @@ private final class ChatScheduleTimeSheetContentComponent: Component { let datePicker: DatePickerNode if let current = self.datePicker { datePicker = current + + if themeUpdated { + datePicker.updateTheme(DatePickerTheme(theme: environment.theme)) + } } else { datePicker = DatePickerNode( theme: DatePickerTheme(theme: environment.theme), @@ -588,6 +607,7 @@ private final class ChatScheduleTimeSheetContentComponent: Component { theme: environment.theme, sourceFrame: repeatValueFrame, component: AnyComponent(RepeatMenuComponent( + theme: environment.theme, value: self.repeatPeriod, valueUpdated: { [weak self] value in guard let self, let component = self.component, let environment = self.environment else { @@ -602,13 +622,13 @@ private final class ChatScheduleTimeSheetContentComponent: Component { content: .premiumPaywall( title: "Premium Required", text: "Subscribe to **Telegram Premium** to schedule repeating messages.", - customUndoText: nil, + customUndoText: "Add", timeout: nil, linkAction: nil ), - elevatedLayout: true, + elevatedLayout: false, action: { [weak environment] action in - if case .info = action { + if case .undo = action { var replaceImpl: ((ViewController) -> Void)? let controller = component.context.sharedContext.makePremiumDemoController(context: component.context, subject: .colors, forceDark: false, action: { let controller = component.context.sharedContext.makePremiumIntroController(context: component.context, source: .nameColor, forceDark: false, dismissed: nil) @@ -656,30 +676,7 @@ private final class ChatScheduleTimeSheetContentComponent: Component { }) } - -// if let controller = environment.controller(), !controller.automaticallyControlPresentationContextLayout { -// let sideInset: CGFloat = 0.0 -// let bottomInset: CGFloat = max(environment.safeInsets.bottom, contentHeight) -//// if case .regular = environment.metrics.widthClass { -//// sideInset = floor((context.availableSize.width - 430.0) / 2.0) - 12.0 -//// bottomInset = (context.availableSize.height - sheetExternalState.contentHeight) / 2.0 + sheetExternalState.contentHeight -//// } -// -// let layout = ContainerViewLayout( -// size: availableSize, -// metrics: environment.metrics, -// deviceMetrics: environment.deviceMetrics, -// intrinsicInsets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: bottomInset, right: 0.0), -// safeInsets: UIEdgeInsets(top: 0.0, left: max(sideInset, environment.safeInsets.left), bottom: 0.0, right: max(sideInset, environment.safeInsets.right)), -// additionalInsets: .zero, -// statusBarHeight: environment.statusBarHeight, -// inputHeight: nil, -// inputHeightIsInteractivellyChanging: false, -// inVoiceOver: false -// ) -// controller.presentationContext.containerLayoutUpdated(layout, transition: transition.containedViewLayoutTransition) -// } - + component.externalState.repeatValueFrame = repeatValueFrame return contentSize } @@ -739,6 +736,8 @@ private final class ChatScheduleTimeScreenComponent: Component { final class View: UIView { private let sheet = ComponentView<(ViewControllerComponentContainer.Environment, SheetComponentEnvironment)>() private let sheetAnimateOut = ActionSlot>() + private let sheetExternalState = SheetComponent.ExternalState() + private let contentExternalState = ChatScheduleTimeSheetContentComponent.ExternalState() private var component: ChatScheduleTimeScreenComponent? private var environment: EnvironmentType? @@ -782,6 +781,7 @@ private final class ChatScheduleTimeScreenComponent: Component { currentTime: component.currentTime, currentRepeatPeriod: component.currentRepeatPeriod, minimalTime: component.minimalTime, + externalState: self.contentExternalState, dismiss: { [weak self] in guard let self else { return @@ -796,6 +796,7 @@ private final class ChatScheduleTimeScreenComponent: Component { style: .glass, backgroundColor: .color(environment.theme.actionSheet.opaqueItemBackgroundColor), followContentSizeChanges: true, + externalState: self.sheetExternalState, animateOut: self.sheetAnimateOut )), environment: { @@ -811,6 +812,25 @@ private final class ChatScheduleTimeScreenComponent: Component { transition.setFrame(view: sheetView, frame: CGRect(origin: CGPoint(), size: availableSize)) } + if let controller = environment.controller(), !controller.automaticallyControlPresentationContextLayout { + let sideInset: CGFloat = 20.0 + let bottomInset: CGFloat = self.sheetExternalState.contentHeight - self.contentExternalState.repeatValueFrame.minY + 14.0 + + let layout = ContainerViewLayout( + size: availableSize, + metrics: environment.metrics, + deviceMetrics: environment.deviceMetrics, + intrinsicInsets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: bottomInset, right: 0.0), + safeInsets: UIEdgeInsets(top: 0.0, left: max(sideInset, environment.safeInsets.left), bottom: 0.0, right: max(sideInset, environment.safeInsets.right)), + additionalInsets: .zero, + statusBarHeight: environment.statusBarHeight, + inputHeight: nil, + inputHeightIsInteractivellyChanging: false, + inVoiceOver: false + ) + controller.presentationContext.containerLayoutUpdated(layout, transition: transition.containedViewLayoutTransition) + } + return availableSize } } @@ -860,7 +880,7 @@ public class ChatScheduleTimeScreen: ViewControllerComponentContainer { self.navigationPresentation = .flatModal self.blocksBackgroundWhenInOverlay = true - //self.automaticallyControlPresentationContextLayout = false + self.automaticallyControlPresentationContextLayout = false } required public init(coder aDecoder: NSCoder) { @@ -1148,18 +1168,24 @@ private final class MenuComponent: Component { } private final class RepeatMenuComponent: Component { + let theme: PresentationTheme let value: Int32? let valueUpdated: (Int32?) -> Void init( + theme: PresentationTheme, value: Int32?, valueUpdated: @escaping (Int32?) -> Void ) { + self.theme = theme self.value = value self.valueUpdated = valueUpdated } public static func ==(lhs: RepeatMenuComponent, rhs: RepeatMenuComponent) -> Bool { + if lhs.theme !== rhs.theme { + return false + } if lhs.value != rhs.value { return false } @@ -1205,14 +1231,16 @@ private final class RepeatMenuComponent: Component { let sideInset: CGFloat = 18.0 let itemInset: CGFloat = 60.0 - self.checkIcon.tintColor = .black + let textColor = component.theme.contextMenu.primaryColor + self.checkIcon.tintColor = textColor + let neverSize = self.never.update( transition: transition, component: AnyComponent( PlainButtonComponent( content: AnyComponent( - Text(text: "Never", font: Font.regular(17.0), color: .black) + Text(text: "Never", font: Font.regular(17.0), color: textColor) ), action: { [weak self] in guard let self else { @@ -1277,7 +1305,7 @@ private final class RepeatMenuComponent: Component { component: AnyComponent( PlainButtonComponent( content: AnyComponent( - Text(text: repeatString, font: Font.regular(17.0), color: .black) + Text(text: repeatString, font: Font.regular(17.0), color: textColor) ), action: { [weak self] in guard let self else { @@ -1311,7 +1339,7 @@ private final class RepeatMenuComponent: Component { let size = CGSize(width: itemInset + maxWidth + 40.0, height: originY) - self.separator.backgroundColor = UIColor(rgb: 0xdddddd).cgColor + self.separator.backgroundColor = textColor.withMultipliedAlpha(0.6).cgColor self.separator.frame = CGRect(origin: CGPoint(x: sideInset, y: 62.0), size: CGSize(width: size.width - sideInset * 2.0, height: UIScreenPixel)) return size diff --git a/submodules/TelegramUI/Components/PeerInfo/MessagePriceItem/Sources/MessagePriceItem.swift b/submodules/TelegramUI/Components/PeerInfo/MessagePriceItem/Sources/MessagePriceItem.swift index 82dfe3588d..02aa0262c9 100644 --- a/submodules/TelegramUI/Components/PeerInfo/MessagePriceItem/Sources/MessagePriceItem.swift +++ b/submodules/TelegramUI/Components/PeerInfo/MessagePriceItem/Sources/MessagePriceItem.swift @@ -374,8 +374,8 @@ private class MessagePriceItemNode: ListViewItemNode { let centralLeftText = item.value == 0 ? item.strings.Stars_SendMessage_PriceFree : item.strings.Privacy_Messages_Stars(Int32(clamping: item.value)) - strongSelf.centerLeftTextNode.attributedText = NSAttributedString(string: centralLeftText, font: textFont, textColor: item.openSetCustom != nil ? item.theme.list.itemAccentColor : item.theme.list.itemPrimaryTextColor) - strongSelf.centerRightTextNode.attributedText = NSAttributedString(string: item.price, font: smallTextFont, textColor: item.openSetCustom != nil ? item.theme.list.itemAccentColor.withMultipliedAlpha(0.5) : item.theme.list.itemSecondaryTextColor) + strongSelf.centerLeftTextNode.attributedText = NSAttributedString(string: centralLeftText, font: textFont, textColor: item.openSetCustom != nil && item.isEnabled ? item.theme.list.itemAccentColor : item.theme.list.itemPrimaryTextColor) + strongSelf.centerRightTextNode.attributedText = NSAttributedString(string: item.price, font: smallTextFont, textColor: item.openSetCustom != nil && item.isEnabled ? item.theme.list.itemAccentColor.withMultipliedAlpha(0.5) : item.theme.list.itemSecondaryTextColor) let leftTextSize = strongSelf.leftTextNode.updateLayout(CGSize(width: 100.0, height: 100.0)) let rightTextSize = strongSelf.rightTextNode.updateLayout(CGSize(width: 100.0, height: 100.0)) @@ -402,7 +402,7 @@ private class MessagePriceItemNode: ListViewItemNode { } strongSelf.centerTextButtonBackground.tintColor = item.theme.list.itemAccentColor.withMultipliedAlpha(0.1) - if item.openSetCustom != nil { + if item.openSetCustom != nil && item.isEnabled { strongSelf.centerTextButtonNode.isEnabled = true strongSelf.centerTextButtonBackground.isHidden = false } else { @@ -446,12 +446,13 @@ private class MessagePriceItemNode: ListViewItemNode { } let sideInset: CGFloat = 16.0 - let buttonSize = CGSize(width: params.width - params.leftInset - params.rightInset - sideInset * 2.0, height: 50.0) + let buttonSize = CGSize(width: params.width - params.leftInset - params.rightInset - sideInset * 2.0, height: 52.0) let _ = strongSelf.button.update( transition: .immediate, component: AnyComponent( ButtonComponent( background: ButtonComponent.Background( + style: .glass, color: item.theme.list.itemCheckColors.fillColor, foreground: item.theme.list.itemCheckColors.foregroundColor, pressedColor: item.theme.list.itemCheckColors.fillColor.withMultipliedAlpha(0.9) diff --git a/submodules/TelegramUI/Components/PeerInfo/PostSuggestionsSettingsScreen/Sources/PostSuggestionsSettingsScreen.swift b/submodules/TelegramUI/Components/PeerInfo/PostSuggestionsSettingsScreen/Sources/PostSuggestionsSettingsScreen.swift index 9b525e8a41..18ae438dcf 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PostSuggestionsSettingsScreen/Sources/PostSuggestionsSettingsScreen.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PostSuggestionsSettingsScreen/Sources/PostSuggestionsSettingsScreen.swift @@ -302,6 +302,7 @@ final class PostSuggestionsSettingsScreenComponent: Component { var switchSectionItems: [AnyComponentWithIdentity] = [] switchSectionItems.append(AnyComponentWithIdentity(id: 0, component: AnyComponent(ListActionItemComponent( theme: environment.theme, + style: .glass, title: AnyComponent(VStack([ AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(MultilineTextComponent( text: .plain(NSAttributedString( @@ -326,6 +327,7 @@ final class PostSuggestionsSettingsScreenComponent: Component { transition: transition, component: AnyComponent(ListSectionComponent( theme: environment.theme, + style: .glass, header: nil, footer: nil, items: switchSectionItems @@ -394,6 +396,7 @@ final class PostSuggestionsSettingsScreenComponent: Component { transition: transition, component: AnyComponent(ListSectionComponent( theme: environment.theme, + style: .glass, header: AnyComponent(MultilineTextComponent( text: .plain(NSAttributedString( string: environment.strings.ChannelMessages_PriceSectionTitle, diff --git a/submodules/TelegramUI/Components/Settings/BirthdayPickerScreen/BUILD b/submodules/TelegramUI/Components/Settings/BirthdayPickerScreen/BUILD index aaa4fa02d9..d025efe999 100644 --- a/submodules/TelegramUI/Components/Settings/BirthdayPickerScreen/BUILD +++ b/submodules/TelegramUI/Components/Settings/BirthdayPickerScreen/BUILD @@ -19,6 +19,7 @@ swift_library( "//submodules/Components/ViewControllerComponent", "//submodules/Components/ComponentDisplayAdapters", "//submodules/Components/MultilineTextComponent", + "//submodules/Components/BundleIconComponent", "//submodules/TelegramPresentationData", "//submodules/AccountContext", "//submodules/AppBundle", @@ -26,6 +27,7 @@ swift_library( "//submodules/PresentationDataUtils", "//submodules/TelegramUI/Components/ButtonComponent", "//submodules/TelegramUI/Components/PlainButtonComponent", + "//submodules/TelegramUI/Components/GlassBarButtonComponent", ], visibility = [ "//visibility:public", diff --git a/submodules/TelegramUI/Components/Settings/BirthdayPickerScreen/Sources/BirthdayPickerContentComponent.swift b/submodules/TelegramUI/Components/Settings/BirthdayPickerScreen/Sources/BirthdayPickerContentComponent.swift index f55bb36caf..adc890180d 100644 --- a/submodules/TelegramUI/Components/Settings/BirthdayPickerScreen/Sources/BirthdayPickerContentComponent.swift +++ b/submodules/TelegramUI/Components/Settings/BirthdayPickerScreen/Sources/BirthdayPickerContentComponent.swift @@ -139,7 +139,7 @@ public final class BirthdayPickerContentComponent: Component { let sideInset: CGFloat = 16.0 - var contentHeight: CGFloat = 0.0 + var contentHeight: CGFloat = 8.0 let titleString = NSMutableAttributedString() let titleRawString: String diff --git a/submodules/TelegramUI/Components/Settings/BirthdayPickerScreen/Sources/BirthdayPickerScreen.swift b/submodules/TelegramUI/Components/Settings/BirthdayPickerScreen/Sources/BirthdayPickerScreen.swift index d768b10f40..a1972adc7a 100644 --- a/submodules/TelegramUI/Components/Settings/BirthdayPickerScreen/Sources/BirthdayPickerScreen.swift +++ b/submodules/TelegramUI/Components/Settings/BirthdayPickerScreen/Sources/BirthdayPickerScreen.swift @@ -4,10 +4,12 @@ import Display import ComponentFlow import SwiftSignalKit import ViewControllerComponent +import TelegramCore import AccountContext import SheetComponent import ButtonComponent -import TelegramCore +import GlassBarButtonComponent +import BundleIconComponent private final class BirthdayPickerSheetContentComponent: Component { typealias EnvironmentType = ViewControllerComponentContainer.Environment @@ -116,18 +118,29 @@ private final class BirthdayPickerSheetContentComponent: Component { let cancelSize = self.cancel.update( transition: transition, - component: AnyComponent(Button( - content: AnyComponent(Text(text: environment.strings.Common_Cancel, font: Font.regular(17.0), color: environment.theme.list.itemAccentColor)), - action: { [weak self] in - if let self, let component = self.component { - component.dismiss() + component: AnyComponent( + GlassBarButtonComponent( + size: CGSize(width: 40.0, height: 40.0), + backgroundColor: environment.theme.rootController.navigationBar.glassBarButtonBackgroundColor, + isDark: environment.theme.overallDarkAppearance, + state: .generic, + component: AnyComponentWithIdentity(id: "close", component: AnyComponent( + BundleIconComponent( + name: "Navigation/Close", + tintColor: environment.theme.rootController.navigationBar.glassBarButtonForegroundColor + ) + )), + action: { [weak self] _ in + if let self, let component = self.component { + component.dismiss() + } } - } - ).minSize(CGSize(width: 32.0, height: 32.0))), + ) + ), environment: {}, - containerSize: CGSize(width: availableSize.width, height: 32.0) + containerSize: CGSize(width: 40.0, height: 40.0) ) - let cancelFrame = CGRect(origin: CGPoint(x: sideInset, y: 13.0), size: cancelSize) + let cancelFrame = CGRect(origin: CGPoint(x: 16.0, y: 16.0), size: cancelSize) if let cancelView = self.cancel.view { if cancelView.superview == nil { self.addSubview(cancelView) @@ -145,10 +158,12 @@ private final class BirthdayPickerSheetContentComponent: Component { buttonTitle = environment.strings.SuggestBirthdate_Accept_Action } + let bottomInsets = ContainerViewLayout.concentricInsets(bottomInset: environment.safeInsets.bottom, innerDiameter: 52.0, sideInset: 30.0) let buttonSize = self.button.update( transition: transition, component: AnyComponent(ButtonComponent( background: ButtonComponent.Background( + style: .glass, color: environment.theme.list.itemCheckColors.fillColor, foreground: environment.theme.list.itemCheckColors.foregroundColor, pressedColor: environment.theme.list.itemCheckColors.fillColor.withMultipliedAlpha(0.8) @@ -166,9 +181,9 @@ private final class BirthdayPickerSheetContentComponent: Component { } )), environment: {}, - containerSize: CGSize(width: availableSize.width - sideInset * 2.0, height: 50.0) + containerSize: CGSize(width: availableSize.width - bottomInsets.left - bottomInsets.right, height: 52.0) ) - let buttonFrame = CGRect(origin: CGPoint(x: sideInset, y: contentHeight), size: buttonSize) + let buttonFrame = CGRect(origin: CGPoint(x: bottomInsets.left, y: contentHeight), size: buttonSize) if let buttonView = self.button.view { if buttonView.superview == nil { self.addSubview(buttonView) @@ -176,13 +191,8 @@ private final class BirthdayPickerSheetContentComponent: Component { transition.setFrame(view: buttonView, frame: buttonFrame) } contentHeight += buttonSize.height - - if environment.safeInsets.bottom.isZero { - contentHeight += 16.0 - } else { - contentHeight += environment.safeInsets.bottom + 14.0 - } - + contentHeight += bottomInsets.bottom + return CGSize(width: availableSize.width, height: contentHeight) } } @@ -321,6 +331,7 @@ private final class BirthdayPickerScreenComponent: Component { controller.requestLayout(forceUpdate: true, transition: transition) } )), + style: .glass, backgroundColor: .color(environment.theme.list.plainBackgroundColor), followContentSizeChanges: true, isScrollEnabled: false, diff --git a/submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsStatisticsScreen.swift b/submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsStatisticsScreen.swift index cd3f1be142..e07614b179 100644 --- a/submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsStatisticsScreen.swift +++ b/submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsStatisticsScreen.swift @@ -777,7 +777,7 @@ final class StarsStatisticsScreenComponent: Component { let panelTransition = transition if !panelItems.isEmpty { let panelContainerInset: CGFloat = self.listIsExpanded ? 0.0 : 16.0 - let panelContainerCornerRadius: CGFloat = self.listIsExpanded ? 0.0 : 11.0 + let panelContainerCornerRadius: CGFloat = self.listIsExpanded ? 0.0 : 26.0 let panelContainerSize = self.panelContainer.update( transition: panelTransition, diff --git a/submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsTransactionsPanelContainerComponent.swift b/submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsTransactionsPanelContainerComponent.swift index 89f1e91ccb..adb7f1f3b1 100644 --- a/submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsTransactionsPanelContainerComponent.swift +++ b/submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsTransactionsPanelContainerComponent.swift @@ -640,7 +640,7 @@ final class StarsTransactionsPanelContainerComponent: Component { transition.setFrame(view: self.topPanelBackgroundView, frame: CGRect(origin: .zero, size: topPanelFrame.size)) transition.setFrame(view: self.topPanelMergedBackgroundView, frame: CGRect(origin: .zero, size: topPanelFrame.size)) - transition.setCornerRadius(layer: self.topPanelClippingView.layer, cornerRadius: component.insets.left > 0.0 ? 11.0 : 0.0) + transition.setCornerRadius(layer: self.topPanelClippingView.layer, cornerRadius: component.insets.left > 0.0 ? 26.0 : 0.0) transition.setFrame(layer: self.panelsBackgroundLayer, frame: CGRect(origin: CGPoint(x: component.insets.left, y: topPanelFrame.maxY), size: CGSize(width: containerWidth, height: availableSize.height - topPanelFrame.maxY))) diff --git a/submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsTransactionsScreen.swift b/submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsTransactionsScreen.swift index 421e7f0f50..59362f2987 100644 --- a/submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsTransactionsScreen.swift +++ b/submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsTransactionsScreen.swift @@ -1134,7 +1134,7 @@ final class StarsTransactionsScreenComponent: Component { if !panelItems.isEmpty { let panelContainerInset: CGFloat = self.listIsExpanded ? 0.0 : 16.0 - let panelContainerCornerRadius: CGFloat = self.listIsExpanded ? 0.0 : 11.0 + let panelContainerCornerRadius: CGFloat = self.listIsExpanded ? 0.0 : 26.0 let panelContainerSize = self.panelContainer.update( transition: panelTransition, diff --git a/submodules/TelegramUI/Components/Stars/StarsTransferScreen/BUILD b/submodules/TelegramUI/Components/Stars/StarsTransferScreen/BUILD index ec0043d257..3ce4e6da61 100644 --- a/submodules/TelegramUI/Components/Stars/StarsTransferScreen/BUILD +++ b/submodules/TelegramUI/Components/Stars/StarsTransferScreen/BUILD @@ -20,6 +20,7 @@ swift_library( "//submodules/Components/ComponentDisplayAdapters", "//submodules/Components/MultilineTextComponent", "//submodules/Components/BalancedTextComponent", + "//submodules/Components/BundleIconComponent", "//submodules/TelegramPresentationData", "//submodules/AccountContext", "//submodules/AppBundle", @@ -29,6 +30,7 @@ swift_library( "//submodules/Components/SheetComponent", "//submodules/UndoUI", "//submodules/TelegramUI/Components/ButtonComponent", + "//submodules/TelegramUI/Components/GlassBarButtonComponent", "//submodules/TelegramUI/Components/ListSectionComponent", "//submodules/TelegramUI/Components/ListActionItemComponent", "//submodules/TelegramUI/Components/Stars/StarsImageComponent", diff --git a/submodules/TelegramUI/Components/Stars/StarsTransferScreen/Sources/StarsTransferScreen.swift b/submodules/TelegramUI/Components/Stars/StarsTransferScreen/Sources/StarsTransferScreen.swift index 2659a9cbde..e8957414d3 100644 --- a/submodules/TelegramUI/Components/Stars/StarsTransferScreen/Sources/StarsTransferScreen.swift +++ b/submodules/TelegramUI/Components/Stars/StarsTransferScreen/Sources/StarsTransferScreen.swift @@ -21,6 +21,8 @@ import StarsImageComponent import ConfettiEffect import PremiumPeerShortcutComponent import StarsBalanceOverlayComponent +import GlassBarButtonComponent +import TelegramStringFormatting private final class SheetContent: CombinedComponent { typealias EnvironmentType = ViewControllerComponentContainer.Environment @@ -68,7 +70,6 @@ private final class SheetContent: CombinedComponent { } final class State: ComponentState { - var cachedCloseImage: (UIImage, PresentationTheme)? var cachedStarImage: (UIImage, PresentationTheme)? private let context: AccountContext @@ -263,7 +264,7 @@ private final class SheetContent: CombinedComponent { static var body: Body { let background = Child(RoundedRectangle.self) let star = Child(StarsImageComponent.self) - let closeButton = Child(Button.self) + let closeButton = Child(GlassBarButtonComponent.self) let title = Child(Text.self) let peerShortcut = Child(PremiumPeerShortcutComponent.self) @@ -337,26 +338,30 @@ private final class SheetContent: CombinedComponent { .position(CGPoint(x: context.availableSize.width / 2.0, y: star.size.height / 2.0 - 27.0)) ) - let closeImage: UIImage - if let (image, cacheTheme) = state.cachedCloseImage, theme === cacheTheme { - closeImage = image - } else { - closeImage = generateCloseButtonImage(backgroundColor: UIColor(rgb: 0x808084, alpha: 0.1), foregroundColor: theme.actionSheet.inputClearButtonColor)! - state.cachedCloseImage = (closeImage, theme) - } + let closeButton = closeButton.update( - component: Button( - content: AnyComponent(Image(image: closeImage)), - action: { + component: GlassBarButtonComponent( + size: CGSize(width: 40.0, height: 40.0), + backgroundColor: theme.rootController.navigationBar.glassBarButtonBackgroundColor, + isDark: theme.overallDarkAppearance, + state: .generic, + component: AnyComponentWithIdentity(id: "close", component: AnyComponent( + BundleIconComponent( + name: "Navigation/Close", + tintColor: theme.rootController.navigationBar.glassBarButtonForegroundColor + ) + )), + action: { _ in component.dismiss() } ), - availableSize: CGSize(width: 30.0, height: 30.0), + availableSize: CGSize(width: 40.0, height: 40.0), transition: .immediate ) context.add(closeButton - .position(CGPoint(x: context.availableSize.width - closeButton.size.width, y: 28.0)) + .position(CGPoint(x: 16.0 + closeButton.size.width / 2.0, y: 16.0 + closeButton.size.height / 2.0)) ) + let constrainedTitleWidth = context.availableSize.width - 16.0 * 2.0 @@ -501,13 +506,15 @@ private final class SheetContent: CombinedComponent { availableSize: context.availableSize, transition: .immediate ) + + let smallLabelFont = Font.regular(11.0) + let labelFont = Font.semibold(14.0) + let formattedBalance = formatStarsAmountText(state.balance ?? StarsAmount.zero, dateTimeFormat: environment.dateTimeFormat) + let balanceText = tonAmountAttributedString(formattedBalance, integralFont: labelFont, fractionalFont: smallLabelFont, color: textColor, decimalSeparator: environment.dateTimeFormat.decimalSeparator) + let balanceValue = balanceValue.update( component: MultilineTextComponent( - text: .plain(NSAttributedString( - string: presentationStringsFormattedNumber(state.balance ?? StarsAmount.zero, environment.dateTimeFormat.groupingSeparator), - font: Font.semibold(16.0), - textColor: textColor - )), + text: .plain(balanceText), maximumNumberOfLines: 1 ), availableSize: context.availableSize, @@ -519,15 +526,15 @@ private final class SheetContent: CombinedComponent { transition: .immediate ) - let topBalanceOriginY = 11.0 + let topBalanceOriginY = 19.0 context.add(balanceTitle - .position(CGPoint(x: 16.0 + environment.safeInsets.left + balanceTitle.size.width / 2.0, y: topBalanceOriginY + balanceTitle.size.height / 2.0)) + .position(CGPoint(x: context.availableSize.width - 16.0 - environment.safeInsets.left - balanceTitle.size.width / 2.0, y: topBalanceOriginY + balanceTitle.size.height / 2.0)) ) context.add(balanceIcon - .position(CGPoint(x: 16.0 + environment.safeInsets.left + balanceIcon.size.width / 2.0, y: topBalanceOriginY + balanceTitle.size.height + balanceValue.size.height / 2.0 + 1.0 + UIScreenPixel)) + .position(CGPoint(x: context.availableSize.width - 16.0 - environment.safeInsets.left - balanceIcon.size.width / 2.0 - balanceValue.size.width - 3.0, y: topBalanceOriginY + balanceTitle.size.height + balanceValue.size.height / 2.0 + 1.0 + UIScreenPixel)) ) context.add(balanceValue - .position(CGPoint(x: 16.0 + environment.safeInsets.left + balanceIcon.size.width + 3.0 + balanceValue.size.width / 2.0, y: topBalanceOriginY + balanceTitle.size.height + balanceValue.size.height / 2.0 + 2.0 - UIScreenPixel)) + .position(CGPoint(x: context.availableSize.width - 16.0 - environment.safeInsets.left - balanceValue.size.width / 2.0, y: topBalanceOriginY + balanceTitle.size.height + balanceValue.size.height / 2.0)) ) if state.cachedStarImage == nil || state.cachedStarImage?.1 !== theme { @@ -557,13 +564,15 @@ private final class SheetContent: CombinedComponent { let botTitle = state.botPeer?.compactDisplayTitle ?? "" let invoice = component.invoice let isMedia = !component.extendedMedia.isEmpty + + let buttonSideInset: CGFloat = 30.0 let button = button.update( component: ButtonComponent( background: ButtonComponent.Background( + style: .glass, color: theme.list.itemCheckColors.fillColor, foreground: theme.list.itemCheckColors.foregroundColor, - pressedColor: theme.list.itemCheckColors.fillColor.withMultipliedAlpha(0.9), - cornerRadius: 10.0 + pressedColor: theme.list.itemCheckColors.fillColor.withMultipliedAlpha(0.9) ), content: AnyComponentWithIdentity( id: AnyHashable(0), @@ -650,7 +659,7 @@ private final class SheetContent: CombinedComponent { }) } ), - availableSize: CGSize(width: context.availableSize.width - 16.0 * 2.0, height: 50), + availableSize: CGSize(width: context.availableSize.width - buttonSideInset * 2.0, height: 52), transition: .immediate ) context.add(button @@ -703,7 +712,11 @@ private final class SheetContent: CombinedComponent { ) contentSize.height += info.size.height - contentSize.height += 48.0 + var bottomInset: CGFloat = environment.safeInsets.bottom + if bottomInset < 5.0 { + bottomInset = 8.0 + } + contentSize.height += 4.0 + bottomInset return contentSize } @@ -779,6 +792,7 @@ private final class StarsTransferSheetComponent: CombinedComponent { }) } )), + style: .glass, backgroundColor: .color(environment.theme.list.modalBlocksBackgroundColor), followContentSizeChanges: true, clipsContent: true, @@ -886,24 +900,3 @@ public final class StarsTransferScreen: ViewControllerComponentContainer { } } } - -private func generateCloseButtonImage(backgroundColor: UIColor, foregroundColor: UIColor) -> UIImage? { - return generateImage(CGSize(width: 30.0, height: 30.0), contextGenerator: { size, context in - context.clear(CGRect(origin: CGPoint(), size: size)) - - context.setFillColor(backgroundColor.cgColor) - context.fillEllipse(in: CGRect(origin: CGPoint(), size: size)) - - context.setLineWidth(2.0) - context.setLineCap(.round) - context.setStrokeColor(foregroundColor.cgColor) - - context.move(to: CGPoint(x: 10.0, y: 10.0)) - context.addLine(to: CGPoint(x: 20.0, y: 20.0)) - context.strokePath() - - context.move(to: CGPoint(x: 20.0, y: 10.0)) - context.addLine(to: CGPoint(x: 10.0, y: 20.0)) - context.strokePath() - }) -} diff --git a/submodules/TelegramUI/Sources/SharedAccountContext.swift b/submodules/TelegramUI/Sources/SharedAccountContext.swift index 323a854e20..12fd16d4fe 100644 --- a/submodules/TelegramUI/Sources/SharedAccountContext.swift +++ b/submodules/TelegramUI/Sources/SharedAccountContext.swift @@ -62,6 +62,7 @@ import MediaEditorScreen import BusinessIntroSetupScreen import TelegramNotices import BotSettingsScreen +import Camera import CameraScreen import BirthdayPickerScreen import StarsTransactionsScreen @@ -3647,6 +3648,57 @@ public final class SharedAccountContextImpl: SharedAccountContext { return editorController } + public func makeCameraScreen(context: AccountContext, mode: CameraScreenMode, cameraHolder: Any?, transitionIn: CameraScreenTransitionIn?, transitionOut: @escaping (Bool) -> CameraScreenTransitionOut?, completion: @escaping (Any, @escaping () -> Void) -> Void, transitionedOut: (() -> Void)?) -> ViewController { + let mappedTransitionIn = transitionIn.flatMap { + if let sourceView = $0.sourceView { + return CameraScreenImpl.TransitionIn( + sourceView: sourceView, + sourceRect: $0.sourceRect, + sourceCornerRadius: $0.sourceCornerRadius, + useFillAnimation: $0.useFillAnimation + ) + } else { + return nil + } + } + let mappedMode: CameraScreenImpl.Mode + switch mode { + case .sticker: + mappedMode = .sticker + case .avatar: + mappedMode = .avatar + case .story: + mappedMode = .story + } + let controller = CameraScreenImpl( + context: context, + mode: mappedMode, + holder: cameraHolder as? CameraHolder, + transitionIn: mappedTransitionIn, + transitionOut: { value in + return transitionOut(value).flatMap { + if let destinationView = $0.destinationView { + return CameraScreenImpl.TransitionOut( + destinationView: destinationView, + destinationRect: $0.destinationRect, + destinationCornerRadius: $0.destinationCornerRadius, + completion: $0.completion + ) + } else { + return nil + } + } + }, + completion: { result, _, _, commit in + completion(result, commit) + } + ) + if let transitionedOut { + controller.transitionedOut = transitionedOut + } + return controller + } + public func makeMediaPickerScreen(context: AccountContext, hasSearch: Bool, completion: @escaping (Any) -> Void) -> ViewController { return mediaPickerController(context: context, hasSearch: hasSearch, completion: completion) }