From 62a6d11e7f5a2cc7dad7d2e6ab1650275cbb015e Mon Sep 17 00:00:00 2001 From: Ali <> Date: Mon, 26 Jun 2023 14:59:20 +0300 Subject: [PATCH] Temp --- .../EmptyStateIndicatorComponent/BUILD | 24 +++ .../EmptyStateIndicatorComponent.swift | 146 ++++++++++++++++++ .../PeerInfoVisualMediaPaneNode/BUILD | 1 + .../Sources/PeerInfoStoryPaneNode.swift | 39 +++++ 4 files changed, 210 insertions(+) create mode 100644 submodules/TelegramUI/Components/EmptyStateIndicatorComponent/BUILD create mode 100644 submodules/TelegramUI/Components/EmptyStateIndicatorComponent/Sources/EmptyStateIndicatorComponent.swift diff --git a/submodules/TelegramUI/Components/EmptyStateIndicatorComponent/BUILD b/submodules/TelegramUI/Components/EmptyStateIndicatorComponent/BUILD new file mode 100644 index 0000000000..dc8ed1d04c --- /dev/null +++ b/submodules/TelegramUI/Components/EmptyStateIndicatorComponent/BUILD @@ -0,0 +1,24 @@ +load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") + +swift_library( + name = "EmptyStateIndicatorComponent", + module_name = "EmptyStateIndicatorComponent", + srcs = glob([ + "Sources/**/*.swift", + ]), + copts = [ + "-warnings-as-errors", + ], + deps = [ + "//submodules/Display", + "//submodules/ComponentFlow", + "//submodules/Components/AnimatedStickerComponent", + "//submodules/Components/MultilineTextComponent", + "//submodules/TelegramUI/Components/ButtonComponent", + "//submodules/TelegramPresentationData", + "//submodules/AccountContext", + ], + visibility = [ + "//visibility:public", + ], +) diff --git a/submodules/TelegramUI/Components/EmptyStateIndicatorComponent/Sources/EmptyStateIndicatorComponent.swift b/submodules/TelegramUI/Components/EmptyStateIndicatorComponent/Sources/EmptyStateIndicatorComponent.swift new file mode 100644 index 0000000000..80a61d9fe2 --- /dev/null +++ b/submodules/TelegramUI/Components/EmptyStateIndicatorComponent/Sources/EmptyStateIndicatorComponent.swift @@ -0,0 +1,146 @@ +import Foundation +import UIKit +import Display +import ComponentFlow +import AnimatedStickerComponent +import ButtonComponent +import TelegramPresentationData +import AccountContext +import MultilineTextComponent + +public final class EmptyStateIndicatorComponent: Component { + public let context: AccountContext + public let animationName: String + public let title: String + public let text: String + public let theme: PresentationTheme + public let action: () -> Void + + public init( + context: AccountContext, + theme: PresentationTheme, + animationName: String, + title: String, + text: String, + action: @escaping () -> Void + ) { + self.context = context + self.theme = theme + self.animationName = animationName + self.title = title + self.text = text + self.action = action + } + + public static func ==(lhs: EmptyStateIndicatorComponent, rhs: EmptyStateIndicatorComponent) -> Bool { + if lhs.context !== rhs.context { + return false + } + if lhs.theme !== rhs.theme { + return false + } + if lhs.animationName != rhs.animationName { + return false + } + if lhs.title != rhs.title { + return false + } + if lhs.text != rhs.text { + return false + } + return true + } + + public final class View: UIView { + private var component: EmptyStateIndicatorComponent? + private weak var componentState: EmptyComponentState? + + private let animation = ComponentView() + private let title = ComponentView() + private let text = ComponentView() + private let button = ComponentView() + + override public init(frame: CGRect) { + super.init(frame: frame) + } + + required public init(coder: NSCoder) { + preconditionFailure() + } + + public func update(component: EmptyStateIndicatorComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + self.component = component + self.componentState = state + + let animationSize = self.animation.update( + transition: transition, + component: AnyComponent(AnimatedStickerComponent( + account: component.context.account, + animation: AnimatedStickerComponent.Animation(source: .bundle(name: component.animationName), loop: true), + size: CGSize(width: 200.0, height: 200.0) + )), + environment: {}, + containerSize: CGSize(width: 200.0, height: 200.0) + ) + let titleSize = self.title.update( + transition: .immediate, + component: AnyComponent(MultilineTextComponent( + text: .plain(NSAttributedString(string: component.title, font: Font.semibold(17.0), textColor: component.theme.list.itemPrimaryTextColor)), + horizontalAlignment: .center, + maximumNumberOfLines: 0 + )), + environment: {}, + containerSize: CGSize(width: min(300.0, availableSize.width - 16.0 * 2.0), height: 1000.0) + ) + let textSize = self.text.update( + transition: .immediate, + component: AnyComponent(MultilineTextComponent( + text: .plain(NSAttributedString(string: component.text, font: Font.regular(15.0), textColor: component.theme.list.itemSecondaryTextColor)), + horizontalAlignment: .center, + maximumNumberOfLines: 0 + )), + environment: {}, + containerSize: CGSize(width: min(300.0, availableSize.width - 16.0 * 2.0), height: 1000.0) + ) + + let animationSpacing: CGFloat = 16.0 + let titleSpacing: CGFloat = 16.0 + + let totalHeight: CGFloat = animationSize.height + animationSpacing + titleSize.height + titleSpacing + textSize.height + + var contentY = floor((availableSize.height - totalHeight) * 0.5) + + if let animationView = self.animation.view { + if animationView.superview == nil { + self.addSubview(animationView) + } + transition.setFrame(view: animationView, frame: CGRect(origin: CGPoint(x: floor((availableSize.width - animationSize.width) * 0.5), y: contentY), size: animationSize)) + contentY += animationSize.height + animationSpacing + } + if let titleView = self.title.view { + if titleView.superview == nil { + self.addSubview(titleView) + } + transition.setFrame(view: titleView, frame: CGRect(origin: CGPoint(x: floor((availableSize.width - titleSize.width) * 0.5), y: contentY), size: titleSize)) + contentY += titleSize.height + titleSpacing + } + if let textView = self.text.view { + if textView.superview == nil { + self.addSubview(textView) + } + transition.setFrame(view: textView, frame: CGRect(origin: CGPoint(x: floor((availableSize.width - textSize.width) * 0.5), y: contentY), size: textSize)) + contentY += textSize.height + titleSpacing + } + + return availableSize + } + } + + public func makeView() -> View { + return View(frame: CGRect()) + } + + public func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition) + } +} diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/BUILD b/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/BUILD index 712da58eaa..b861093abe 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/BUILD +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/BUILD @@ -36,6 +36,7 @@ swift_library( "//submodules/InvisibleInkDustNode", "//submodules/MediaPickerUI", "//submodules/TelegramUI/Components/Stories/StoryContainerScreen", + "//submodules/TelegramUI/Components/EmptyStateIndicatorComponent", ], visibility = [ "//visibility:public", diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoStoryPaneNode.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoStoryPaneNode.swift index 77f5e9b15a..252edda46c 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoStoryPaneNode.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoStoryPaneNode.swift @@ -26,6 +26,7 @@ import AppBundle import InvisibleInkDustNode import MediaPickerUI import StoryContainerScreen +import EmptyStateIndicatorComponent private let mediaBadgeBackgroundColor = UIColor(white: 0.0, alpha: 0.6) private let mediaBadgeTextColor = UIColor.white @@ -892,6 +893,8 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr private weak var pendingOpenListContext: PeerStoryListContentContextImpl? private var preloadArchiveListContext: PeerStoryListContext? + + private var emptyStateView: ComponentView? public init(context: AccountContext, peerId: PeerId, chatLocation: ChatLocation, contentType: ContentType, captureProtected: Bool, isSaved: Bool, isArchive: Bool, navigationController: @escaping () -> NavigationController?, listContext: PeerStoryListContext?) { self.context = context @@ -1863,6 +1866,42 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr self.currentParams = (size, topInset, sideInset, bottomInset, visibleHeight, isScrollingLockedAtTop, expandProgress, presentationData) transition.updateFrame(node: self.contextGestureContainerNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: size.width, height: size.height))) + + if let items = self.items, items.items.isEmpty { + let emptyStateView: ComponentView + var emptyStateTransition = Transition(transition) + if let current = self.emptyStateView { + emptyStateView = current + } else { + emptyStateTransition = .immediate + emptyStateView = ComponentView() + self.emptyStateView = emptyStateView + } + let emptyStateSize = emptyStateView.update( + transition: emptyStateTransition, + component: AnyComponent(EmptyStateIndicatorComponent( + context: self.context, + theme: presentationData.theme, + animationName: "", + title: "No saved stories", + text: "Open the Archive to select stories you want to be displayed in your profile.", + action: { + + } + )), + environment: {}, + containerSize: CGSize(width: size.width, height: size.height - topInset - bottomInset) + ) + if let emptyStateComponentView = emptyStateView.view { + if emptyStateComponentView.superview == nil { + self.view.addSubview(emptyStateComponentView) + } + emptyStateTransition.setFrame(view: emptyStateComponentView, frame: CGRect(origin: CGPoint(x: floor((size.width - emptyStateSize.width) * 0.5), y: topInset), size: emptyStateSize)) + } + } else if let emptyStateView = self.emptyStateView { + self.emptyStateView = nil + emptyStateView.view?.removeFromSuperview() + } transition.updateFrame(node: self.itemGrid, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: size.width, height: size.height))) if let items = self.items {