mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-15 21:45:19 +00:00
Move limits page to horizontal scroll
This commit is contained in:
parent
0ffcbf0b06
commit
f8c5bf2a6b
@ -17,7 +17,7 @@ import SolidRoundedButtonComponent
|
||||
import Markdown
|
||||
import TelegramUIPreferences
|
||||
|
||||
private final class GradientBackgroundComponent: Component {
|
||||
final class GradientBackgroundComponent: Component {
|
||||
public let colors: [UIColor]
|
||||
|
||||
public init(
|
||||
@ -153,7 +153,7 @@ final class DemoPageEnvironment: Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
private final class PageComponent<ChildEnvironment: Equatable>: CombinedComponent {
|
||||
final class PageComponent<ChildEnvironment: Equatable>: CombinedComponent {
|
||||
typealias EnvironmentType = ChildEnvironment
|
||||
|
||||
private let content: AnyComponent<ChildEnvironment>
|
||||
@ -263,7 +263,7 @@ private final class PageComponent<ChildEnvironment: Equatable>: CombinedComponen
|
||||
}
|
||||
}
|
||||
|
||||
private final class DemoPagerComponent: Component {
|
||||
final class DemoPagerComponent: Component {
|
||||
public final class Item: Equatable {
|
||||
public let content: AnyComponentWithIdentity<DemoPageEnvironment>
|
||||
|
||||
@ -282,40 +282,29 @@ private final class DemoPagerComponent: Component {
|
||||
|
||||
let items: [Item]
|
||||
let index: Int
|
||||
let activeColor: UIColor
|
||||
let inactiveColor: UIColor
|
||||
let updated: (CGFloat, Int) -> Void
|
||||
|
||||
public init(
|
||||
items: [Item],
|
||||
index: Int = 0,
|
||||
activeColor: UIColor,
|
||||
inactiveColor: UIColor
|
||||
updated: @escaping (CGFloat, Int) -> Void
|
||||
) {
|
||||
self.items = items
|
||||
self.index = index
|
||||
self.activeColor = activeColor
|
||||
self.inactiveColor = inactiveColor
|
||||
self.updated = updated
|
||||
}
|
||||
|
||||
public static func ==(lhs: DemoPagerComponent, rhs: DemoPagerComponent) -> Bool {
|
||||
if lhs.items != rhs.items {
|
||||
return false
|
||||
}
|
||||
if !lhs.activeColor.isEqual(rhs.activeColor) {
|
||||
return false
|
||||
}
|
||||
if !lhs.inactiveColor.isEqual(rhs.inactiveColor) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
fileprivate final class View: UIView, UIScrollViewDelegate {
|
||||
final class View: UIView, UIScrollViewDelegate {
|
||||
private let scrollView: UIScrollView
|
||||
private var itemViews: [AnyHashable: ComponentHostView<DemoPageEnvironment>] = [:]
|
||||
|
||||
private let pageIndicatorView: ComponentHostView<Empty>
|
||||
|
||||
private var component: DemoPagerComponent?
|
||||
|
||||
override init(frame: CGRect) {
|
||||
@ -327,15 +316,11 @@ private final class DemoPagerComponent: Component {
|
||||
self.scrollView.bounces = false
|
||||
self.scrollView.layer.cornerRadius = 10.0
|
||||
|
||||
self.pageIndicatorView = ComponentHostView<Empty>()
|
||||
self.pageIndicatorView.isUserInteractionEnabled = false
|
||||
|
||||
super.init(frame: frame)
|
||||
|
||||
self.scrollView.delegate = self
|
||||
|
||||
self.addSubview(self.scrollView)
|
||||
self.addSubview(self.pageIndicatorView)
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
@ -350,6 +335,7 @@ private final class DemoPagerComponent: Component {
|
||||
|
||||
self.ignoreContentOffsetChange = true
|
||||
let _ = self.update(component: component, availableSize: self.bounds.size, transition: .immediate)
|
||||
component.updated(self.scrollView.contentOffset.x / (self.scrollView.contentSize.width - self.scrollView.frame.width), component.items.count)
|
||||
self.ignoreContentOffsetChange = false
|
||||
}
|
||||
|
||||
@ -369,6 +355,7 @@ private final class DemoPagerComponent: Component {
|
||||
|
||||
if firstTime {
|
||||
self.scrollView.contentOffset = CGPoint(x: CGFloat(component.index) * availableSize.width, y: 0.0)
|
||||
component.updated(self.scrollView.contentOffset.x / (self.scrollView.contentSize.width - self.scrollView.frame.width), component.items.count)
|
||||
}
|
||||
let viewportCenter = self.scrollView.contentOffset.x + availableSize.width * 0.5
|
||||
|
||||
@ -398,7 +385,6 @@ private final class DemoPagerComponent: Component {
|
||||
itemView = ComponentHostView<DemoPageEnvironment>()
|
||||
self.itemViews[item.content.id] = itemView
|
||||
|
||||
|
||||
if item.content.id == (PremiumDemoScreen.Subject.fasterDownload as AnyHashable) {
|
||||
self.scrollView.insertSubview(itemView, at: 0)
|
||||
} else {
|
||||
@ -430,33 +416,15 @@ private final class DemoPagerComponent: Component {
|
||||
|
||||
self.component = component
|
||||
|
||||
if component.items.count > 1 {
|
||||
let pageIndicatorComponent = PageIndicatorComponent(
|
||||
pageCount: component.items.count,
|
||||
position: self.scrollView.contentOffset.x / (self.scrollView.contentSize.width - availableSize.width),
|
||||
inactiveColor: component.inactiveColor,
|
||||
activeColor: component.activeColor
|
||||
)
|
||||
let indicatorSize = self.pageIndicatorView.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(
|
||||
pageIndicatorComponent
|
||||
),
|
||||
environment: {},
|
||||
containerSize: availableSize
|
||||
)
|
||||
self.pageIndicatorView.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((availableSize.width - indicatorSize.width) / 2.0), y: availableSize.height - indicatorSize.height - 11.0), size: indicatorSize)
|
||||
}
|
||||
|
||||
return availableSize
|
||||
}
|
||||
}
|
||||
|
||||
public func makeView() -> View {
|
||||
func makeView() -> View {
|
||||
return View(frame: CGRect())
|
||||
}
|
||||
|
||||
public func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: Transition) -> CGSize {
|
||||
func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: Transition) -> CGSize {
|
||||
return view.update(component: self, availableSize: availableSize, transition: transition)
|
||||
}
|
||||
}
|
||||
@ -949,8 +917,7 @@ private final class DemoSheetContent: CombinedComponent {
|
||||
component: DemoPagerComponent(
|
||||
items: items,
|
||||
index: index,
|
||||
activeColor: UIColor(rgb: 0x7169ff),
|
||||
inactiveColor: theme.list.disclosureArrowColor
|
||||
updated: { _, _ in }
|
||||
),
|
||||
availableSize: CGSize(width: context.availableSize.width, height: context.availableSize.width + 154.0),
|
||||
transition: context.transition
|
||||
@ -1177,6 +1144,7 @@ private final class DemoSheetComponent: CombinedComponent {
|
||||
|
||||
public class PremiumDemoScreen: ViewControllerComponentContainer {
|
||||
public enum Subject {
|
||||
case doubleLimits
|
||||
case moreUpload
|
||||
case fasterDownload
|
||||
case voiceToText
|
||||
|
@ -361,21 +361,7 @@ private final class PremiumGiftScreenContentComponent: CombinedComponent {
|
||||
var demoSubject: PremiumDemoScreen.Subject
|
||||
switch perk {
|
||||
case .doubleLimits:
|
||||
var dismissImpl: (() -> Void)?
|
||||
let controller = PremimLimitsListScreen(context: accountContext, buttonText: strings.Premium_Gift_GiftSubscription(state?.price ?? "–").string, isPremium: false)
|
||||
controller.action = {
|
||||
dismissImpl?()
|
||||
buy()
|
||||
}
|
||||
controller.disposed = {
|
||||
// updateIsFocused(false)
|
||||
}
|
||||
present(controller)
|
||||
dismissImpl = { [weak controller] in
|
||||
controller?.dismiss(animated: true, completion: nil)
|
||||
}
|
||||
// updateIsFocused(true)
|
||||
return
|
||||
demoSubject = .doubleLimits
|
||||
case .moreUpload:
|
||||
demoSubject = .moreUpload
|
||||
case .fasterDownload:
|
||||
@ -402,20 +388,34 @@ private final class PremiumGiftScreenContentComponent: CombinedComponent {
|
||||
demoSubject = .emojiStatus
|
||||
}
|
||||
|
||||
let controller = PremiumDemoScreen(
|
||||
context: accountContext,
|
||||
subject: demoSubject,
|
||||
source: .gift(state?.price),
|
||||
order: state?.configuration.perks,
|
||||
action: {
|
||||
buy()
|
||||
}
|
||||
)
|
||||
var dismissImpl: (() -> Void)?
|
||||
let controller = PremiumLimitsListScreen(context: accountContext, subject: demoSubject, source: .gift(state?.price), order: state?.configuration.perks, buttonText: strings.Premium_Gift_GiftSubscription(state?.price ?? "–").string, isPremium: false)
|
||||
controller.action = {
|
||||
dismissImpl?()
|
||||
buy()
|
||||
}
|
||||
controller.disposed = {
|
||||
// updateIsFocused(false)
|
||||
// updateIsFocused(false)
|
||||
}
|
||||
present(controller)
|
||||
// updateIsFocused(true)
|
||||
dismissImpl = { [weak controller] in
|
||||
controller?.dismiss(animated: true, completion: nil)
|
||||
}
|
||||
|
||||
// let controller = PremiumDemoScreen(
|
||||
// context: accountContext,
|
||||
// subject: demoSubject,
|
||||
// source: .gift(state?.price),
|
||||
// order: state?.configuration.perks,
|
||||
// action: {
|
||||
// buy()
|
||||
// }
|
||||
// )
|
||||
// controller.disposed = {
|
||||
//// updateIsFocused(false)
|
||||
// }
|
||||
// present(controller)
|
||||
//// updateIsFocused(true)
|
||||
|
||||
addAppLogEvent(postbox: accountContext.account.postbox, type: "premium.promo_screen_tap", data: ["item": perk.identifier])
|
||||
}
|
||||
|
@ -1556,25 +1556,7 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
|
||||
var demoSubject: PremiumDemoScreen.Subject
|
||||
switch perk {
|
||||
case .doubleLimits:
|
||||
let isPremium = state?.isPremium == true
|
||||
|
||||
var dismissImpl: (() -> Void)?
|
||||
let controller = PremimLimitsListScreen(context: accountContext, buttonText: isPremium ? strings.Common_OK : (state?.isAnnual == true ? strings.Premium_SubscribeForAnnual(state?.price ?? "–").string : strings.Premium_SubscribeFor(state?.price ?? "–").string), isPremium: isPremium)
|
||||
controller.action = { [weak state] in
|
||||
dismissImpl?()
|
||||
if state?.isPremium == false {
|
||||
buy()
|
||||
}
|
||||
}
|
||||
controller.disposed = {
|
||||
updateIsFocused(false)
|
||||
}
|
||||
present(controller)
|
||||
dismissImpl = { [weak controller] in
|
||||
controller?.dismiss(animated: true, completion: nil)
|
||||
}
|
||||
updateIsFocused(true)
|
||||
return
|
||||
demoSubject = .doubleLimits
|
||||
case .moreUpload:
|
||||
demoSubject = .moreUpload
|
||||
case .fasterDownload:
|
||||
@ -1601,23 +1583,42 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
|
||||
demoSubject = .emojiStatus
|
||||
}
|
||||
|
||||
let controller = PremiumDemoScreen(
|
||||
context: accountContext,
|
||||
subject: demoSubject,
|
||||
source: .intro(state?.price),
|
||||
order: state?.configuration.perks,
|
||||
action: {
|
||||
if state?.isPremium == false {
|
||||
buy()
|
||||
}
|
||||
let isPremium = state?.isPremium == true
|
||||
|
||||
var dismissImpl: (() -> Void)?
|
||||
let controller = PremiumLimitsListScreen(context: accountContext, subject: demoSubject, source: .intro(state?.price), order: state?.configuration.perks, buttonText: isPremium ? strings.Common_OK : (state?.isAnnual == true ? strings.Premium_SubscribeForAnnual(state?.price ?? "–").string : strings.Premium_SubscribeFor(state?.price ?? "–").string), isPremium: isPremium)
|
||||
controller.action = { [weak state] in
|
||||
dismissImpl?()
|
||||
if state?.isPremium == false {
|
||||
buy()
|
||||
}
|
||||
)
|
||||
}
|
||||
controller.disposed = {
|
||||
updateIsFocused(false)
|
||||
}
|
||||
present(controller)
|
||||
dismissImpl = { [weak controller] in
|
||||
controller?.dismiss(animated: true, completion: nil)
|
||||
}
|
||||
updateIsFocused(true)
|
||||
|
||||
// let controller = PremiumDemoScreen(
|
||||
// context: accountContext,
|
||||
// subject: demoSubject,
|
||||
// source: .intro(state?.price),
|
||||
// order: state?.configuration.perks,
|
||||
// action: {
|
||||
// if state?.isPremium == false {
|
||||
// buy()
|
||||
// }
|
||||
// }
|
||||
// )
|
||||
// controller.disposed = {
|
||||
// updateIsFocused(false)
|
||||
// }
|
||||
// present(controller)
|
||||
// updateIsFocused(true)
|
||||
|
||||
addAppLogEvent(postbox: accountContext.account.postbox, type: "premium.promo_screen_tap", data: ["item": perk.identifier])
|
||||
}
|
||||
))
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -20,23 +20,26 @@ final class ScrollChildEnvironment: Equatable {
|
||||
}
|
||||
|
||||
final class ScrollComponent<ChildEnvironment: Equatable>: Component {
|
||||
public typealias EnvironmentType = ChildEnvironment
|
||||
typealias EnvironmentType = ChildEnvironment
|
||||
|
||||
public let content: AnyComponent<(ChildEnvironment, ScrollChildEnvironment)>
|
||||
public let contentInsets: UIEdgeInsets
|
||||
public let contentOffsetUpdated: (_ top: CGFloat, _ bottom: CGFloat) -> Void
|
||||
public let contentOffsetWillCommit: (UnsafeMutablePointer<CGPoint>) -> Void
|
||||
let content: AnyComponent<(ChildEnvironment, ScrollChildEnvironment)>
|
||||
let contentInsets: UIEdgeInsets
|
||||
let contentOffsetUpdated: (_ top: CGFloat, _ bottom: CGFloat) -> Void
|
||||
let contentOffsetWillCommit: (UnsafeMutablePointer<CGPoint>) -> Void
|
||||
let resetScroll: ActionSlot<Void>
|
||||
|
||||
public init(
|
||||
content: AnyComponent<(ChildEnvironment, ScrollChildEnvironment)>,
|
||||
contentInsets: UIEdgeInsets,
|
||||
contentOffsetUpdated: @escaping (_ top: CGFloat, _ bottom: CGFloat) -> Void,
|
||||
contentOffsetWillCommit: @escaping (UnsafeMutablePointer<CGPoint>) -> Void
|
||||
contentOffsetWillCommit: @escaping (UnsafeMutablePointer<CGPoint>) -> Void,
|
||||
resetScroll: ActionSlot<Void> = ActionSlot()
|
||||
) {
|
||||
self.content = content
|
||||
self.contentInsets = contentInsets
|
||||
self.contentOffsetUpdated = contentOffsetUpdated
|
||||
self.contentOffsetWillCommit = contentOffsetWillCommit
|
||||
self.resetScroll = resetScroll
|
||||
}
|
||||
|
||||
public static func ==(lhs: ScrollComponent, rhs: ScrollComponent) -> Bool {
|
||||
@ -46,7 +49,6 @@ final class ScrollComponent<ChildEnvironment: Equatable>: Component {
|
||||
if lhs.contentInsets != rhs.contentInsets {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@ -107,6 +109,10 @@ final class ScrollComponent<ChildEnvironment: Equatable>: Component {
|
||||
)
|
||||
transition.setFrame(view: self.contentView, frame: CGRect(origin: .zero, size: contentSize), completion: nil)
|
||||
|
||||
component.resetScroll.connect { [weak self] _ in
|
||||
self?.setContentOffset(.zero, animated: false)
|
||||
}
|
||||
|
||||
if self.contentSize != contentSize {
|
||||
self.ignoreDidScroll = true
|
||||
self.contentSize = contentSize
|
||||
|
@ -8,7 +8,8 @@ private let whitelistedHosts: Set<String> = Set([
|
||||
"t.me",
|
||||
"telegram.me",
|
||||
"telegra.ph",
|
||||
"telesco.pe"
|
||||
"telesco.pe",
|
||||
"fragment.com"
|
||||
])
|
||||
|
||||
private let dataDetector = try? NSDataDetector(types: NSTextCheckingResult.CheckingType([.link]).rawValue)
|
||||
|
@ -4,7 +4,8 @@ private let whitelistedHosts: Set<String> = Set([
|
||||
"t.me",
|
||||
"telegram.me",
|
||||
"telegra.ph",
|
||||
"telesco.pe"
|
||||
"telesco.pe",
|
||||
"fragment.com"
|
||||
])
|
||||
|
||||
public func isConcealedUrlWhitelisted(_ url: URL) -> Bool {
|
||||
|
Loading…
x
Reference in New Issue
Block a user