From b4cc4e0bd04e2c922993fa4c0d58d8d4375fa8f5 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Tue, 16 Jul 2024 02:41:00 +0400 Subject: [PATCH] Various improvements --- .../Telegram-iOS/en.lproj/Localizable.strings | 12 +- .../BrowserUI/Sources/BrowserContent.swift | 2 + .../Sources/BrowserInstantPageContent.swift | 17 +- .../BrowserUI/Sources/BrowserScreen.swift | 30 ++- .../BrowserUI/Sources/BrowserWebContent.swift | 178 ++++++++++++++++-- .../Sources/MediaPickerGridItem.swift | 7 +- .../Sources/MediaPickerScreen.swift | 7 +- .../Sources/ChannelStatsController.swift | 12 +- .../{Utils.swift => MediaEditorUtils.swift} | 0 .../PeerInfoScreen/Sources/PeerInfoData.swift | 2 +- .../Sources/StarsStatisticsScreen.swift | 11 ++ .../SelectedIcon.imageset/Contents.json | 12 ++ .../SelectedIcon.imageset/albumcheck.pdf | 93 +++++++++ 13 files changed, 348 insertions(+), 35 deletions(-) rename submodules/TelegramUI/Components/MediaEditorScreen/Sources/{Utils.swift => MediaEditorUtils.swift} (100%) create mode 100644 submodules/TelegramUI/Images.xcassets/Media Gallery/SelectedIcon.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Media Gallery/SelectedIcon.imageset/albumcheck.pdf diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 665b64bc35..ca34f09469 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -12518,4 +12518,14 @@ Sorry for the inconvenience."; "Bot.Settings" = "Bot Settings"; -"Browser.OpenInNewTap" = ""; +"Browser.ErrorTitle" = "An Error Occurred"; + +"Browser.ContextMenu.Open" = "Open"; +"Browser.ContextMenu.OpenInNewTab" = "Open in New Tab"; +"Browser.ContextMenu.AddToReadingList" = "Add to Reading List"; +"Browser.ContextMenu.CopyLink" = "Copy Link"; +"Browser.ContextMenu.Share" = "Share"; + +"Monetization.Proceeds.Ton.Info" = "TON from your total balance can be used for ads or withdrawn as rewards 3 days after they are earned."; +"Monetization.Proceeds.Stars.Info" = "Stars from your total balance can be used for ads or withdrawn as rewards 21 days after they are earned."; +"Monetization.Proceeds.TonAndStars.Info" = "Stars and TON from your total balance can be used for ads or withdrawn as rewards 21 and 3 days respectively after they are earned."; diff --git a/submodules/BrowserUI/Sources/BrowserContent.swift b/submodules/BrowserUI/Sources/BrowserContent.swift index 567ec9e08c..931103bc78 100644 --- a/submodules/BrowserUI/Sources/BrowserContent.swift +++ b/submodules/BrowserUI/Sources/BrowserContent.swift @@ -4,6 +4,7 @@ import Display import ComponentFlow import SwiftSignalKit import WebKit +import TelegramPresentationData final class BrowserContentState: Equatable { enum ContentType: Equatable { @@ -162,6 +163,7 @@ protocol BrowserContent: UIView { func navigateForward() func navigateTo(historyItem: BrowserContentState.HistoryItem) + func updatePresentationData(_ presentationData: PresentationData) func updateFontState(_ state: BrowserPresentationState.FontState) func setSearch(_ query: String?, completion: ((Int) -> Void)?) diff --git a/submodules/BrowserUI/Sources/BrowserInstantPageContent.swift b/submodules/BrowserUI/Sources/BrowserInstantPageContent.swift index d686a615db..7abc50eea1 100644 --- a/submodules/BrowserUI/Sources/BrowserInstantPageContent.swift +++ b/submodules/BrowserUI/Sources/BrowserInstantPageContent.swift @@ -24,8 +24,8 @@ import GalleryUI final class BrowserInstantPageContent: UIView, BrowserContent, UIScrollViewDelegate { private let context: AccountContext - private let presentationData: PresentationData - private let theme: InstantPageTheme + private var presentationData: PresentationData + private var theme: InstantPageTheme private let sourceLocation: InstantPageSourceLocation private var webPage: TelegramMediaWebpage? @@ -87,11 +87,11 @@ final class BrowserInstantPageContent: UIView, BrowserContent, UIScrollViewDeleg private var containerLayout: (size: CGSize, insets: UIEdgeInsets)? private var setupScrollOffsetOnLayout = false - init(context: AccountContext, webPage: TelegramMediaWebpage, anchor: String?, url: String, sourceLocation: InstantPageSourceLocation) { + init(context: AccountContext, presentationData: PresentationData, webPage: TelegramMediaWebpage, anchor: String?, url: String, sourceLocation: InstantPageSourceLocation) { self.context = context self.webPage = webPage - self.presentationData = context.sharedContext.currentPresentationData.with { $0 } - self.theme = instantPageThemeForType(.light, settings: .defaultSettings) + self.presentationData = presentationData + self.theme = instantPageThemeForType(presentationData.theme.overallDarkAppearance ? .dark : .light, settings: .defaultSettings) self.sourceLocation = sourceLocation self.uuid = UUID() @@ -171,6 +171,13 @@ final class BrowserInstantPageContent: UIView, BrowserContent, UIScrollViewDeleg fatalError("init(coder:) has not been implemented") } + func updatePresentationData(_ presentationData: PresentationData) { + self.presentationData = presentationData + + self.theme = instantPageThemeForType(presentationData.theme.overallDarkAppearance ? .dark : .light, settings: .defaultSettings) + self.updatePageLayout() + } + func tapActionAtPoint(_ point: CGPoint) -> TapLongTapOrDoubleTapGestureRecognizerAction { if let currentLayout = self.currentLayout { for item in currentLayout.items { diff --git a/submodules/BrowserUI/Sources/BrowserScreen.swift b/submodules/BrowserUI/Sources/BrowserScreen.swift index ee0cea073f..2d9bd49d46 100644 --- a/submodules/BrowserUI/Sources/BrowserScreen.swift +++ b/submodules/BrowserUI/Sources/BrowserScreen.swift @@ -455,6 +455,9 @@ public class BrowserScreen: ViewController, MinimizableController { return } self.presentationData = presentationData + for content in self.content { + content.updatePresentationData(presentationData) + } self.requestLayout(transition: .immediate) }) } @@ -480,9 +483,9 @@ public class BrowserScreen: ViewController, MinimizableController { let browserContent: BrowserContent switch content { case let .webPage(url): - browserContent = BrowserWebContent(context: self.context, url: url) + browserContent = BrowserWebContent(context: self.context, presentationData: self.presentationData, url: url) case let .instantPage(webPage, anchor, sourceLocation): - let instantPageContent = BrowserInstantPageContent(context: self.context, webPage: webPage, anchor: anchor, url: webPage.content.url ?? "", sourceLocation: sourceLocation) + let instantPageContent = BrowserInstantPageContent(context: self.context, presentationData: self.presentationData, webPage: webPage, anchor: anchor, url: webPage.content.url ?? "", sourceLocation: sourceLocation) instantPageContent.openPeer = { [weak self] peer in guard let self else { return @@ -580,14 +583,15 @@ public class BrowserScreen: ViewController, MinimizableController { self.controller?.title = state.title self.contentState = state - let transition: ComponentTransition - if let previousState, previousState.withUpdatedReadingProgress(state.readingProgress) == state { - transition = .immediate - } else { - transition = .easeInOut(duration: 0.25) + if !self.isUpdating { + let transition: ComponentTransition + if let previousState, previousState.withUpdatedReadingProgress(state.readingProgress) == state { + transition = .immediate + } else { + transition = .easeInOut(duration: 0.25) + } + self.requestLayout(transition: transition) } - - self.requestLayout(transition: transition) })) content.onScrollingUpdate = { [weak self] update in @@ -823,13 +827,19 @@ public class BrowserScreen: ViewController, MinimizableController { self.controller?.present(contextController, in: .window(.root)) } + private var isUpdating = false func requestLayout(transition: ComponentTransition) { - if let (layout, navigationBarHeight) = self.validLayout { + if !self.isUpdating, let (layout, navigationBarHeight) = self.validLayout { self.containerLayoutUpdated(layout: layout, navigationBarHeight: navigationBarHeight, transition: transition) } } func containerLayoutUpdated(layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ComponentTransition) { + self.isUpdating = true + defer { + self.isUpdating = false + } + self.validLayout = (layout, navigationBarHeight) let environment = ViewControllerComponentContainer.Environment( diff --git a/submodules/BrowserUI/Sources/BrowserWebContent.swift b/submodules/BrowserUI/Sources/BrowserWebContent.swift index f67a5cc45e..c645dec035 100644 --- a/submodules/BrowserUI/Sources/BrowserWebContent.swift +++ b/submodules/BrowserUI/Sources/BrowserWebContent.swift @@ -15,6 +15,8 @@ import PromptUI import SafariServices import ShareController import UndoUI +import LottieComponent +import MultilineTextComponent private final class IpfsSchemeHandler: NSObject, WKURLSchemeHandler { private final class PendingTask { @@ -88,9 +90,13 @@ private final class IpfsSchemeHandler: NSObject, WKURLSchemeHandler { final class BrowserWebContent: UIView, BrowserContent, WKNavigationDelegate, WKUIDelegate, UIScrollViewDelegate { private let context: AccountContext + private var presentationData: PresentationData private let webView: WKWebView + private let errorView: ComponentHostView + private var currentError: Error? + let uuid: UUID private var _state: BrowserContentState @@ -112,9 +118,10 @@ final class BrowserWebContent: UIView, BrowserContent, WKNavigationDelegate, WKU var presentInGlobalOverlay: (ViewController) -> Void = { _ in } var getNavigationController: () -> NavigationController? = { return nil } - init(context: AccountContext, url: String) { + init(context: AccountContext, presentationData: PresentationData, url: String) { self.context = context self.uuid = UUID() + self.presentationData = presentationData let configuration = WKWebViewConfiguration() @@ -126,7 +133,7 @@ final class BrowserWebContent: UIView, BrowserContent, WKNavigationDelegate, WKU self.webView = WKWebView(frame: CGRect(), configuration: configuration) self.webView.allowsLinkPreview = true - if #available(iOSApplicationExtension 11.0, iOS 11.0, *) { + if #available(iOS 11.0, *) { self.webView.scrollView.contentInsetAdjustmentBehavior = .never } @@ -138,6 +145,8 @@ final class BrowserWebContent: UIView, BrowserContent, WKNavigationDelegate, WKU title = parsedUrl.host ?? "" } + self.errorView = ComponentHostView() + self._state = BrowserContentState(title: title, url: url, estimatedProgress: 0.0, readingProgress: 0.0, contentType: .webPage) self.statePromise = Promise(self._state) @@ -152,7 +161,9 @@ final class BrowserWebContent: UIView, BrowserContent, WKNavigationDelegate, WKU self.webView.addObserver(self, forKeyPath: #keyPath(WKWebView.estimatedProgress), options: [], context: nil) self.webView.addObserver(self, forKeyPath: #keyPath(WKWebView.canGoBack), options: [], context: nil) self.webView.addObserver(self, forKeyPath: #keyPath(WKWebView.canGoForward), options: [], context: nil) - + if #available(iOS 15.0, *) { + self.webView.underPageBackgroundColor = presentationData.theme.list.plainBackgroundColor + } self.addSubview(self.webView) } @@ -170,6 +181,16 @@ final class BrowserWebContent: UIView, BrowserContent, WKNavigationDelegate, WKU self.faviconDisposable.dispose() } + func updatePresentationData(_ presentationData: PresentationData) { + self.presentationData = presentationData + if #available(iOS 15.0, *) { + self.webView.underPageBackgroundColor = presentationData.theme.list.plainBackgroundColor + } + if let (size, insets) = self.validLayout { + self.updateLayout(size: size, insets: insets, transition: .immediate) + } + } + var currentFontState = BrowserPresentationState.FontState(size: 100, isSerif: false) func updateFontState(_ state: BrowserPresentationState.FontState) { self.updateFontState(state, force: false) @@ -313,15 +334,42 @@ final class BrowserWebContent: UIView, BrowserContent, WKNavigationDelegate, WKU self.webView.scrollView.setContentOffset(CGPoint(x: 0.0, y: -self.webView.scrollView.contentInset.top), animated: true) } + private var validLayout: (CGSize, UIEdgeInsets)? func updateLayout(size: CGSize, insets: UIEdgeInsets, transition: ComponentTransition) { + self.validLayout = (size, insets) + var scrollInsets = insets + scrollInsets.left = 0.0 + scrollInsets.right = 0.0 scrollInsets.top = 0.0 if self.webView.scrollView.contentInset != insets { self.webView.scrollView.contentInset = scrollInsets self.webView.scrollView.scrollIndicatorInsets = scrollInsets } self.previousScrollingOffset = ScrollingOffsetState(value: self.webView.scrollView.contentOffset.y, isDraggingOrDecelerating: self.webView.scrollView.isDragging || self.webView.scrollView.isDecelerating) - transition.setFrame(view: self.webView, frame: CGRect(origin: CGPoint(x: 0.0, y: insets.top), size: CGSize(width: size.width, height: size.height - insets.top))) + transition.setFrame(view: self.webView, frame: CGRect(origin: CGPoint(x: insets.left, y: insets.top), size: CGSize(width: size.width - insets.left - insets.right, height: size.height - insets.top))) + + if let error = self.currentError { + let errorSize = self.errorView.update( + transition: .immediate, + component: AnyComponent( + ErrorComponent( + theme: self.presentationData.theme, + title: self.presentationData.strings.Browser_ErrorTitle, + text: error.localizedDescription + ) + ), + environment: {}, + containerSize: CGSize(width: size.width - insets.left - insets.right - 72.0, height: size.height) + ) + if self.errorView.superview == nil { + self.addSubview(self.errorView) + self.errorView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25) + } + self.errorView.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - errorSize.width) / 2.0), y: insets.top + floorToScreenPixels((size.height - insets.top - insets.bottom - errorSize.height) / 2.0)), size: errorSize) + } else if self.errorView.superview != nil { + self.errorView.removeFromSuperview() + } } private func updateState(_ f: (BrowserContentState) -> BrowserContentState) { @@ -403,6 +451,7 @@ final class BrowserWebContent: UIView, BrowserContent, WKNavigationDelegate, WKU } func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) { + self.currentError = nil self.updateFontState(self.currentFontState, force: true) } @@ -411,10 +460,24 @@ final class BrowserWebContent: UIView, BrowserContent, WKNavigationDelegate, WKU $0 .withUpdatedBackList(webView.backForwardList.backList.map { BrowserContentState.HistoryItem(webItem: $0) }) .withUpdatedForwardList(webView.backForwardList.forwardList.map { BrowserContentState.HistoryItem(webItem: $0) }) - } + } self.parseFavicon() } + func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) { + self.currentError = error + if let (size, insets) = self.validLayout { + self.updateLayout(size: size, insets: insets, transition: .immediate) + } + } + + func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) { + self.currentError = error + if let (size, insets) = self.validLayout { + self.updateLayout(size: size, insets: insets, transition: .immediate) + } + } + @available(iOSApplicationExtension 15.0, iOS 15.0, *) func webView(_ webView: WKWebView, requestMediaCapturePermissionFor origin: WKSecurityOrigin, initiatedByFrame frame: WKFrameInfo, type: WKMediaCaptureType, decisionHandler: @escaping (WKPermissionDecision) -> Void) { decisionHandler(.prompt) @@ -494,24 +557,23 @@ final class BrowserWebContent: UIView, BrowserContent, WKNavigationDelegate, WKU completionHandler(nil) return } - //TODO:localize let presentationData = self.context.sharedContext.currentPresentationData.with { $0 } let configuration = UIContextMenuConfiguration(identifier: nil, previewProvider: nil) { [weak self] _ in return UIMenu(title: "", children: [ - UIAction(title: "Open", image: generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Browser"), color: presentationData.theme.contextMenu.primaryColor), handler: { [weak self] _ in + UIAction(title: presentationData.strings.Browser_ContextMenu_Open, image: generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Browser"), color: presentationData.theme.contextMenu.primaryColor), handler: { [weak self] _ in self?.open(url: url.absoluteString, new: false) }), - UIAction(title: "Open in New Tab", image: generateTintedImage(image: UIImage(bundleImageName: "Instant View/NewTab"), color: presentationData.theme.contextMenu.primaryColor), handler: { [weak self] _ in + UIAction(title: presentationData.strings.Browser_ContextMenu_OpenInNewTab, image: generateTintedImage(image: UIImage(bundleImageName: "Instant View/NewTab"), color: presentationData.theme.contextMenu.primaryColor), handler: { [weak self] _ in self?.open(url: url.absoluteString, new: true) }), - UIAction(title: "Add to Reading List", image: generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/ReadingList"), color: presentationData.theme.contextMenu.primaryColor), handler: { _ in + UIAction(title: presentationData.strings.Browser_ContextMenu_AddToReadingList, image: generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/ReadingList"), color: presentationData.theme.contextMenu.primaryColor), handler: { _ in let _ = try? SSReadingList.default()?.addItem(with: url, title: nil, previewText: nil) }), - UIAction(title: "Copy Link", image: generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Copy"), color: presentationData.theme.contextMenu.primaryColor), handler: { [weak self] _ in + UIAction(title: presentationData.strings.Browser_ContextMenu_CopyLink, image: generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Copy"), color: presentationData.theme.contextMenu.primaryColor), handler: { [weak self] _ in UIPasteboard.general.string = url.absoluteString self?.present(UndoOverlayController(presentationData: presentationData, content: .linkCopied(text: presentationData.strings.Conversation_LinkCopied), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), nil) }), - UIAction(title: "Share", image: generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Forward"), color: presentationData.theme.contextMenu.primaryColor), handler: { [weak self] _ in + UIAction(title: presentationData.strings.Browser_ContextMenu_Share, image: generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Forward"), color: presentationData.theme.contextMenu.primaryColor), handler: { [weak self] _ in self?.share(url: url.absoluteString) }) ]) @@ -625,3 +687,97 @@ final class BrowserWebContent: UIView, BrowserContent, WKNavigationDelegate, WKU }) } } + +private final class ErrorComponent: CombinedComponent { + let theme: PresentationTheme + let title: String + let text: String + + init( + theme: PresentationTheme, + title: String, + text: String + ) { + self.theme = theme + self.title = title + self.text = text + } + + static func ==(lhs: ErrorComponent, rhs: ErrorComponent) -> Bool { + if lhs.theme !== rhs.theme { + return false + } + if lhs.title != rhs.title { + return false + } + if lhs.text != rhs.text { + return false + } + return true + } + + static var body: Body { + let animation = Child(LottieComponent.self) + let title = Child(MultilineTextComponent.self) + let text = Child(MultilineTextComponent.self) + + return { context in + var contentHeight: CGFloat = 0.0 + let animationSize = 148.0 + let animationSpacing: CGFloat = 8.0 + let textSpacing: CGFloat = 8.0 + + let animation = animation.update( + component: LottieComponent( + content: LottieComponent.AppBundleContent(name: "ChatListNoResults") + ), + environment: {}, + availableSize: CGSize(width: animationSize, height: animationSize), + transition: .immediate + ) + context.add(animation + .position(CGPoint(x: context.availableSize.width / 2.0, y: contentHeight + animation.size.height / 2.0)) + ) + contentHeight += animation.size.height + animationSpacing + + let title = title.update( + component: MultilineTextComponent( + text: .plain(NSAttributedString( + string: context.component.title, + font: Font.semibold(17.0), + textColor: context.component.theme.list.itemSecondaryTextColor + )), + horizontalAlignment: .center + ), + environment: {}, + availableSize: context.availableSize, + transition: .immediate + ) + context.add(title + .position(CGPoint(x: context.availableSize.width / 2.0, y: contentHeight + title.size.height / 2.0)) + ) + contentHeight += title.size.height + textSpacing + + let text = text.update( + component: MultilineTextComponent( + text: .plain(NSAttributedString( + string: context.component.text, + font: Font.regular(15.0), + textColor: context.component.theme.list.itemSecondaryTextColor + )), + horizontalAlignment: .center, + maximumNumberOfLines: 0 + ), + environment: {}, + availableSize: context.availableSize, + transition: .immediate + ) + context.add(text + .position(CGPoint(x: context.availableSize.width / 2.0, y: contentHeight + text.size.height / 2.0)) + ) + contentHeight += text.size.height + + return CGSize(width: context.availableSize.width, height: contentHeight) + } + } +} diff --git a/submodules/MediaPickerUI/Sources/MediaPickerGridItem.swift b/submodules/MediaPickerUI/Sources/MediaPickerGridItem.swift index c5cab76799..4c2873fbef 100644 --- a/submodules/MediaPickerUI/Sources/MediaPickerGridItem.swift +++ b/submodules/MediaPickerUI/Sources/MediaPickerGridItem.swift @@ -585,9 +585,7 @@ final class MediaPickerGridItemNode: GridItemNode { var typeIcon: UIImage? var duration: String? - if asset.isFavorite { - typeIcon = generateTintedImage(image: UIImage(bundleImageName: "Media Grid/Favorite"), color: .white) - } else if asset.mediaType == .video { + if asset.mediaType == .video { if asset.mediaSubtypes.contains(.videoHighFrameRate) { typeIcon = UIImage(bundleImageName: "Media Editor/MediaSlomo") } else if asset.mediaSubtypes.contains(.videoTimelapse) { @@ -597,6 +595,9 @@ final class MediaPickerGridItemNode: GridItemNode { } duration = stringForDuration(Int32(asset.duration)) } + if asset.isFavorite { + typeIcon = generateTintedImage(image: UIImage(bundleImageName: "Media Grid/Favorite"), color: .white) + } if typeIcon != nil { if self.leftShadowNode.supernode == nil { diff --git a/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift b/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift index 5e151f6597..f3d483c191 100644 --- a/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift +++ b/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift @@ -3186,6 +3186,7 @@ private class SelectedButtonNode: HighlightableButtonNode { var theme: PresentationTheme { didSet { + self.icon.image = generateTintedImage(image: UIImage(bundleImageName: "Media Gallery/SelectedIcon"), color: self.theme.list.itemCheckColors.foregroundColor) self.background.image = generateStretchableFilledCircleImage(radius: 21.0 / 2.0, color: self.theme.list.itemCheckColors.fillColor) let _ = self.update(count: self.count) } @@ -3202,7 +3203,7 @@ private class SelectedButtonNode: HighlightableButtonNode { self.icon.displaysAsynchronously = false self.label.displaysAsynchronously = false - self.icon.image = generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: .white) + self.icon.image = generateTintedImage(image: UIImage(bundleImageName: "Media Gallery/SelectedIcon"), color: self.theme.list.itemCheckColors.foregroundColor) self.background.image = generateStretchableFilledCircleImage(radius: 21.0 / 2.0, color: self.theme.list.itemCheckColors.fillColor) self.addSubnode(self.background) @@ -3229,8 +3230,8 @@ private class SelectedButtonNode: HighlightableButtonNode { let size = CGSize(width: textSize.width + 28.0, height: diameter) if let _ = self.icon.image { - let iconSize = CGSize(width: 22.0, height: 22.0) - let iconFrame = CGRect(origin: CGPoint(x: 0.0, y: floor((size.height - iconSize.height) / 2.0)), size: iconSize) + let iconSize = CGSize(width: 14.0, height: 11.0) + let iconFrame = CGRect(origin: CGPoint(x: 5.0, y: floor((size.height - iconSize.height) / 2.0)), size: iconSize) self.icon.frame = iconFrame } diff --git a/submodules/StatisticsUI/Sources/ChannelStatsController.swift b/submodules/StatisticsUI/Sources/ChannelStatsController.swift index 463012ae1e..3a9a97ff33 100644 --- a/submodules/StatisticsUI/Sources/ChannelStatsController.swift +++ b/submodules/StatisticsUI/Sources/ChannelStatsController.swift @@ -1555,7 +1555,17 @@ private func monetizationEntries( entries.append(.adsProceedsTitle(presentationData.theme, presentationData.strings.Monetization_StarsProceeds_Title)) entries.append(.adsProceedsOverview(presentationData.theme, canViewRevenue ? data : nil, canViewStarsRevenue ? starsData : nil)) - entries.append(.adsProceedsInfo(presentationData.theme, presentationData.strings.Monetization_StarsProceeds_Info)) + + + let proceedsInfo: String + if canViewStarsRevenue && canViewRevenue { + proceedsInfo = presentationData.strings.Monetization_Proceeds_TonAndStars_Info + } else if canViewStarsRevenue { + proceedsInfo = presentationData.strings.Monetization_Proceeds_Stars_Info + } else { + proceedsInfo = presentationData.strings.Monetization_Proceeds_Ton_Info + } + entries.append(.adsProceedsInfo(presentationData.theme, proceedsInfo)) var isCreator = false if let peer, case let .channel(channel) = peer, channel.flags.contains(.isCreator) { diff --git a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/Utils.swift b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorUtils.swift similarity index 100% rename from submodules/TelegramUI/Components/MediaEditorScreen/Sources/Utils.swift rename to submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorUtils.swift diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoData.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoData.swift index 48e0f0dde5..48a161e9b3 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoData.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoData.swift @@ -1186,7 +1186,7 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen let starsRevenueContextAndState = context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) |> mapToSignal { peer -> Signal<(StarsRevenueStatsContext?, StarsRevenueStats?), NoError> in - guard let peer, case let .user(user) = peer, let botInfo = user.botInfo, botInfo.flags.contains(.canEdit) || context.sharedContext.applicationBindings.appBuildType == .internal else { + guard let peer, case let .user(user) = peer, let botInfo = user.botInfo, botInfo.flags.contains(.canEdit) || context.sharedContext.applicationBindings.appBuildType == .public else { return .single((nil, nil)) } let starsRevenueStatsContext = StarsRevenueStatsContext(account: context.account, peerId: peerId) diff --git a/submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsStatisticsScreen.swift b/submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsStatisticsScreen.swift index de36ea1c50..d8ea1cab30 100644 --- a/submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsStatisticsScreen.swift +++ b/submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsStatisticsScreen.swift @@ -193,6 +193,10 @@ final class StarsStatisticsScreenComponent: Component { deinit { self.stateDisposable?.dispose() } + + func scrollToTop() { + self.scrollView.setContentOffset(CGPoint(x: 0.0, y: -self.scrollView.contentInset.top), animated: true) + } func scrollViewDidScroll(_ scrollView: UIScrollView) { if !self.ignoreScrolling { @@ -783,6 +787,13 @@ public final class StarsStatisticsScreen: ViewControllerComponentContainer { } self.transactionsContext.loadMore() + + self.scrollToTop = { [weak self] in + guard let self, let componentView = self.node.hostView.componentView as? StarsStatisticsScreenComponent.View else { + return + } + componentView.scrollToTop() + } } required public init(coder aDecoder: NSCoder) { diff --git a/submodules/TelegramUI/Images.xcassets/Media Gallery/SelectedIcon.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Media Gallery/SelectedIcon.imageset/Contents.json new file mode 100644 index 0000000000..f64d2b6f8c --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Media Gallery/SelectedIcon.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "albumcheck.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Media Gallery/SelectedIcon.imageset/albumcheck.pdf b/submodules/TelegramUI/Images.xcassets/Media Gallery/SelectedIcon.imageset/albumcheck.pdf new file mode 100644 index 0000000000..1632870d60 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Media Gallery/SelectedIcon.imageset/albumcheck.pdf @@ -0,0 +1,93 @@ +%PDF-1.7 + +1 0 obj + << >> +endobj + +2 0 obj + << /Length 3 0 R >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +1.000000 0.000000 -0.000000 1.000000 1.500000 -1.125229 cm +1.000000 1.000000 1.000000 scn +0.752577 6.783733 m +0.388895 7.199370 -0.242868 7.241488 -0.658505 6.877806 c +-1.074141 6.514123 -1.116259 5.882361 -0.752577 5.466724 c +0.752577 6.783733 l +h +3.500000 2.125229 m +2.747423 1.466724 l +2.940081 1.246544 3.219498 1.121778 3.512046 1.125301 c +3.804593 1.128825 4.080924 1.260287 4.268221 1.485044 c +3.500000 2.125229 l +h +11.768221 10.485044 m +12.121785 10.909322 12.064462 11.539886 11.640184 11.893450 c +11.215907 12.247014 10.585342 12.189691 10.231779 11.765413 c +11.768221 10.485044 l +h +-0.752577 5.466724 m +2.747423 1.466724 l +4.252577 2.783733 l +0.752577 6.783733 l +-0.752577 5.466724 l +h +4.268221 1.485044 m +11.768221 10.485044 l +10.231779 11.765413 l +2.731779 2.765413 l +4.268221 1.485044 l +h +f +n +Q + +endstream +endobj + +3 0 obj + 839 +endobj + +4 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 14.000000 11.000031 ] + /Resources 1 0 R + /Contents 2 0 R + /Parent 5 0 R + >> +endobj + +5 0 obj + << /Kids [ 4 0 R ] + /Count 1 + /Type /Pages + >> +endobj + +6 0 obj + << /Pages 5 0 R + /Type /Catalog + >> +endobj + +xref +0 7 +0000000000 65535 f +0000000010 00000 n +0000000034 00000 n +0000000929 00000 n +0000000951 00000 n +0000001124 00000 n +0000001198 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +1257 +%%EOF \ No newline at end of file