Business intro screen

This commit is contained in:
Ilya Laktyushin 2024-02-16 15:29:55 -04:00
parent ba24da0593
commit 16903cdffd
50 changed files with 4424 additions and 357 deletions

View File

@ -11315,3 +11315,44 @@ Sorry for the inconvenience.";
"ChannelBoost.Header.Giveaway" = "giveaway";
"ChannelBoost.Header.Features" = "features";
"Premium.Business" = "Telegram Business";
"Premium.BusinessInfo" = "Upgrade your account with business features such as location, opening hours and quick replies.";
"Premium.Business.Location.Title" = "Location";
"Premium.Business.Location.Text" = "Display the location of your business on your account.";
"Premium.Business.Hours.Title" = "Opening Hours";
"Premium.Business.Hours.Text" = "Show to your customers when you are
open for business.";
"Premium.Business.Replies.Title" = "Quick Replies";
"Premium.Business.Replies.Text" = "Set up shortcuts with rich text and media
to respond to messages faster.";
"Premium.Business.Greetings.Title" = "Greeting Messages";
"Premium.Business.Greetings.Text" = "Create greetings that will be automatically sent to new customers.";
"Premium.Business.Away.Title" = "Away Messages";
"Premium.Business.Away.Text" = "Define messages that are automatically sent when you are off.";
"Premium.Business.Chatbots.Title" = "Chatbots";
"Premium.Business.Chatbots.Text" = "Add any third party chatbots that will process customer interactions.";
"Business.Title" = "Telegram Business";
"Business.Description" = "Turn your account into a **business page** with these additional features.";
"Business.SubscribedDescription" = "You have now unlocked these additional business features.";
"Business.PlusPremiumFeatures" = "+20 MORE TELEGRAM PREMIUM FEATURES";
"Business.Location" = "Location";
"Business.OpeningHours" = "Opening Hours";
"Business.QuickReplies" = "Quick Replies";
"Business.GreetingMessages" = "Greeting Messages";
"Business.AwayMessages" = "Away Messages";
"Business.Chatbots" = "Chatbots";
"Business.LocationInfo" = "Display the location of your business on your account.";
"Business.OpeningHoursInfo" = "Show to your customers when you are open for business.";
"Business.QuickRepliesInfo" = "Set up shortcuts with rich text and media to respond to messages faster.";
"Business.GreetingMessagesInfo" = "Create greetings that will be automatically sent to new customers.";
"Business.AwayMessagesInfo" = "Define messages that are automatically sent when you are off.";
"Business.ChatbotsInfo" = "Add any third-party chatbots that will process customer interactions.";

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 9.0 KiB

View File

@ -0,0 +1,650 @@
import Foundation
import UIKit
import Display
import ComponentFlow
import SwiftSignalKit
import TelegramCore
import AccountContext
import MultilineTextComponent
import BlurredBackgroundComponent
import Markdown
import TelegramPresentationData
import BundleIconComponent
private final class HeaderComponent: Component {
let context: AccountContext
let theme: PresentationTheme
init(context: AccountContext, theme: PresentationTheme) {
self.context = context
self.theme = theme
}
static func ==(lhs: HeaderComponent, rhs: HeaderComponent) -> Bool {
if lhs.context !== rhs.context {
return false
}
if lhs.theme !== rhs.theme {
return false
}
return true
}
final class View: UIView {
private let coin = ComponentView<Empty>()
private let text = ComponentView<Empty>()
private var component: HeaderComponent?
private weak var state: EmptyComponentState?
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func update(component: HeaderComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: Transition) -> CGSize {
self.component = component
self.state = state
let containerSize = CGSize(width: min(414.0, availableSize.width), height: 220.0)
let coinSize = self.coin.update(
transition: .immediate,
component: AnyComponent(PremiumCoinComponent(isIntro: true, isVisible: true, hasIdleAnimations: true)),
environment: {},
containerSize: containerSize
)
if let view = self.coin.view {
if view.superview == nil {
self.addSubview(view)
}
view.frame = CGRect(origin: CGPoint(x: floor((availableSize.width - coinSize.width) / 2.0), y: -90.0), size: coinSize)
}
let textSize = self.text.update(
transition: .immediate,
component: AnyComponent(
MultilineTextComponent(
text: .plain(NSAttributedString(string: "Turn your account to a business page with these additional features.", font: Font.regular(15.0), textColor: .black)),
horizontalAlignment: .center,
maximumNumberOfLines: 0,
lineSpacing: 0.2
)
),
environment: {},
containerSize: CGSize(width: availableSize.width - 32.0, height: 1000.0)
)
if let view = text.view {
if view.superview == nil {
self.addSubview(view)
}
view.frame = CGRect(origin: CGPoint(x: floor((availableSize.width - textSize.width) / 2.0), y: 118.0), size: textSize)
}
return CGSize(width: availableSize.width, height: 189.0)
}
}
func makeView() -> View {
return View(frame: CGRect())
}
func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: Transition) -> CGSize {
return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition)
}
}
private final class ParagraphComponent: CombinedComponent {
let title: String
let titleColor: UIColor
let text: String
let textColor: UIColor
let iconName: String
let iconColor: UIColor
public init(
title: String,
titleColor: UIColor,
text: String,
textColor: UIColor,
iconName: String,
iconColor: UIColor
) {
self.title = title
self.titleColor = titleColor
self.text = text
self.textColor = textColor
self.iconName = iconName
self.iconColor = iconColor
}
static func ==(lhs: ParagraphComponent, rhs: ParagraphComponent) -> Bool {
if lhs.title != rhs.title {
return false
}
if lhs.titleColor != rhs.titleColor {
return false
}
if lhs.text != rhs.text {
return false
}
if lhs.textColor != rhs.textColor {
return false
}
if lhs.iconName != rhs.iconName {
return false
}
if lhs.iconColor != rhs.iconColor {
return false
}
return true
}
static var body: Body {
let title = Child(MultilineTextComponent.self)
let text = Child(MultilineTextComponent.self)
let icon = Child(BundleIconComponent.self)
return { context in
let component = context.component
let leftInset: CGFloat = 64.0
let rightInset: CGFloat = 32.0
let textSideInset: CGFloat = leftInset + 8.0
let spacing: CGFloat = 5.0
let textTopInset: CGFloat = 9.0
let title = title.update(
component: MultilineTextComponent(
text: .plain(NSAttributedString(
string: component.title,
font: Font.semibold(15.0),
textColor: component.titleColor,
paragraphAlignment: .natural
)),
horizontalAlignment: .center,
maximumNumberOfLines: 1
),
availableSize: CGSize(width: context.availableSize.width - leftInset - rightInset, height: CGFloat.greatestFiniteMagnitude),
transition: .immediate
)
let textFont = Font.regular(15.0)
let boldTextFont = Font.semibold(15.0)
let textColor = component.textColor
let markdownAttributes = MarkdownAttributes(
body: MarkdownAttributeSet(font: textFont, textColor: textColor),
bold: MarkdownAttributeSet(font: boldTextFont, textColor: textColor),
link: MarkdownAttributeSet(font: textFont, textColor: textColor),
linkAttribute: { _ in
return nil
}
)
let text = text.update(
component: MultilineTextComponent(
text: .markdown(text: component.text, attributes: markdownAttributes),
horizontalAlignment: .natural,
maximumNumberOfLines: 0,
lineSpacing: 0.2
),
availableSize: CGSize(width: context.availableSize.width - leftInset - rightInset, height: context.availableSize.height),
transition: .immediate
)
let icon = icon.update(
component: BundleIconComponent(
name: component.iconName,
tintColor: component.iconColor
),
availableSize: CGSize(width: context.availableSize.width, height: context.availableSize.height),
transition: .immediate
)
context.add(title
.position(CGPoint(x: textSideInset + title.size.width / 2.0, y: textTopInset + title.size.height / 2.0))
)
context.add(text
.position(CGPoint(x: textSideInset + text.size.width / 2.0, y: textTopInset + title.size.height + spacing + text.size.height / 2.0))
)
context.add(icon
.position(CGPoint(x: 47.0, y: textTopInset + 18.0))
)
return CGSize(width: context.availableSize.width, height: textTopInset + title.size.height + text.size.height + 25.0)
}
}
}
private final class BusinessListComponent: CombinedComponent {
typealias EnvironmentType = (Empty, ScrollChildEnvironment)
let context: AccountContext
let theme: PresentationTheme
let topInset: CGFloat
let bottomInset: CGFloat
init(context: AccountContext, theme: PresentationTheme, topInset: CGFloat, bottomInset: CGFloat) {
self.context = context
self.theme = theme
self.topInset = topInset
self.bottomInset = bottomInset
}
static func ==(lhs: BusinessListComponent, rhs: BusinessListComponent) -> Bool {
if lhs.context !== rhs.context {
return false
}
if lhs.theme !== rhs.theme {
return false
}
if lhs.topInset != rhs.topInset {
return false
}
if lhs.bottomInset != rhs.bottomInset {
return false
}
return true
}
final class State: ComponentState {
private let context: AccountContext
private var disposable: Disposable?
var limits: EngineConfiguration.UserLimits = .defaultValue
var premiumLimits: EngineConfiguration.UserLimits = .defaultValue
var accountPeer: EnginePeer?
init(context: AccountContext) {
self.context = context
super.init()
self.disposable = (context.engine.data.get(
TelegramEngine.EngineData.Item.Configuration.UserLimits(isPremium: false),
TelegramEngine.EngineData.Item.Configuration.UserLimits(isPremium: true),
TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId)
)
|> deliverOnMainQueue).start(next: { [weak self] limits, premiumLimits, accountPeer in
if let strongSelf = self {
strongSelf.limits = limits
strongSelf.premiumLimits = premiumLimits
strongSelf.accountPeer = accountPeer
strongSelf.updated(transition: .immediate)
}
})
}
deinit {
self.disposable?.dispose()
}
}
func makeState() -> State {
return State(context: self.context)
}
static var body: Body {
let list = Child(List<Empty>.self)
return { context in
let theme = context.component.theme
let strings = context.component.context.sharedContext.currentPresentationData.with { $0 }.strings
let colors = [
UIColor(rgb: 0x007aff),
UIColor(rgb: 0x798aff),
UIColor(rgb: 0xac64f3),
UIColor(rgb: 0xc456ae),
UIColor(rgb: 0xe95d44),
UIColor(rgb: 0xf2822a),
UIColor(rgb: 0xe79519),
UIColor(rgb: 0xe7ad19)
]
let titleColor = theme.list.itemPrimaryTextColor
let textColor = theme.list.itemSecondaryTextColor
var items: [AnyComponentWithIdentity<Empty>] = []
items.append(
AnyComponentWithIdentity(
id: "header",
component: AnyComponent(HeaderComponent(
context: context.component.context,
theme: theme
))
)
)
items.append(
AnyComponentWithIdentity(
id: "location",
component: AnyComponent(ParagraphComponent(
title: strings.Premium_Business_Location_Title,
titleColor: titleColor,
text: strings.Premium_Business_Location_Text,
textColor: textColor,
iconName: "Premium/Business/Location",
iconColor: colors[0]
))
)
)
items.append(
AnyComponentWithIdentity(
id: "hours",
component: AnyComponent(ParagraphComponent(
title: strings.Premium_Business_Hours_Title,
titleColor: titleColor,
text: strings.Premium_Business_Hours_Text,
textColor: textColor,
iconName: "Premium/Business/Hours",
iconColor: colors[1]
))
)
)
items.append(
AnyComponentWithIdentity(
id: "replies",
component: AnyComponent(ParagraphComponent(
title: strings.Premium_Business_Replies_Title,
titleColor: titleColor,
text: strings.Premium_Business_Replies_Text,
textColor: textColor,
iconName: "Premium/Business/Replies",
iconColor: colors[2]
))
)
)
items.append(
AnyComponentWithIdentity(
id: "greetings",
component: AnyComponent(ParagraphComponent(
title: strings.Premium_Business_Greetings_Title,
titleColor: titleColor,
text: strings.Premium_Business_Greetings_Text,
textColor: textColor,
iconName: "Premium/Business/Greetings",
iconColor: colors[3]
))
)
)
items.append(
AnyComponentWithIdentity(
id: "away",
component: AnyComponent(ParagraphComponent(
title: strings.Premium_Business_Away_Title,
titleColor: titleColor,
text: strings.Premium_Business_Away_Text,
textColor: textColor,
iconName: "Premium/Business/Away",
iconColor: colors[4]
))
)
)
items.append(
AnyComponentWithIdentity(
id: "chatbots",
component: AnyComponent(ParagraphComponent(
title: strings.Premium_Business_Chatbots_Title,
titleColor: titleColor,
text: strings.Premium_Business_Chatbots_Text,
textColor: textColor,
iconName: "Premium/Business/Chatbots",
iconColor: colors[5]
))
)
)
let list = list.update(
component: List(items),
availableSize: CGSize(width: context.availableSize.width, height: 10000.0),
transition: context.transition
)
let contentHeight = context.component.topInset + list.size.height + context.component.bottomInset
context.add(list
.position(CGPoint(x: list.size.width / 2.0, y: context.component.topInset + list.size.height / 2.0))
)
return CGSize(width: context.availableSize.width, height: contentHeight)
}
}
}
final class BusinessPageComponent: CombinedComponent {
typealias EnvironmentType = DemoPageEnvironment
let context: AccountContext
let theme: PresentationTheme
let neighbors: PageNeighbors
let bottomInset: CGFloat
let updatedBottomAlpha: (CGFloat) -> Void
let updatedDismissOffset: (CGFloat) -> Void
let updatedIsDisplaying: (Bool) -> Void
init(context: AccountContext, theme: PresentationTheme, neighbors: PageNeighbors, bottomInset: CGFloat, updatedBottomAlpha: @escaping (CGFloat) -> Void, updatedDismissOffset: @escaping (CGFloat) -> Void, updatedIsDisplaying: @escaping (Bool) -> Void) {
self.context = context
self.theme = theme
self.neighbors = neighbors
self.bottomInset = bottomInset
self.updatedBottomAlpha = updatedBottomAlpha
self.updatedDismissOffset = updatedDismissOffset
self.updatedIsDisplaying = updatedIsDisplaying
}
static func ==(lhs: BusinessPageComponent, rhs: BusinessPageComponent) -> Bool {
if lhs.context !== rhs.context {
return false
}
if lhs.theme !== rhs.theme {
return false
}
if lhs.neighbors != rhs.neighbors {
return false
}
if lhs.bottomInset != rhs.bottomInset {
return false
}
return true
}
final class State: ComponentState {
let updateBottomAlpha: (CGFloat) -> Void
let updateDismissOffset: (CGFloat) -> Void
let updatedIsDisplaying: (Bool) -> Void
var resetScroll: ActionSlot<Void>?
var topContentOffset: CGFloat = 0.0
var bottomContentOffset: CGFloat = 100.0 {
didSet {
self.updateAlpha()
}
}
var position: CGFloat? {
didSet {
self.updateAlpha()
}
}
var isDisplaying = false {
didSet {
if oldValue != self.isDisplaying {
self.updatedIsDisplaying(self.isDisplaying)
if !self.isDisplaying {
self.resetScroll?.invoke(Void())
}
}
}
}
var neighbors = PageNeighbors(leftIsList: false, rightIsList: false)
init(updateBottomAlpha: @escaping (CGFloat) -> Void, updateDismissOffset: @escaping (CGFloat) -> Void, updateIsDisplaying: @escaping (Bool) -> Void) {
self.updateBottomAlpha = updateBottomAlpha
self.updateDismissOffset = updateDismissOffset
self.updatedIsDisplaying = updateIsDisplaying
super.init()
}
func updateAlpha() {
var dismissToLeft = false
if let position = self.position, position > 0.0 {
dismissToLeft = true
}
var dismissPosition = min(1.0, abs(self.position ?? 0.0) / 1.3333)
var position = min(1.0, abs(self.position ?? 0.0))
if position > 0.001, (dismissToLeft && self.neighbors.leftIsList) || (!dismissToLeft && self.neighbors.rightIsList) {
dismissPosition = 0.0
position = 1.0
}
self.updateDismissOffset(dismissPosition)
let verticalPosition = 1.0 - min(30.0, self.bottomContentOffset) / 30.0
let backgroundAlpha: CGFloat = max(position, verticalPosition)
self.updateBottomAlpha(backgroundAlpha)
}
}
func makeState() -> State {
return State(updateBottomAlpha: self.updatedBottomAlpha, updateDismissOffset: self.updatedDismissOffset, updateIsDisplaying: self.updatedIsDisplaying)
}
static var body: Body {
let background = Child(Rectangle.self)
let scroll = Child(ScrollComponent<Empty>.self)
let topPanel = Child(BlurredBackgroundComponent.self)
let topSeparator = Child(Rectangle.self)
let title = Child(MultilineTextComponent.self)
let resetScroll = ActionSlot<Void>()
return { context in
let state = context.state
let environment = context.environment[DemoPageEnvironment.self].value
state.neighbors = context.component.neighbors
state.resetScroll = resetScroll
state.position = environment.position
state.isDisplaying = environment.isDisplaying
let theme = context.component.theme
// let strings = context.component.context.sharedContext.currentPresentationData.with { $0 }.strings
let topInset: CGFloat = 56.0
let scroll = scroll.update(
component: ScrollComponent<Empty>(
content: AnyComponent(
BusinessListComponent(
context: context.component.context,
theme: theme,
topInset: topInset,
bottomInset: context.component.bottomInset + 110.0
)
),
contentInsets: UIEdgeInsets(top: topInset, left: 0.0, bottom: 0.0, right: 0.0),
contentOffsetUpdated: { [weak state] topContentOffset, bottomContentOffset in
state?.topContentOffset = topContentOffset
state?.bottomContentOffset = bottomContentOffset
Queue.mainQueue().justDispatch {
state?.updated(transition: .immediate)
}
},
contentOffsetWillCommit: { _ in },
resetScroll: resetScroll
),
availableSize: context.availableSize,
transition: context.transition
)
let background = background.update(
component: Rectangle(color: theme.overallDarkAppearance ? theme.list.blocksBackgroundColor : theme.list.plainBackgroundColor),
availableSize: scroll.size,
transition: context.transition
)
context.add(background
.position(CGPoint(x: context.availableSize.width / 2.0, y: background.size.height / 2.0))
)
context.add(scroll
.position(CGPoint(x: context.availableSize.width / 2.0, y: scroll.size.height / 2.0))
)
let topPanel = topPanel.update(
component: BlurredBackgroundComponent(
color: theme.rootController.navigationBar.blurredBackgroundColor
),
availableSize: CGSize(width: context.availableSize.width, height: topInset),
transition: context.transition
)
let topSeparator = topSeparator.update(
component: Rectangle(
color: theme.rootController.navigationBar.separatorColor
),
availableSize: CGSize(width: context.availableSize.width, height: UIScreenPixel),
transition: context.transition
)
//TODO:localize
let title = title.update(
component: MultilineTextComponent(
text: .plain(NSAttributedString(string: "Telegram Business", font: Font.semibold(20.0), textColor: theme.rootController.navigationBar.primaryTextColor)),
horizontalAlignment: .center,
truncationType: .end,
maximumNumberOfLines: 1
),
availableSize: context.availableSize,
transition: context.transition
)
let topPanelAlpha: CGFloat
if state.topContentOffset > 78.0 {
topPanelAlpha = min(30.0, state.topContentOffset - 78.0) / 30.0
} else {
topPanelAlpha = 0.0
}
context.add(topPanel
.position(CGPoint(x: context.availableSize.width / 2.0, y: topPanel.size.height / 2.0))
.opacity(topPanelAlpha)
)
context.add(topSeparator
.position(CGPoint(x: context.availableSize.width / 2.0, y: topPanel.size.height))
.opacity(topPanelAlpha)
)
let titleTopOriginY = topPanel.size.height / 2.0
let titleBottomOriginY: CGFloat = 155.0
let titleOriginDelta = titleTopOriginY - titleBottomOriginY
let fraction = min(1.0, state.topContentOffset / abs(titleOriginDelta))
let titleOriginY: CGFloat = titleBottomOriginY + fraction * titleOriginDelta
let titleScale = 1.0 - max(0.0, fraction * 0.2)
context.add(title
.position(CGPoint(x: context.availableSize.width / 2.0, y: titleOriginY))
.scale(titleScale)
)
return scroll.size
}
}
}

View File

@ -0,0 +1,536 @@
import Foundation
import UIKit
import Display
import ComponentFlow
import SwiftSignalKit
import SceneKit
import GZip
import AppBundle
import LegacyComponents
private let sceneVersion: Int = 1
private func deg2rad(_ number: Float) -> Float {
return number * .pi / 180
}
private func rad2deg(_ number: Float) -> Float {
return number * 180.0 / .pi
}
class PremiumCoinComponent: Component {
let isIntro: Bool
let isVisible: Bool
let hasIdleAnimations: Bool
init(isIntro: Bool, isVisible: Bool, hasIdleAnimations: Bool) {
self.isIntro = isIntro
self.isVisible = isVisible
self.hasIdleAnimations = hasIdleAnimations
}
static func ==(lhs: PremiumCoinComponent, rhs: PremiumCoinComponent) -> Bool {
return lhs.isIntro == rhs.isIntro && lhs.isVisible == rhs.isVisible && lhs.hasIdleAnimations == rhs.hasIdleAnimations
}
final class View: UIView, SCNSceneRendererDelegate, ComponentTaggedView {
final class Tag {
}
func matches(tag: Any) -> Bool {
if let _ = tag as? Tag {
return true
}
return false
}
private var _ready = Promise<Bool>()
var ready: Signal<Bool, NoError> {
return self._ready.get()
}
weak var animateFrom: UIView?
weak var containerView: UIView?
private let sceneView: SCNView
private var previousInteractionTimestamp: Double = 0.0
private var timer: SwiftSignalKit.Timer?
private var hasIdleAnimations = false
private let isIntro: Bool
init(frame: CGRect, isIntro: Bool) {
self.isIntro = isIntro
self.sceneView = SCNView(frame: CGRect(origin: .zero, size: CGSize(width: 64.0, height: 64.0)))
self.sceneView.backgroundColor = .clear
self.sceneView.transform = CGAffineTransform(scaleX: 0.5, y: 0.5)
self.sceneView.isUserInteractionEnabled = false
self.sceneView.preferredFramesPerSecond = 60
self.sceneView.isJitteringEnabled = true
super.init(frame: frame)
self.addSubview(self.sceneView)
self.setup()
let panGestureRecoginzer = UIPanGestureRecognizer(target: self, action: #selector(self.handlePan(_:)))
self.addGestureRecognizer(panGestureRecoginzer)
let tapGestureRecoginzer = UITapGestureRecognizer(target: self, action: #selector(self.handleTap(_:)))
self.addGestureRecognizer(tapGestureRecoginzer)
self.disablesInteractiveModalDismiss = true
self.disablesInteractiveTransitionGestureRecognizer = true
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
deinit {
self.timer?.invalidate()
}
private let hapticFeedback = HapticFeedback()
private var delayTapsTill: Double?
@objc private func handleTap(_ gesture: UITapGestureRecognizer) {
guard let scene = self.sceneView.scene, let node = scene.rootNode.childNode(withName: "star", recursively: false) else {
return
}
let currentTime = CACurrentMediaTime()
self.previousInteractionTimestamp = currentTime
if let delayTapsTill = self.delayTapsTill, currentTime < delayTapsTill {
return
}
var left: Bool?
var top: Bool?
if let view = gesture.view {
let point = gesture.location(in: view)
let horizontalDistanceFromCenter = abs(point.x - view.frame.size.width / 2.0)
if horizontalDistanceFromCenter > 60.0 {
return
}
let verticalDistanceFromCenter = abs(point.y - view.frame.size.height / 2.0)
if horizontalDistanceFromCenter > 20.0 {
left = point.x < view.frame.width / 2.0
}
if verticalDistanceFromCenter > 20.0 {
top = point.y < view.frame.height / 2.0
}
}
if node.animationKeys.contains("tapRotate"), let left = left {
self.playAppearanceAnimation(velocity: nil, mirror: left, explode: true)
self.hapticFeedback.impact(.medium)
return
}
let initial = node.eulerAngles
var yaw: CGFloat = 0.0
var pitch: CGFloat = 0.0
if let left = left {
yaw = left ? -0.6 : 0.6
}
if let top = top {
pitch = top ? -0.3 : 0.3
}
let target = SCNVector3(pitch, yaw, 0.0)
let animation = CABasicAnimation(keyPath: "eulerAngles")
animation.fromValue = NSValue(scnVector3: initial)
animation.toValue = NSValue(scnVector3: target)
animation.duration = 0.25
animation.timingFunction = CAMediaTimingFunction(name: .easeOut)
animation.fillMode = .forwards
node.addAnimation(animation, forKey: "tapRotate")
node.eulerAngles = target
Queue.mainQueue().after(0.25) {
node.eulerAngles = initial
let springAnimation = CASpringAnimation(keyPath: "eulerAngles")
springAnimation.fromValue = NSValue(scnVector3: target)
springAnimation.toValue = NSValue(scnVector3: SCNVector3(x: 0.0, y: 0.0, z: 0.0))
springAnimation.mass = 1.0
springAnimation.stiffness = 21.0
springAnimation.damping = 5.8
springAnimation.duration = springAnimation.settlingDuration * 0.8
node.addAnimation(springAnimation, forKey: "tapRotate")
}
self.hapticFeedback.tap()
}
private var previousYaw: Float = 0.0
@objc private func handlePan(_ gesture: UIPanGestureRecognizer) {
guard let scene = self.sceneView.scene, let node = scene.rootNode.childNode(withName: "star", recursively: false) else {
return
}
self.previousInteractionTimestamp = CACurrentMediaTime()
let keys = [
"rotate",
"tapRotate"
]
for key in keys {
node.removeAnimation(forKey: key)
}
switch gesture.state {
case .began:
self.previousYaw = 0.0
case .changed:
let translation = gesture.translation(in: gesture.view)
let yawPan = deg2rad(Float(translation.x))
func rubberBandingOffset(offset: CGFloat, bandingStart: CGFloat) -> CGFloat {
let bandedOffset = offset - bandingStart
let range: CGFloat = 60.0
let coefficient: CGFloat = 0.4
return bandingStart + (1.0 - (1.0 / ((bandedOffset * coefficient / range) + 1.0))) * range
}
var pitchTranslation = rubberBandingOffset(offset: abs(translation.y), bandingStart: 0.0)
if translation.y < 0.0 {
pitchTranslation *= -1.0
}
let pitchPan = deg2rad(Float(pitchTranslation))
self.previousYaw = yawPan
node.eulerAngles = SCNVector3(pitchPan, yawPan, 0.0)
case .ended:
let velocity = gesture.velocity(in: gesture.view)
var smallAngle = false
if (self.previousYaw < .pi / 2 && self.previousYaw > -.pi / 2) && abs(velocity.x) < 200 {
smallAngle = true
}
self.playAppearanceAnimation(velocity: velocity.x, smallAngle: smallAngle, explode: !smallAngle && abs(velocity.x) > 600)
node.eulerAngles = SCNVector3(0.0, 0.0, 0.0)
default:
break
}
}
private func setup() {
let resourceUrl: URL
if let url = getAppBundle().url(forResource: "coin", withExtension: "scn") {
resourceUrl = url
} else {
let fileName = "coin_\(sceneVersion).scn"
let tmpUrl = URL(fileURLWithPath: NSTemporaryDirectory() + fileName)
if !FileManager.default.fileExists(atPath: tmpUrl.path) {
guard let url = getAppBundle().url(forResource: "coin", withExtension: ""),
let compressedData = try? Data(contentsOf: url),
let decompressedData = TGGUnzipData(compressedData, 8 * 1024 * 1024) else {
return
}
try? decompressedData.write(to: tmpUrl)
}
resourceUrl = tmpUrl
}
guard let scene = try? SCNScene(url: resourceUrl, options: nil) else {
return
}
self.sceneView.scene = scene
self.sceneView.delegate = self
let _ = self.sceneView.snapshot()
}
private var didSetReady = false
func renderer(_ renderer: SCNSceneRenderer, didRenderScene scene: SCNScene, atTime time: TimeInterval) {
if !self.didSetReady {
self.didSetReady = true
Queue.mainQueue().justDispatch {
self._ready.set(.single(true))
self.onReady()
}
}
}
private func maybeAnimateIn() {
guard let scene = self.sceneView.scene, let _ = scene.rootNode.childNode(withName: "star", recursively: false), let animateFrom = self.animateFrom, var containerView = self.containerView else {
return
}
containerView = containerView.subviews[2].subviews[1]
let initialPosition = self.sceneView.center
let targetPosition = self.sceneView.superview!.convert(self.sceneView.center, to: containerView)
let sourcePosition = animateFrom.superview!.convert(animateFrom.center, to: containerView).offsetBy(dx: 0.0, dy: -20.0)
containerView.addSubview(self.sceneView)
self.sceneView.center = targetPosition
animateFrom.alpha = 0.0
self.sceneView.layer.animateScale(from: 0.05, to: 0.5, duration: 1.0, timingFunction: kCAMediaTimingFunctionSpring)
self.sceneView.layer.animatePosition(from: sourcePosition, to: targetPosition, duration: 1.0, timingFunction: kCAMediaTimingFunctionSpring, completion: { _ in
self.addSubview(self.sceneView)
self.sceneView.center = initialPosition
})
Queue.mainQueue().after(0.4, {
animateFrom.alpha = 1.0
})
self.animateFrom = nil
self.containerView = nil
}
private func onReady() {
self.setupScaleAnimation()
self.setupGradientAnimation()
self.setupShineAnimation()
self.maybeAnimateIn()
self.playAppearanceAnimation(explode: true)
self.previousInteractionTimestamp = CACurrentMediaTime()
self.timer = SwiftSignalKit.Timer(timeout: 1.0, repeat: true, completion: { [weak self] in
if let strongSelf = self, strongSelf.hasIdleAnimations {
let currentTimestamp = CACurrentMediaTime()
if currentTimestamp > strongSelf.previousInteractionTimestamp + 5.0 {
strongSelf.playAppearanceAnimation()
}
}
}, queue: Queue.mainQueue())
self.timer?.start()
}
private func setupScaleAnimation() {
guard let scene = self.sceneView.scene, let node = scene.rootNode.childNode(withName: "star", recursively: false) else {
return
}
let fromScale: Float = 0.9
let toScale: Float = 1.0
let animation = CABasicAnimation(keyPath: "scale")
animation.duration = 2.0
animation.fromValue = NSValue(scnVector3: SCNVector3(x: fromScale, y: fromScale, z: fromScale))
animation.toValue = NSValue(scnVector3: SCNVector3(x: toScale, y: toScale, z: toScale))
animation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
animation.autoreverses = true
animation.repeatCount = .infinity
node.addAnimation(animation, forKey: "scale")
}
private func setupGradientAnimation() {
guard let scene = self.sceneView.scene, let node = scene.rootNode.childNode(withName: "star", recursively: false) else {
return
}
guard let first = node.childNodes.first, let last = node.childNodes.last else {
return
}
let nodes = [first, last]
for node in nodes {
guard let initial = node.geometry?.materials.first?.diffuse.contentsTransform else {
return
}
let animation = CABasicAnimation(keyPath: "contentsTransform")
animation.duration = 4.5
animation.fromValue = NSValue(scnMatrix4: initial)
animation.toValue = NSValue(scnMatrix4: SCNMatrix4Translate(initial, -0.35, 0.35, 0))
animation.timingFunction = CAMediaTimingFunction(name: .linear)
animation.autoreverses = true
animation.repeatCount = .infinity
node.geometry?.materials.first?.diffuse.addAnimation(animation, forKey: "gradient")
}
}
private func setupShineAnimation() {
guard let scene = self.sceneView.scene, let node = scene.rootNode.childNode(withName: "star", recursively: false) else {
return
}
guard let first = node.childNodes.first, let last = node.childNodes.last else {
return
}
let nodes = [first, last]
for node in nodes {
guard let initial = node.geometry?.materials.first?.emission.contentsTransform else {
return
}
if #available(iOS 17.0, *), let material = node.geometry?.materials.first {
material.metalness.intensity = 0.3
}
let animation = CABasicAnimation(keyPath: "contentsTransform")
animation.fillMode = .forwards
animation.fromValue = NSValue(scnMatrix4: initial)
animation.toValue = NSValue(scnMatrix4: SCNMatrix4Translate(initial, -1.6, 0.0, 0.0))
animation.timingFunction = CAMediaTimingFunction(name: .easeOut)
animation.beginTime = 1.1
animation.duration = 0.9
let group = CAAnimationGroup()
group.animations = [animation]
group.beginTime = 1.0
group.duration = 4.0
group.repeatCount = .infinity
node.geometry?.materials.first?.emission.addAnimation(group, forKey: "shimmer")
}
}
private func playAppearanceAnimation(velocity: CGFloat? = nil, smallAngle: Bool = false, mirror: Bool = false, explode: Bool = false) {
guard let scene = self.sceneView.scene, let node = scene.rootNode.childNode(withName: "star", recursively: false) else {
return
}
let currentTime = CACurrentMediaTime()
self.previousInteractionTimestamp = currentTime
self.delayTapsTill = currentTime + 0.85
if explode, let node = scene.rootNode.childNode(withName: "swirl", recursively: false), let particlesLeft = scene.rootNode.childNode(withName: "particles_left", recursively: false), let particlesRight = scene.rootNode.childNode(withName: "particles_right", recursively: false), let particlesBottomLeft = scene.rootNode.childNode(withName: "particles_left_bottom", recursively: false), let particlesBottomRight = scene.rootNode.childNode(withName: "particles_right_bottom", recursively: false) {
if let leftParticleSystem = particlesLeft.particleSystems?.first, let rightParticleSystem = particlesRight.particleSystems?.first, let leftBottomParticleSystem = particlesBottomLeft.particleSystems?.first, let rightBottomParticleSystem = particlesBottomRight.particleSystems?.first {
leftParticleSystem.speedFactor = 2.0
leftParticleSystem.particleVelocity = 1.6
leftParticleSystem.birthRate = 60.0
leftParticleSystem.particleLifeSpan = 4.0
rightParticleSystem.speedFactor = 2.0
rightParticleSystem.particleVelocity = 1.6
rightParticleSystem.birthRate = 60.0
rightParticleSystem.particleLifeSpan = 4.0
leftBottomParticleSystem.particleVelocity = 1.6
leftBottomParticleSystem.birthRate = 24.0
leftBottomParticleSystem.particleLifeSpan = 7.0
rightBottomParticleSystem.particleVelocity = 1.6
rightBottomParticleSystem.birthRate = 24.0
rightBottomParticleSystem.particleLifeSpan = 7.0
node.physicsField?.isActive = true
Queue.mainQueue().after(1.0) {
node.physicsField?.isActive = false
leftParticleSystem.birthRate = 15.0
leftParticleSystem.particleVelocity = 1.0
leftParticleSystem.particleLifeSpan = 3.0
rightParticleSystem.birthRate = 15.0
rightParticleSystem.particleVelocity = 1.0
rightParticleSystem.particleLifeSpan = 3.0
leftBottomParticleSystem.particleVelocity = 1.0
leftBottomParticleSystem.birthRate = 10.0
leftBottomParticleSystem.particleLifeSpan = 5.0
rightBottomParticleSystem.particleVelocity = 1.0
rightBottomParticleSystem.birthRate = 10.0
rightBottomParticleSystem.particleLifeSpan = 5.0
let leftAnimation = POPBasicAnimation()
leftAnimation.property = (POPAnimatableProperty.property(withName: "speedFactor", initializer: { property in
property?.readBlock = { particleSystem, values in
values?.pointee = (particleSystem as! SCNParticleSystem).speedFactor
}
property?.writeBlock = { particleSystem, values in
(particleSystem as! SCNParticleSystem).speedFactor = values!.pointee
}
property?.threshold = 0.01
}) as! POPAnimatableProperty)
leftAnimation.fromValue = 1.2 as NSNumber
leftAnimation.toValue = 0.85 as NSNumber
leftAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear)
leftAnimation.duration = 0.5
leftParticleSystem.pop_add(leftAnimation, forKey: "speedFactor")
let rightAnimation = POPBasicAnimation()
rightAnimation.property = (POPAnimatableProperty.property(withName: "speedFactor", initializer: { property in
property?.readBlock = { particleSystem, values in
values?.pointee = (particleSystem as! SCNParticleSystem).speedFactor
}
property?.writeBlock = { particleSystem, values in
(particleSystem as! SCNParticleSystem).speedFactor = values!.pointee
}
property?.threshold = 0.01
}) as! POPAnimatableProperty)
rightAnimation.fromValue = 1.2 as NSNumber
rightAnimation.toValue = 0.85 as NSNumber
rightAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear)
rightAnimation.duration = 0.5
rightParticleSystem.pop_add(rightAnimation, forKey: "speedFactor")
}
}
}
var from = node.presentation.eulerAngles
if abs(from.y - .pi * 2.0) < 0.001 {
from.y = 0.0
}
node.removeAnimation(forKey: "tapRotate")
var toValue: Float = smallAngle ? 0.0 : .pi * 2.0
if let velocity = velocity, !smallAngle && abs(velocity) > 200 && velocity < 0.0 {
toValue *= -1
}
if mirror {
toValue *= -1
}
let to = SCNVector3(x: 0.0, y: toValue, z: 0.0)
let distance = rad2deg(to.y - from.y)
guard !distance.isZero else {
return
}
let springAnimation = CASpringAnimation(keyPath: "eulerAngles")
springAnimation.fromValue = NSValue(scnVector3: from)
springAnimation.toValue = NSValue(scnVector3: to)
springAnimation.mass = 1.0
springAnimation.stiffness = 21.0
springAnimation.damping = 5.8
springAnimation.duration = springAnimation.settlingDuration * 0.75
springAnimation.initialVelocity = velocity.flatMap { abs($0 / CGFloat(distance)) } ?? 1.7
springAnimation.completion = { [weak node] finished in
if finished {
node?.eulerAngles = SCNVector3(x: 0.0, y: 0.0, z: 0.0)
}
}
node.addAnimation(springAnimation, forKey: "rotate")
}
func update(component: PremiumCoinComponent, availableSize: CGSize, transition: Transition) -> CGSize {
self.sceneView.bounds = CGRect(origin: .zero, size: CGSize(width: availableSize.width * 2.0, height: availableSize.height * 2.0))
if self.sceneView.superview == self {
self.sceneView.center = CGPoint(x: availableSize.width / 2.0, y: availableSize.height / 2.0)
}
self.hasIdleAnimations = component.hasIdleAnimations
return availableSize
}
}
func makeView() -> View {
return View(frame: CGRect(), isIntro: self.isIntro)
}
func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: Transition) -> CGSize {
return view.update(component: self, availableSize: availableSize, transition: transition)
}
}

View File

@ -1177,7 +1177,7 @@ private final class DemoSheetContent: CombinedComponent {
text = strings.Premium_LastSeenInfo
case .messagePrivacy:
text = strings.Premium_MessagePrivacyInfo
case .doubleLimits, .stories:
case .doubleLimits, .stories, .business:
text = ""
}
@ -1391,6 +1391,7 @@ public class PremiumDemoScreen: ViewControllerComponentContainer {
case messageTags
case lastSeen
case messagePrivacy
case business
}
public enum Source: Equatable {

View File

@ -530,6 +530,8 @@ private final class PremiumGiftScreenContentComponent: CombinedComponent {
demoSubject = .lastSeen
case .messagePrivacy:
demoSubject = .messagePrivacy
case .business:
demoSubject = .business
}
let buttonText: String

View File

@ -433,6 +433,7 @@ public enum PremiumPerk: CaseIterable {
case messageTags
case lastSeen
case messagePrivacy
case business
public static var allCases: [PremiumPerk] {
return [
@ -455,7 +456,8 @@ public enum PremiumPerk: CaseIterable {
.wallpapers,
.messageTags,
.lastSeen,
.messagePrivacy
.messagePrivacy,
.business
]
}
@ -511,6 +513,8 @@ public enum PremiumPerk: CaseIterable {
return "last_seen"
case .messagePrivacy:
return "message_privacy"
case .business:
return "business"
}
}
@ -556,6 +560,8 @@ public enum PremiumPerk: CaseIterable {
return strings.Premium_LastSeen
case .messagePrivacy:
return strings.Premium_MessagePrivacy
case .business:
return strings.Premium_Business
}
}
@ -601,6 +607,8 @@ public enum PremiumPerk: CaseIterable {
return strings.Premium_LastSeenInfo
case .messagePrivacy:
return strings.Premium_MessagePrivacyInfo
case .business:
return strings.Premium_BusinessInfo
}
}
@ -646,6 +654,85 @@ public enum PremiumPerk: CaseIterable {
return "Premium/Perk/LastSeen"
case .messagePrivacy:
return "Premium/Perk/MessagePrivacy"
case .business:
return "Premium/Perk/Business"
}
}
}
private enum BusinessPerk: CaseIterable {
case location
case hours
case quickReplies
case greetings
case awayMessages
case chatbots
var identifier: String {
switch self {
case .location:
return "location"
case .hours:
return "opening_hours"
case .quickReplies:
return "quick_replies"
case .greetings:
return "greeting_messages"
case .awayMessages:
return "away_messages"
case .chatbots:
return "chatbots"
}
}
func title(strings: PresentationStrings) -> String {
switch self {
case .location:
return strings.Business_Location
case .hours:
return strings.Business_OpeningHours
case .quickReplies:
return strings.Business_QuickReplies
case .greetings:
return strings.Business_GreetingMessages
case .awayMessages:
return strings.Business_AwayMessages
case .chatbots:
return strings.Business_Chatbots
}
}
func subtitle(strings: PresentationStrings) -> String {
switch self {
case .location:
return strings.Business_LocationInfo
case .hours:
return strings.Business_OpeningHoursInfo
case .quickReplies:
return strings.Business_QuickRepliesInfo
case .greetings:
return strings.Business_GreetingMessagesInfo
case .awayMessages:
return strings.Business_AwayMessagesInfo
case .chatbots:
return strings.Business_ChatbotsInfo
}
}
var iconName: String {
switch self {
case .location:
return "Premium/BusinessPerk/Location"
case .hours:
return "Premium/BusinessPerk/Hours"
case .quickReplies:
return "Premium/BusinessPerk/Replies"
case .greetings:
return "Premium/BusinessPerk/Greetings"
case .awayMessages:
return "Premium/BusinessPerk/Away"
case .chatbots:
return "Premium/BusinessPerk/Chatbots"
}
}
}
@ -672,7 +759,8 @@ struct PremiumIntroConfiguration {
.appIcons,
.uniqueReactions,
.animatedUserpics,
.premiumStickers
.premiumStickers,
.business
])
}
@ -711,6 +799,9 @@ struct PremiumIntroConfiguration {
if !perks.contains(.messageTags) {
perks.append(.messageTags)
}
if !perks.contains(.business) {
perks.append(.business)
}
#endif
return PremiumIntroConfiguration(perks: perks)
} else {
@ -748,339 +839,6 @@ private struct PremiumProduct: Equatable {
}
}
final class PremiumOptionComponent: CombinedComponent {
let title: String
let subtitle: String
let labelPrice: String
let discount: String
let multiple: Bool
let selected: Bool
let primaryTextColor: UIColor
let secondaryTextColor: UIColor
let accentColor: UIColor
let checkForegroundColor: UIColor
let checkBorderColor: UIColor
init(
title: String,
subtitle: String,
labelPrice: String,
discount: String,
multiple: Bool = false,
selected: Bool,
primaryTextColor: UIColor,
secondaryTextColor: UIColor,
accentColor: UIColor,
checkForegroundColor: UIColor,
checkBorderColor: UIColor
) {
self.title = title
self.subtitle = subtitle
self.labelPrice = labelPrice
self.discount = discount
self.multiple = multiple
self.selected = selected
self.primaryTextColor = primaryTextColor
self.secondaryTextColor = secondaryTextColor
self.accentColor = accentColor
self.checkForegroundColor = checkForegroundColor
self.checkBorderColor = checkBorderColor
}
static func ==(lhs: PremiumOptionComponent, rhs: PremiumOptionComponent) -> Bool {
if lhs.title != rhs.title {
return false
}
if lhs.subtitle != rhs.subtitle {
return false
}
if lhs.labelPrice != rhs.labelPrice {
return false
}
if lhs.discount != rhs.discount {
return false
}
if lhs.multiple != rhs.multiple {
return false
}
if lhs.selected != rhs.selected {
return false
}
if lhs.primaryTextColor != rhs.primaryTextColor {
return false
}
if lhs.secondaryTextColor != rhs.secondaryTextColor {
return false
}
if lhs.accentColor != rhs.accentColor {
return false
}
if lhs.checkForegroundColor != rhs.checkForegroundColor {
return false
}
if lhs.checkBorderColor != rhs.checkBorderColor {
return false
}
return true
}
static var body: Body {
let check = Child(CheckComponent.self)
let title = Child(MultilineTextComponent.self)
let subtitle = Child(MultilineTextComponent.self)
let discountBackground = Child(RoundedRectangle.self)
let discount = Child(MultilineTextComponent.self)
let label = Child(MultilineTextComponent.self)
return { context in
let component = context.component
var insets = UIEdgeInsets(top: 11.0, left: 46.0, bottom: 13.0, right: 16.0)
let label = label.update(
component: MultilineTextComponent(
text: .plain(
NSAttributedString(
string: component.labelPrice,
font: Font.regular(17),
textColor: component.secondaryTextColor
)
),
maximumNumberOfLines: 1
),
availableSize: context.availableSize,
transition: context.transition
)
let title = title.update(
component: MultilineTextComponent(
text: .plain(
NSAttributedString(
string: component.title,
font: Font.regular(17),
textColor: component.primaryTextColor
)
),
maximumNumberOfLines: 1
),
availableSize: CGSize(width: context.availableSize.width - insets.left - insets.right - label.size.width, height: context.availableSize.height),
transition: context.transition
)
let discountSize: CGSize
if !component.discount.isEmpty {
let discount = discount.update(
component: MultilineTextComponent(
text: .plain(
NSAttributedString(
string: component.discount,
font: Font.with(size: 14.0, design: .round, weight: .semibold, traits: []),
textColor: .white
)
),
maximumNumberOfLines: 1
),
availableSize: context.availableSize,
transition: context.transition
)
discountSize = CGSize(width: discount.size.width + 6.0, height: 18.0)
let discountBackground = discountBackground.update(
component: RoundedRectangle(
color: component.accentColor,
cornerRadius: 5.0
),
availableSize: discountSize,
transition: context.transition
)
let discountPosition = CGPoint(x: insets.left + title.size.width + 6.0 + discountSize.width / 2.0, y: insets.top + title.size.height / 2.0)
context.add(discountBackground
.position(discountPosition)
)
context.add(discount
.position(discountPosition)
)
} else {
discountSize = CGSize(width: 0.0, height: 18.0)
}
var spacing: CGFloat = 0.0
var subtitleSize = CGSize()
if !component.subtitle.isEmpty {
spacing = 2.0
let subtitleFont = Font.regular(13)
let subtitleColor = component.secondaryTextColor
let subtitleString = parseMarkdownIntoAttributedString(
component.subtitle,
attributes: MarkdownAttributes(
body: MarkdownAttributeSet(font: subtitleFont, textColor: subtitleColor),
bold: MarkdownAttributeSet(font: subtitleFont, textColor: subtitleColor, additionalAttributes: [NSAttributedString.Key.strikethroughStyle.rawValue: NSUnderlineStyle.single.rawValue as NSNumber]),
link: MarkdownAttributeSet(font: subtitleFont, textColor: subtitleColor),
linkAttribute: { _ in return nil }
)
)
let subtitle = subtitle.update(
component: MultilineTextComponent(
text: .plain(subtitleString),
maximumNumberOfLines: 1
),
availableSize: CGSize(width: context.availableSize.width - insets.left - insets.right, height: context.availableSize.height),
transition: context.transition
)
context.add(subtitle
.position(CGPoint(x: insets.left + subtitle.size.width / 2.0, y: insets.top + title.size.height + spacing + subtitle.size.height / 2.0))
)
subtitleSize = subtitle.size
insets.top -= 2.0
insets.bottom -= 2.0
}
let check = check.update(
component: CheckComponent(
theme: CheckComponent.Theme(
backgroundColor: component.accentColor,
strokeColor: component.checkForegroundColor,
borderColor: component.checkBorderColor,
overlayBorder: false,
hasInset: false,
hasShadow: false
),
selected: component.selected
),
availableSize: context.availableSize,
transition: context.transition
)
context.add(title
.position(CGPoint(x: insets.left + title.size.width / 2.0, y: insets.top + title.size.height / 2.0))
)
let size = CGSize(width: context.availableSize.width, height: insets.top + title.size.height + spacing + subtitleSize.height + insets.bottom)
let distance = context.availableSize.width - insets.left - insets.right - label.size.width - subtitleSize.width
let labelY: CGFloat
if distance > 8.0 {
labelY = size.height / 2.0
} else {
labelY = insets.top + title.size.height / 2.0
}
context.add(label
.position(CGPoint(x: context.availableSize.width - insets.right - label.size.width / 2.0, y: labelY))
)
context.add(check
.position(CGPoint(x: 4.0 + check.size.width / 2.0, y: size.height / 2.0))
)
return size
}
}
}
private final class CheckComponent: Component {
struct Theme: Equatable {
public let backgroundColor: UIColor
public let strokeColor: UIColor
public let borderColor: UIColor
public let overlayBorder: Bool
public let hasInset: Bool
public let hasShadow: Bool
public let filledBorder: Bool
public let borderWidth: CGFloat?
public init(backgroundColor: UIColor, strokeColor: UIColor, borderColor: UIColor, overlayBorder: Bool, hasInset: Bool, hasShadow: Bool, filledBorder: Bool = false, borderWidth: CGFloat? = nil) {
self.backgroundColor = backgroundColor
self.strokeColor = strokeColor
self.borderColor = borderColor
self.overlayBorder = overlayBorder
self.hasInset = hasInset
self.hasShadow = hasShadow
self.filledBorder = filledBorder
self.borderWidth = borderWidth
}
var checkNodeTheme: CheckNodeTheme {
return CheckNodeTheme(
backgroundColor: self.backgroundColor,
strokeColor: self.strokeColor,
borderColor: self.borderColor,
overlayBorder: self.overlayBorder,
hasInset: self.hasInset,
hasShadow: self.hasShadow,
filledBorder: self.filledBorder,
borderWidth: self.borderWidth
)
}
}
let theme: Theme
let selected: Bool
init(
theme: Theme,
selected: Bool
) {
self.theme = theme
self.selected = selected
}
static func ==(lhs: CheckComponent, rhs: CheckComponent) -> Bool {
if lhs.theme != rhs.theme {
return false
}
if lhs.selected != rhs.selected {
return false
}
return true
}
final class View: UIView {
private var currentValue: CGFloat?
private var animator: DisplayLinkAnimator?
private var checkLayer: CheckLayer {
return self.layer as! CheckLayer
}
override class var layerClass: AnyClass {
return CheckLayer.self
}
init() {
super.init(frame: CGRect())
}
required init?(coder aDecoder: NSCoder) {
preconditionFailure()
}
func update(component: CheckComponent, availableSize: CGSize, transition: Transition) -> CGSize {
self.checkLayer.setSelected(component.selected, animated: true)
self.checkLayer.theme = component.theme.checkNodeTheme
return CGSize(width: 22.0, height: 22.0)
}
}
func makeView() -> View {
return View()
}
func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: Transition) -> CGSize {
return view.update(component: self, availableSize: availableSize, transition: transition)
}
}
final class SectionGroupComponent: Component {
public final class Item: Equatable {
public let content: AnyComponentWithIdentity<Empty>
@ -1479,6 +1237,7 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
typealias EnvironmentType = (ViewControllerComponentContainer.Environment, ScrollChildEnvironment)
let context: AccountContext
let mode: PremiumIntroScreen.Mode
let source: PremiumSource
let forceDark: Bool
let isPremium: Bool?
@ -1489,6 +1248,7 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
let validPurchases: [InAppPurchaseManager.ReceiptPurchase]
let promoConfiguration: PremiumPromoConfiguration?
let present: (ViewController) -> Void
let push: (ViewController) -> Void
let selectProduct: (String) -> Void
let buy: () -> Void
let updateIsFocused: (Bool) -> Void
@ -1497,6 +1257,7 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
init(
context: AccountContext,
mode: PremiumIntroScreen.Mode,
source: PremiumSource,
forceDark: Bool,
isPremium: Bool?,
@ -1507,6 +1268,7 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
validPurchases: [InAppPurchaseManager.ReceiptPurchase],
promoConfiguration: PremiumPromoConfiguration?,
present: @escaping (ViewController) -> Void,
push: @escaping (ViewController) -> Void,
selectProduct: @escaping (String) -> Void,
buy: @escaping () -> Void,
updateIsFocused: @escaping (Bool) -> Void,
@ -1514,6 +1276,7 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
shareLink: @escaping (String) -> Void
) {
self.context = context
self.mode = mode
self.source = source
self.forceDark = forceDark
self.isPremium = isPremium
@ -1524,6 +1287,7 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
self.validPurchases = validPurchases
self.promoConfiguration = promoConfiguration
self.present = present
self.push = push
self.selectProduct = selectProduct
self.buy = buy
self.updateIsFocused = updateIsFocused
@ -1688,6 +1452,8 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
if !dismissedMessagePrivacyBadge {
newPerks.append(PremiumPerk.messagePrivacy.identifier)
}
//TODO:
newPerks.append(PremiumPerk.business.identifier)
self.newPerks = newPerks
self.updated()
})
@ -1712,6 +1478,7 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
let completedText = Child(MultilineTextComponent.self)
let linkButton = Child(Button.self)
let optionsSection = Child(SectionGroupComponent.self)
let businessSection = Child(SectionGroupComponent.self)
let perksTitle = Child(MultilineTextComponent.self)
let perksSection = Child(SectionGroupComponent.self)
let infoBackground = Child(RoundedRectangle.self)
@ -1805,13 +1572,21 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
textString = strings.Premium_PersonalDescription
}
} else if context.component.isPremium == true {
if !context.component.justBought, let products = state.products, let current = products.first(where: { $0.isCurrent }), current.months == 1 {
textString = strings.Premium_UpgradeDescription
if case .business = context.component.mode {
textString = strings.Business_SubscribedDescription
} else {
textString = strings.Premium_SubscribedDescription
if !context.component.justBought, let products = state.products, let current = products.first(where: { $0.isCurrent }), current.months == 1 {
textString = strings.Premium_UpgradeDescription
} else {
textString = strings.Premium_SubscribedDescription
}
}
} else {
textString = strings.Premium_Description
if case .business = context.component.mode {
textString = strings.Business_Description
} else {
textString = strings.Premium_Description
}
}
let markdownAttributes = MarkdownAttributes(body: MarkdownAttributeSet(font: textFont, textColor: textColor), bold: MarkdownAttributeSet(font: boldTextFont, textColor: textColor), link: MarkdownAttributeSet(font: textFont, textColor: accentColor), linkAttribute: { contents in
@ -1862,6 +1637,7 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
UIColor(rgb: 0xef6922),
UIColor(rgb: 0xe95a2c),
UIColor(rgb: 0xe74e33),
UIColor(rgb: 0xe74e33), //replace
UIColor(rgb: 0xe54937),
UIColor(rgb: 0xe3433c),
UIColor(rgb: 0xdb374b),
@ -1883,6 +1659,7 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
let accountContext = context.component.context
let present = context.component.present
let push = context.component.push
let selectProduct = context.component.selectProduct
let buy = context.component.buy
let updateIsFocused = context.component.updateIsFocused
@ -2005,10 +1782,17 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
let forceDark = context.component.forceDark
let layoutPerks = {
size.height += 8.0
let title: String
if case .business = context.component.mode {
title = strings.Business_PlusPremiumFeatures
} else {
title = strings.Premium_WhatsIncluded
}
let perksTitle = perksTitle.update(
component: MultilineTextComponent(
text: .plain(
NSAttributedString(string: strings.Premium_WhatsIncluded.uppercased(), font: Font.regular(14.0), textColor: environment.theme.list.freeTextColor)
NSAttributedString(string: title.uppercased(), font: Font.regular(14.0), textColor: environment.theme.list.freeTextColor)
),
horizontalAlignment: .natural,
maximumNumberOfLines: 0,
@ -2020,6 +1804,7 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
)
context.add(perksTitle
.position(CGPoint(x: sideInset + environment.safeInsets.left + textSideInset + perksTitle.size.width / 2.0, y: size.height + perksTitle.size.height / 2.0))
.disappear(.default(alpha: true))
)
size.height += perksTitle.size.height
size.height += 3.0
@ -2027,6 +1812,9 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
var i = 0
var perksItems: [SectionGroupComponent.Item] = []
for perk in state.configuration.perks {
if case .business = context.component.mode, case .business = perk {
continue
}
let iconBackgroundColors = gradientColors[i]
perksItems.append(SectionGroupComponent.Item(
AnyComponentWithIdentity(
@ -2073,7 +1861,6 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
demoSubject = .animatedUserpics
case .appIcons:
demoSubject = .appIcons
// let _ = ApplicationSpecificNotice.setDismissedPremiumAppIconsBadge(accountManager: accountContext.sharedContext.accountManager).startStandalone()
case .animatedEmoji:
demoSubject = .animatedEmoji
case .emojiStatus:
@ -2097,6 +1884,8 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
case .messagePrivacy:
demoSubject = .messagePrivacy
let _ = ApplicationSpecificNotice.setDismissedMessagePrivacyBadge(accountManager: accountContext.sharedContext.accountManager).startStandalone()
case .business:
demoSubject = .business
}
let isPremium = state?.isPremium == true
@ -2138,6 +1927,7 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
.position(CGPoint(x: availableWidth / 2.0, y: size.height + perksSection.size.height / 2.0))
.clipsToBounds(true)
.cornerRadius(10.0)
.disappear(.default(alpha: true))
)
size.height += perksSection.size.height
@ -2152,6 +1942,82 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
}
}
let layoutBusinessPerks = {
size.height += 8.0
let gradientColors: [UIColor] = [
UIColor(rgb: 0x007aff),
UIColor(rgb: 0xac64f3),
UIColor(rgb: 0xef6922),
UIColor(rgb: 0xe95d44),
UIColor(rgb: 0xf2822a),
UIColor(rgb: 0xe79519)
]
var i = 0
var perksItems: [SectionGroupComponent.Item] = []
for perk in BusinessPerk.allCases {
let iconBackgroundColors = gradientColors[i]
perksItems.append(SectionGroupComponent.Item(
AnyComponentWithIdentity(
id: perk.identifier,
component: AnyComponent(
PerkComponent(
iconName: perk.iconName,
iconBackgroundColors: [
iconBackgroundColors
],
title: perk.title(strings: strings),
titleColor: titleColor,
subtitle: perk.subtitle(strings: strings),
subtitleColor: subtitleColor,
arrowColor: arrowColor,
accentColor: accentColor,
badge: nil
)
)
),
accessibilityLabel: "\(perk.title(strings: strings)). \(perk.subtitle(strings: strings))",
action: {
switch perk {
case .location:
push(accountContext.sharedContext.makeBusinessLocationSetupScreen(context: accountContext))
case .hours:
push(accountContext.sharedContext.makeBusinessHoursSetupScreen(context: accountContext))
case .quickReplies:
break
case .greetings:
push(accountContext.sharedContext.makeGreetingMessageSetupScreen(context: accountContext))
case .awayMessages:
break
case .chatbots:
push(accountContext.sharedContext.makeChatbotSetupScreen(context: accountContext))
}
}
))
i += 1
}
let businessSection = businessSection.update(
component: SectionGroupComponent(
items: perksItems,
backgroundColor: environment.theme.list.itemBlocksBackgroundColor,
selectionColor: environment.theme.list.itemHighlightedBackgroundColor,
separatorColor: environment.theme.list.itemBlocksSeparatorColor
),
environment: {},
availableSize: CGSize(width: availableWidth - sideInsets, height: .greatestFiniteMagnitude),
transition: context.transition
)
context.add(businessSection
.position(CGPoint(x: availableWidth / 2.0, y: size.height + businessSection.size.height / 2.0))
.clipsToBounds(true)
.cornerRadius(10.0)
)
size.height += businessSection.size.height
size.height += 23.0
}
let copyLink = context.component.copyLink
if case .emojiStatus = context.component.source {
layoutPerks()
@ -2182,7 +2048,15 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
layoutPerks()
} else {
layoutOptions()
layoutPerks()
if case .business = context.component.mode {
layoutBusinessPerks()
if context.component.isPremium == false {
layoutPerks()
}
} else {
layoutPerks()
}
let textPadding: CGFloat = 13.0
@ -2344,6 +2218,7 @@ private final class PremiumIntroScreenComponent: CombinedComponent {
typealias EnvironmentType = ViewControllerComponentContainer.Environment
let context: AccountContext
let mode: PremiumIntroScreen.Mode
let source: PremiumSource
let forceDark: Bool
let forceHasPremium: Bool
@ -2354,8 +2229,9 @@ private final class PremiumIntroScreenComponent: CombinedComponent {
let copyLink: (String) -> Void
let shareLink: (String) -> Void
init(context: AccountContext, source: PremiumSource, forceDark: Bool, forceHasPremium: Bool, updateInProgress: @escaping (Bool) -> Void, present: @escaping (ViewController) -> Void, push: @escaping (ViewController) -> Void, completion: @escaping () -> Void, copyLink: @escaping (String) -> Void, shareLink: @escaping (String) -> Void) {
init(context: AccountContext, mode: PremiumIntroScreen.Mode, source: PremiumSource, forceDark: Bool, forceHasPremium: Bool, updateInProgress: @escaping (Bool) -> Void, present: @escaping (ViewController) -> Void, push: @escaping (ViewController) -> Void, completion: @escaping () -> Void, copyLink: @escaping (String) -> Void, shareLink: @escaping (String) -> Void) {
self.context = context
self.mode = mode
self.source = source
self.forceDark = forceDark
self.forceHasPremium = forceHasPremium
@ -2371,6 +2247,9 @@ private final class PremiumIntroScreenComponent: CombinedComponent {
if lhs.context !== rhs.context {
return false
}
if lhs.mode != rhs.mode {
return false
}
if lhs.source != rhs.source {
return false
}
@ -2730,6 +2609,7 @@ private final class PremiumIntroScreenComponent: CombinedComponent {
let scrollContent = Child(ScrollComponent<EnvironmentType>.self)
let star = Child(PremiumStarComponent.self)
let emoji = Child(EmojiHeaderComponent.self)
let coin = Child(PremiumCoinComponent.self)
let topPanel = Child(BlurredBackgroundComponent.self)
let topSeparator = Child(Rectangle.self)
let title = Child(MultilineTextComponent.self)
@ -2755,7 +2635,17 @@ private final class PremiumIntroScreenComponent: CombinedComponent {
}
let header: _UpdatedChildComponent
if case let .emojiStatus(_, fileId, _, _) = context.component.source {
if case .business = context.component.mode {
header = coin.update(
component: PremiumCoinComponent(
isIntro: isIntro,
isVisible: starIsVisible,
hasIdleAnimations: state.hasIdleAnimations
),
availableSize: CGSize(width: min(414.0, context.availableSize.width), height: 220.0),
transition: context.transition
)
} else if case let .emojiStatus(_, fileId, _, _) = context.component.source {
header = emoji.update(
component: EmojiHeaderComponent(
context: context.component.context,
@ -2799,7 +2689,9 @@ private final class PremiumIntroScreenComponent: CombinedComponent {
)
let titleString: String
if case .emojiStatus = context.component.source {
if case .business = context.component.mode {
titleString = environment.strings.Business_Title
} else if case .emojiStatus = context.component.source {
titleString = environment.strings.Premium_Title
} else if case .giftTerms = context.component.source {
titleString = environment.strings.Premium_Title
@ -2951,6 +2843,7 @@ private final class PremiumIntroScreenComponent: CombinedComponent {
component: ScrollComponent<EnvironmentType>(
content: AnyComponent(PremiumIntroScreenContentComponent(
context: context.component.context,
mode: context.component.mode,
source: context.component.source,
forceDark: context.component.forceDark,
isPremium: state.isPremium,
@ -2961,6 +2854,7 @@ private final class PremiumIntroScreenComponent: CombinedComponent {
validPurchases: state.validPurchases,
promoConfiguration: state.promoConfiguration,
present: context.component.present,
push: context.component.push,
selectProduct: { [weak state] productId in
state?.selectProduct(productId)
},
@ -3177,7 +3071,13 @@ private final class PremiumIntroScreenComponent: CombinedComponent {
}
public final class PremiumIntroScreen: ViewControllerComponentContainer {
public enum Mode {
case premium
case business
}
fileprivate let context: AccountContext
fileprivate let mode: Mode
private var didSetReady = false
private let _ready = Promise<Bool>()
@ -3189,8 +3089,9 @@ public final class PremiumIntroScreen: ViewControllerComponentContainer {
public weak var containerView: UIView?
public var animationColor: UIColor?
public init(context: AccountContext, modal: Bool = true, source: PremiumSource, forceDark: Bool = false, forceHasPremium: Bool = false) {
public init(context: AccountContext, mode: Mode = .premium, source: PremiumSource, modal: Bool = true, forceDark: Bool = false, forceHasPremium: Bool = false) {
self.context = context
self.mode = mode
var updateInProgressImpl: ((Bool) -> Void)?
var pushImpl: ((ViewController) -> Void)?
@ -3200,6 +3101,7 @@ public final class PremiumIntroScreen: ViewControllerComponentContainer {
var shareLinkImpl: ((String) -> Void)?
super.init(context: context, component: PremiumIntroScreenComponent(
context: context,
mode: mode,
source: source,
forceDark: forceDark,
forceHasPremium: forceHasPremium,
@ -3335,7 +3237,10 @@ public final class PremiumIntroScreen: ViewControllerComponentContainer {
super.containerLayoutUpdated(layout, transition: transition)
if !self.didSetReady {
if let view = self.node.hostView.findTaggedView(tag: PremiumStarComponent.View.Tag()) as? PremiumStarComponent.View {
if let view = self.node.hostView.findTaggedView(tag: PremiumCoinComponent.View.Tag()) as? PremiumCoinComponent.View {
self.didSetReady = true
self._ready.set(view.ready)
} else if let view = self.node.hostView.findTaggedView(tag: PremiumStarComponent.View.Tag()) as? PremiumStarComponent.View {
self.didSetReady = true
self._ready.set(view.ready)

View File

@ -391,12 +391,15 @@ public class PremiumLimitsListScreen: ViewController {
var storiesIndex: Int?
var limitsIndex: Int?
var businessIndex: Int?
var storiesNeighbors = PageNeighbors(leftIsList: false, rightIsList: false)
var limitsNeighbors = PageNeighbors(leftIsList: false, rightIsList: false)
let businessNeighbors = PageNeighbors(leftIsList: false, rightIsList: false)
if let order = controller.order {
storiesIndex = order.firstIndex(where: { $0 == .stories })
limitsIndex = order.firstIndex(where: { $0 == .doubleLimits })
if let limitsIndex, let storiesIndex {
businessIndex = order.firstIndex(where: { $0 == .doubleLimits })
if let limitsIndex, let storiesIndex, let _ = businessIndex {
if limitsIndex == storiesIndex + 1 {
storiesNeighbors.rightIsList = true
limitsNeighbors.leftIsList = true
@ -799,6 +802,37 @@ public class PremiumLimitsListScreen: ViewController {
)
)
)
availableItems[.business] = DemoPagerComponent.Item(
AnyComponentWithIdentity(
id: PremiumDemoScreen.Subject.business,
component: AnyComponent(
BusinessPageComponent(
context: context,
theme: self.presentationData.theme,
neighbors: businessNeighbors,
bottomInset: self.footerNode.frame.height,
updatedBottomAlpha: { [weak self] alpha in
if let strongSelf = self {
strongSelf.footerNode.updateCoverAlpha(alpha, transition: .immediate)
}
},
updatedDismissOffset: { [weak self] offset in
if let strongSelf = self {
strongSelf.updateDismissOffset(offset)
}
},
updatedIsDisplaying: { [weak self] isDisplaying in
if let self, self.isExpanded && !isDisplaying {
if let limitsIndex, let indexPosition = self.indexPosition, abs(CGFloat(limitsIndex) - indexPosition) < 0.1 {
} else {
self.update(isExpanded: false, transition: .animated(duration: 0.2, curve: .easeInOut))
}
}
}
)
)
)
)
if let order = controller.order {
var items: [DemoPagerComponent.Item] = order.compactMap { availableItems[$0] }
@ -852,7 +886,7 @@ public class PremiumLimitsListScreen: ViewController {
id: "background",
component: AnyComponent(
BlurredBackgroundComponent(
color: UIColor(rgb: 0x888888, alpha: 0.3)
color: UIColor(rgb: 0xbbbbbb, alpha: 0.22)
)
)
),

View File

@ -0,0 +1,340 @@
import Foundation
import UIKit
import Display
import ComponentFlow
import MultilineTextComponent
import CheckNode
import Markdown
final class PremiumOptionComponent: CombinedComponent {
let title: String
let subtitle: String
let labelPrice: String
let discount: String
let multiple: Bool
let selected: Bool
let primaryTextColor: UIColor
let secondaryTextColor: UIColor
let accentColor: UIColor
let checkForegroundColor: UIColor
let checkBorderColor: UIColor
init(
title: String,
subtitle: String,
labelPrice: String,
discount: String,
multiple: Bool = false,
selected: Bool,
primaryTextColor: UIColor,
secondaryTextColor: UIColor,
accentColor: UIColor,
checkForegroundColor: UIColor,
checkBorderColor: UIColor
) {
self.title = title
self.subtitle = subtitle
self.labelPrice = labelPrice
self.discount = discount
self.multiple = multiple
self.selected = selected
self.primaryTextColor = primaryTextColor
self.secondaryTextColor = secondaryTextColor
self.accentColor = accentColor
self.checkForegroundColor = checkForegroundColor
self.checkBorderColor = checkBorderColor
}
static func ==(lhs: PremiumOptionComponent, rhs: PremiumOptionComponent) -> Bool {
if lhs.title != rhs.title {
return false
}
if lhs.subtitle != rhs.subtitle {
return false
}
if lhs.labelPrice != rhs.labelPrice {
return false
}
if lhs.discount != rhs.discount {
return false
}
if lhs.multiple != rhs.multiple {
return false
}
if lhs.selected != rhs.selected {
return false
}
if lhs.primaryTextColor != rhs.primaryTextColor {
return false
}
if lhs.secondaryTextColor != rhs.secondaryTextColor {
return false
}
if lhs.accentColor != rhs.accentColor {
return false
}
if lhs.checkForegroundColor != rhs.checkForegroundColor {
return false
}
if lhs.checkBorderColor != rhs.checkBorderColor {
return false
}
return true
}
static var body: Body {
let check = Child(CheckComponent.self)
let title = Child(MultilineTextComponent.self)
let subtitle = Child(MultilineTextComponent.self)
let discountBackground = Child(RoundedRectangle.self)
let discount = Child(MultilineTextComponent.self)
let label = Child(MultilineTextComponent.self)
return { context in
let component = context.component
var insets = UIEdgeInsets(top: 11.0, left: 46.0, bottom: 13.0, right: 16.0)
let label = label.update(
component: MultilineTextComponent(
text: .plain(
NSAttributedString(
string: component.labelPrice,
font: Font.regular(17),
textColor: component.secondaryTextColor
)
),
maximumNumberOfLines: 1
),
availableSize: context.availableSize,
transition: context.transition
)
let title = title.update(
component: MultilineTextComponent(
text: .plain(
NSAttributedString(
string: component.title,
font: Font.regular(17),
textColor: component.primaryTextColor
)
),
maximumNumberOfLines: 1
),
availableSize: CGSize(width: context.availableSize.width - insets.left - insets.right - label.size.width, height: context.availableSize.height),
transition: context.transition
)
let discountSize: CGSize
if !component.discount.isEmpty {
let discount = discount.update(
component: MultilineTextComponent(
text: .plain(
NSAttributedString(
string: component.discount,
font: Font.with(size: 14.0, design: .round, weight: .semibold, traits: []),
textColor: .white
)
),
maximumNumberOfLines: 1
),
availableSize: context.availableSize,
transition: context.transition
)
discountSize = CGSize(width: discount.size.width + 6.0, height: 18.0)
let discountBackground = discountBackground.update(
component: RoundedRectangle(
color: component.accentColor,
cornerRadius: 5.0
),
availableSize: discountSize,
transition: context.transition
)
let discountPosition = CGPoint(x: insets.left + title.size.width + 6.0 + discountSize.width / 2.0, y: insets.top + title.size.height / 2.0)
context.add(discountBackground
.position(discountPosition)
)
context.add(discount
.position(discountPosition)
)
} else {
discountSize = CGSize(width: 0.0, height: 18.0)
}
var spacing: CGFloat = 0.0
var subtitleSize = CGSize()
if !component.subtitle.isEmpty {
spacing = 2.0
let subtitleFont = Font.regular(13)
let subtitleColor = component.secondaryTextColor
let subtitleString = parseMarkdownIntoAttributedString(
component.subtitle,
attributes: MarkdownAttributes(
body: MarkdownAttributeSet(font: subtitleFont, textColor: subtitleColor),
bold: MarkdownAttributeSet(font: subtitleFont, textColor: subtitleColor, additionalAttributes: [NSAttributedString.Key.strikethroughStyle.rawValue: NSUnderlineStyle.single.rawValue as NSNumber]),
link: MarkdownAttributeSet(font: subtitleFont, textColor: subtitleColor),
linkAttribute: { _ in return nil }
)
)
let subtitle = subtitle.update(
component: MultilineTextComponent(
text: .plain(subtitleString),
maximumNumberOfLines: 1
),
availableSize: CGSize(width: context.availableSize.width - insets.left - insets.right, height: context.availableSize.height),
transition: context.transition
)
context.add(subtitle
.position(CGPoint(x: insets.left + subtitle.size.width / 2.0, y: insets.top + title.size.height + spacing + subtitle.size.height / 2.0))
)
subtitleSize = subtitle.size
insets.top -= 2.0
insets.bottom -= 2.0
}
let check = check.update(
component: CheckComponent(
theme: CheckComponent.Theme(
backgroundColor: component.accentColor,
strokeColor: component.checkForegroundColor,
borderColor: component.checkBorderColor,
overlayBorder: false,
hasInset: false,
hasShadow: false
),
selected: component.selected
),
availableSize: context.availableSize,
transition: context.transition
)
context.add(title
.position(CGPoint(x: insets.left + title.size.width / 2.0, y: insets.top + title.size.height / 2.0))
)
let size = CGSize(width: context.availableSize.width, height: insets.top + title.size.height + spacing + subtitleSize.height + insets.bottom)
let distance = context.availableSize.width - insets.left - insets.right - label.size.width - subtitleSize.width
let labelY: CGFloat
if distance > 8.0 {
labelY = size.height / 2.0
} else {
labelY = insets.top + title.size.height / 2.0
}
context.add(label
.position(CGPoint(x: context.availableSize.width - insets.right - label.size.width / 2.0, y: labelY))
)
context.add(check
.position(CGPoint(x: 4.0 + check.size.width / 2.0, y: size.height / 2.0))
)
return size
}
}
}
private final class CheckComponent: Component {
struct Theme: Equatable {
public let backgroundColor: UIColor
public let strokeColor: UIColor
public let borderColor: UIColor
public let overlayBorder: Bool
public let hasInset: Bool
public let hasShadow: Bool
public let filledBorder: Bool
public let borderWidth: CGFloat?
public init(backgroundColor: UIColor, strokeColor: UIColor, borderColor: UIColor, overlayBorder: Bool, hasInset: Bool, hasShadow: Bool, filledBorder: Bool = false, borderWidth: CGFloat? = nil) {
self.backgroundColor = backgroundColor
self.strokeColor = strokeColor
self.borderColor = borderColor
self.overlayBorder = overlayBorder
self.hasInset = hasInset
self.hasShadow = hasShadow
self.filledBorder = filledBorder
self.borderWidth = borderWidth
}
var checkNodeTheme: CheckNodeTheme {
return CheckNodeTheme(
backgroundColor: self.backgroundColor,
strokeColor: self.strokeColor,
borderColor: self.borderColor,
overlayBorder: self.overlayBorder,
hasInset: self.hasInset,
hasShadow: self.hasShadow,
filledBorder: self.filledBorder,
borderWidth: self.borderWidth
)
}
}
let theme: Theme
let selected: Bool
init(
theme: Theme,
selected: Bool
) {
self.theme = theme
self.selected = selected
}
static func ==(lhs: CheckComponent, rhs: CheckComponent) -> Bool {
if lhs.theme != rhs.theme {
return false
}
if lhs.selected != rhs.selected {
return false
}
return true
}
final class View: UIView {
private var currentValue: CGFloat?
private var animator: DisplayLinkAnimator?
private var checkLayer: CheckLayer {
return self.layer as! CheckLayer
}
override class var layerClass: AnyClass {
return CheckLayer.self
}
init() {
super.init(frame: CGRect())
}
required init?(coder aDecoder: NSCoder) {
preconditionFailure()
}
func update(component: CheckComponent, availableSize: CGSize, transition: Transition) -> CGSize {
self.checkLayer.setSelected(component.selected, animated: true)
self.checkLayer.theme = component.theme.checkNodeTheme
return CGSize(width: 22.0, height: 22.0)
}
}
func makeView() -> View {
return View()
}
func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: Transition) -> CGSize {
return view.update(component: self, availableSize: availableSize, transition: transition)
}
}

View File

@ -279,13 +279,13 @@ private func premiumSearchableItems(context: AccountContext) -> [SettingsSearcha
var result: [SettingsSearchableItem] = []
result.append(SettingsSearchableItem(id: .premium(0), title: strings.Settings_Premium, alternate: synonyms(strings.SettingsSearch_Synonyms_Premium), icon: icon, breadcrumbs: [], present: { context, _, present in
present(.push, PremiumIntroScreen(context: context, modal: false, source: .settings))
present(.push, PremiumIntroScreen(context: context, source: .settings, modal: false))
}))
let presentDemo: (PremiumDemoScreen.Subject, (SettingsSearchableItemPresentation, ViewController?) -> Void) -> Void = { subject, present in
var replaceImpl: ((ViewController) -> Void)?
let controller = PremiumDemoScreen(context: context, subject: subject, action: {
let controller = PremiumIntroScreen(context: context, modal: false, source: .settings)
let controller = PremiumIntroScreen(context: context, source: .settings, modal: false)
replaceImpl?(controller)
})
replaceImpl = { [weak controller] c in

View File

@ -40,7 +40,6 @@ swift_library(
"//submodules/TelegramUI/Components/AnimationCache",
"//submodules/TelegramUI/Components/MultiAnimationRenderer",
"//submodules/UndoUI",
"//submodules/PremiumUI",
],
visibility = [
"//visibility:public",

View File

@ -20,7 +20,6 @@ import TelegramIntents
import AnimationCache
import MultiAnimationRenderer
import ObjectiveC
import PremiumUI
import UndoUI
private var ObjCKey_DeinitWatcher: Int?
@ -1241,7 +1240,8 @@ public final class ShareController: ViewController {
}
if case .undo = action {
self.controllerNode.cancel?()
let premiumController = PremiumIntroScreen(context: context.context, source: .settings)
let premiumController = context.context.sharedContext.makePremiumIntroController(context: context.context, source: .settings, forceDark: false, dismissed: nil)
parentNavigationController.pushViewController(premiumController)
}
return false

View File

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "sleep_30.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,261 @@
%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 5.000000 3.620605 cm
0.949020 0.509804 0.164706 scn
10.000000 22.044395 m
9.632730 22.044395 9.335000 21.746664 9.335000 21.379395 c
9.335000 21.012125 9.632730 20.714394 10.000000 20.714394 c
10.000000 22.044395 l
h
7.545889 3.473347 m
7.397222 2.825178 l
7.397222 2.825178 l
7.545889 3.473347 l
h
5.266314 1.841904 m
4.941034 2.421919 l
4.941034 2.421919 l
5.266314 1.841904 l
h
2.471971 1.400562 m
2.729195 2.013800 l
2.471971 1.400562 l
h
3.613619 5.411449 m
3.220784 4.874880 l
3.613619 5.411449 l
h
1.044152 14.673008 m
1.158136 15.022142 0.967510 15.397573 0.618376 15.511558 c
0.269242 15.625542 -0.106189 15.434916 -0.220173 15.085781 c
1.044152 14.673008 l
h
10.000000 20.714394 m
15.216641 20.714394 19.334999 16.883762 19.334999 12.288485 c
20.665001 12.288485 l
20.665001 17.734749 15.829054 22.044395 10.000000 22.044395 c
10.000000 20.714394 l
h
19.334999 12.288485 m
19.334999 7.693207 15.216641 3.862574 10.000000 3.862574 c
10.000000 2.532574 l
15.829054 2.532574 20.665001 6.842219 20.665001 12.288485 c
19.334999 12.288485 l
h
10.000000 3.862574 m
9.203434 3.862574 8.431143 3.952568 7.694556 4.121515 c
7.397222 2.825178 l
8.231061 2.633924 9.103088 2.532574 10.000000 2.532574 c
10.000000 3.862574 l
h
7.694556 4.121515 m
7.296880 4.212729 6.988394 3.993870 6.866287 3.902132 c
6.721981 3.793718 6.552248 3.631363 6.405339 3.496563 c
6.085002 3.202633 5.640136 2.813984 4.941034 2.421919 c
5.591593 1.261889 l
6.417547 1.725092 6.948387 2.189800 7.304534 2.516590 c
7.495866 2.692152 7.589569 2.781998 7.665158 2.838787 c
7.762947 2.912254 7.630817 2.771599 7.397222 2.825178 c
7.694556 4.121515 l
h
4.941034 2.421919 m
4.518973 2.185223 3.984706 2.063799 3.502597 2.019850 c
3.266237 1.998302 3.056922 1.996719 2.899935 2.005188 c
2.821182 2.009438 2.761494 2.015903 2.721901 2.022036 c
2.669684 2.030127 2.683973 2.032768 2.729195 2.013800 c
2.214746 0.787323 l
2.322490 0.742130 2.437665 0.720205 2.518294 0.707714 c
2.611548 0.693268 2.716668 0.683142 2.828284 0.677120 c
3.052034 0.665049 3.325697 0.668207 3.623343 0.695341 c
4.209246 0.748755 4.947106 0.900452 5.591593 1.261889 c
4.941034 2.421919 l
h
2.729195 2.013800 m
2.749930 2.005102 2.882758 1.946644 2.968039 1.777296 c
3.061458 1.591787 3.022986 1.426355 3.001172 1.364454 c
2.982595 1.311741 2.964163 1.295036 2.989081 1.328537 c
3.009508 1.355999 3.043106 1.396255 3.097501 1.456871 c
3.303000 1.685871 3.720195 2.103413 4.080953 2.656435 c
2.967015 3.383101 l
2.678986 2.941566 2.367350 2.634581 2.107628 2.345156 c
2.045717 2.276165 1.979485 2.199696 1.921927 2.122314 c
1.868860 2.050972 1.794289 1.941307 1.746787 1.806517 c
1.696047 1.662539 1.655866 1.425913 1.780159 1.179098 c
1.896313 0.948442 2.092599 0.838558 2.214746 0.787323 c
2.729195 2.013800 l
h
4.080953 2.656435 m
4.494962 3.291088 4.613440 3.980347 4.585420 4.541801 c
4.571406 4.822594 4.520174 5.086731 4.439862 5.311481 c
4.369761 5.507656 4.241846 5.775682 4.006453 5.948018 c
3.220784 4.874880 l
3.130925 4.940668 3.145670 4.980780 3.187423 4.863935 c
3.218965 4.775667 3.248780 4.641680 3.257073 4.475508 c
3.273666 4.143036 3.201793 3.743002 2.967015 3.383101 c
4.080953 2.656435 l
h
4.006453 5.948018 m
1.882439 7.503057 0.665000 9.659537 0.665000 12.288485 c
-0.665000 12.288485 l
-0.665000 9.190426 0.792707 6.652532 3.220784 4.874880 c
4.006453 5.948018 l
h
0.665000 12.288485 m
0.665000 13.117238 0.797420 13.917267 1.044152 14.673008 c
-0.220173 15.085781 l
-0.509575 14.199340 -0.665000 13.260109 -0.665000 12.288485 c
0.665000 12.288485 l
h
f
n
Q
q
1.000000 0.000000 -0.000000 1.000000 7.000000 19.669922 cm
0.949020 0.509804 0.164706 scn
0.000000 6.995078 m
-0.367269 6.995078 -0.665000 6.697348 -0.665000 6.330078 c
-0.665000 5.962809 -0.367269 5.665078 0.000000 5.665078 c
0.000000 6.995078 l
h
5.000000 6.330078 m
5.470226 5.859852 l
5.660415 6.050041 5.717309 6.336069 5.614380 6.584563 c
5.511451 6.833056 5.268968 6.995078 5.000000 6.995078 c
5.000000 6.330078 l
h
0.000000 1.330078 m
-0.470226 1.800304 l
-0.660415 1.610116 -0.717309 1.324087 -0.614380 1.075593 c
-0.511451 0.827100 -0.268967 0.665078 0.000000 0.665078 c
0.000000 1.330078 l
h
5.000000 0.665078 m
5.367270 0.665078 5.665000 0.962809 5.665000 1.330078 c
5.665000 1.697348 5.367270 1.995078 5.000000 1.995078 c
5.000000 0.665078 l
h
0.000000 5.665078 m
5.000000 5.665078 l
5.000000 6.995078 l
0.000000 6.995078 l
0.000000 5.665078 l
h
4.529774 6.800304 m
-0.470226 1.800304 l
0.470226 0.859852 l
5.470226 5.859852 l
4.529774 6.800304 l
h
0.000000 0.665078 m
5.000000 0.665078 l
5.000000 1.995078 l
0.000000 1.995078 l
0.000000 0.665078 l
h
f
n
Q
q
1.000000 0.000000 -0.000000 1.000000 15.000000 13.669922 cm
0.949020 0.509804 0.164706 scn
0.000000 5.995078 m
-0.367269 5.995078 -0.665000 5.697348 -0.665000 5.330078 c
-0.665000 4.962809 -0.367269 4.665078 0.000000 4.665078 c
0.000000 5.995078 l
h
4.000000 5.330078 m
4.470226 4.859852 l
4.660415 5.050041 4.717309 5.336069 4.614380 5.584563 c
4.511451 5.833056 4.268968 5.995078 4.000000 5.995078 c
4.000000 5.330078 l
h
0.000000 1.330078 m
-0.470226 1.800304 l
-0.660415 1.610116 -0.717309 1.324087 -0.614380 1.075593 c
-0.511451 0.827100 -0.268967 0.665078 0.000000 0.665078 c
0.000000 1.330078 l
h
4.000000 0.665078 m
4.367270 0.665078 4.665000 0.962809 4.665000 1.330078 c
4.665000 1.697347 4.367270 1.995078 4.000000 1.995078 c
4.000000 0.665078 l
h
0.000000 4.665078 m
4.000000 4.665078 l
4.000000 5.995078 l
0.000000 5.995078 l
0.000000 4.665078 l
h
3.529774 5.800304 m
-0.470226 1.800304 l
0.470226 0.859852 l
4.470226 4.859852 l
3.529774 5.800304 l
h
0.000000 0.665078 m
4.000000 0.665078 l
4.000000 1.995078 l
0.000000 1.995078 l
0.000000 0.665078 l
h
f
n
Q
endstream
endobj
3 0 obj
5735
endobj
4 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 30.000000 30.000000 ]
/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
0000005825 00000 n
0000005848 00000 n
0000006021 00000 n
0000006095 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
6154
%%EOF

View File

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "bot_30.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,345 @@
%PDF-1.7
1 0 obj
<< >>
endobj
2 0 obj
<< /Length 3 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
15.180588 25.111094 m
19.269030 25.111094 22.583366 21.796757 22.583366 17.708317 c
22.583366 10.477497 l
22.583366 8.388166 20.889627 6.694427 18.800297 6.694427 c
6.658101 6.694427 l
6.358946 6.694427 6.116434 6.936939 6.116434 7.236094 c
6.116434 7.348185 6.151209 7.457516 6.215963 7.549011 c
7.246989 9.005806 l
7.592346 9.493778 7.777810 10.076874 7.777810 10.674694 c
7.777810 17.708317 l
7.777810 21.796757 11.092146 25.111094 15.180588 25.111094 c
h
W*
n
q
1.000000 0.000000 -0.000000 1.000000 6.116434 6.694427 cm
0.905882 0.582745 0.098039 scn
4.283545 6.640582 m
13.883546 6.640582 l
13.883546 7.970582 l
4.283545 7.970582 l
4.283545 6.640582 l
h
16.548546 9.305582 m
16.548546 10.305582 l
15.218545 10.305582 l
15.218545 9.305582 l
16.548546 9.305582 l
h
2.948545 9.305582 m
2.948545 10.305582 l
1.618545 10.305582 l
1.618545 9.305582 l
2.948545 9.305582 l
h
13.883546 6.640582 m
15.355385 6.640582 16.548546 7.833743 16.548546 9.305582 c
15.218545 9.305582 l
15.218545 8.568282 14.620845 7.970582 13.883546 7.970582 c
13.883546 6.640582 l
h
4.283545 7.970582 m
3.546245 7.970582 2.948545 8.568282 2.948545 9.305582 c
1.618545 9.305582 l
1.618545 7.833743 2.811706 6.640582 4.283545 6.640582 c
4.283545 7.970582 l
h
0.099529 0.854584 m
-0.986089 1.622915 l
-0.986089 1.622915 l
0.099529 0.854584 l
h
1.130555 2.311378 m
2.216174 1.543047 l
2.216174 1.543047 l
1.130555 2.311378 l
h
9.064154 17.086666 m
12.418056 17.086666 15.136932 14.367790 15.136932 11.013888 c
17.796932 11.013888 l
17.796932 15.836868 13.887134 19.746666 9.064154 19.746666 c
9.064154 17.086666 l
h
15.136932 11.013888 m
15.136932 3.783070 l
17.796932 3.783070 l
17.796932 11.013888 l
15.136932 11.013888 l
h
15.136932 3.783070 m
15.136932 2.428277 14.038655 1.330000 12.683863 1.330000 c
12.683863 -1.330000 l
15.507732 -1.330000 17.796932 0.959200 17.796932 3.783070 c
15.136932 3.783070 l
h
12.683863 1.330000 m
0.541667 1.330000 l
0.541667 -1.330000 l
12.683863 -1.330000 l
12.683863 1.330000 l
h
0.541667 1.330000 m
0.977049 1.330000 1.330000 0.977053 1.330000 0.541666 c
-1.330000 0.541666 l
-1.330000 -0.492029 -0.492025 -1.330000 0.541667 -1.330000 c
0.541667 1.330000 l
h
1.330000 0.541666 m
1.330000 0.378532 1.279391 0.219414 1.185147 0.086252 c
-0.986089 1.622915 l
-1.209841 1.306763 -1.330000 0.928982 -1.330000 0.541666 c
1.330000 0.541666 l
h
1.185147 0.086252 m
2.216174 1.543047 l
0.044937 3.079710 l
-0.986089 1.622915 l
1.185147 0.086252 l
h
2.216174 1.543047 m
2.720526 2.255676 2.991376 3.107221 2.991376 3.980268 c
0.331376 3.980268 l
0.331376 3.657675 0.231297 3.343028 0.044937 3.079710 c
2.216174 1.543047 l
h
2.991376 3.980268 m
2.991376 11.013888 l
0.331376 11.013888 l
0.331376 3.980268 l
2.991376 3.980268 l
h
2.991376 11.013888 m
2.991376 14.367791 5.710251 17.086666 9.064154 17.086666 c
9.064154 19.746666 l
4.241174 19.746666 0.331376 15.836868 0.331376 11.013888 c
2.991376 11.013888 l
h
f
n
Q
Q
q
1.000000 0.000000 -0.000000 1.000000 24.500000 9.670000 cm
0.905882 0.582745 0.098039 scn
0.665000 7.330000 m
0.665000 7.697269 0.367269 7.995000 0.000000 7.995000 c
-0.367269 7.995000 -0.665000 7.697269 -0.665000 7.330000 c
0.665000 7.330000 l
h
-0.665000 1.330000 m
-0.665000 0.962730 -0.367269 0.665000 0.000000 0.665000 c
0.367269 0.665000 0.665000 0.962730 0.665000 1.330000 c
-0.665000 1.330000 l
h
-0.665000 7.330000 m
-0.665000 1.330000 l
0.665000 1.330000 l
0.665000 7.330000 l
-0.665000 7.330000 l
h
f
n
Q
q
1.000000 0.000000 -0.000000 1.000000 5.500000 9.670000 cm
0.905882 0.582745 0.098039 scn
0.665000 7.330000 m
0.665000 7.697269 0.367269 7.995000 0.000000 7.995000 c
-0.367269 7.995000 -0.665000 7.697269 -0.665000 7.330000 c
0.665000 7.330000 l
h
-0.665000 1.330000 m
-0.665000 0.962730 -0.367269 0.665000 0.000000 0.665000 c
0.367269 0.665000 0.665000 0.962730 0.665000 1.330000 c
-0.665000 1.330000 l
h
-0.665000 7.330000 m
-0.665000 1.330000 l
0.665000 1.330000 l
0.665000 7.330000 l
-0.665000 7.330000 l
h
f
n
Q
q
q
1.000000 0.000000 -0.000000 1.000000 16.444336 16.805582 cm
1.000000 1.000000 1.000000 scn
1.083333 0.000000 m
1.681642 0.000000 2.166667 0.606281 2.166667 1.354167 c
2.166667 2.102052 1.681642 2.708333 1.083333 2.708333 c
0.485025 2.708333 0.000000 2.102052 0.000000 1.354167 c
0.000000 0.606281 0.485025 0.000000 1.083333 0.000000 c
h
f
n
Q
17.527670 16.805584 m
18.125978 16.805584 18.611002 17.411863 18.611002 18.159748 c
18.611002 18.907635 18.125978 19.513916 17.527670 19.513916 c
16.929361 19.513916 16.444336 18.907635 16.444336 18.159748 c
16.444336 17.411863 16.929361 16.805584 17.527670 16.805584 c
h
W*
n
q
1.000000 0.000000 -0.000000 1.000000 16.444336 16.805582 cm
0.905882 0.582745 0.098039 scn
0.836667 1.354167 m
0.836667 1.261054 0.805378 1.220680 0.810810 1.227471 c
0.814971 1.232672 0.836092 1.257200 0.883374 1.282198 c
0.933451 1.308675 1.003185 1.330000 1.083333 1.330000 c
1.083333 -1.330000 l
2.677790 -1.330000 3.496667 0.164029 3.496667 1.354167 c
0.836667 1.354167 l
h
1.083333 1.330000 m
1.163481 1.330000 1.233215 1.308675 1.283293 1.282198 c
1.330575 1.257200 1.351696 1.232672 1.355857 1.227471 c
1.361289 1.220680 1.330000 1.261054 1.330000 1.354167 c
-1.330000 1.354167 l
-1.330000 0.164029 -0.511123 -1.330000 1.083333 -1.330000 c
1.083333 1.330000 l
h
1.330000 1.354167 m
1.330000 1.447279 1.361289 1.487653 1.355857 1.480863 c
1.351696 1.475661 1.330575 1.451133 1.283293 1.426135 c
1.233215 1.399659 1.163481 1.378333 1.083333 1.378333 c
1.083333 4.038333 l
-0.511123 4.038333 -1.330000 2.544304 -1.330000 1.354167 c
1.330000 1.354167 l
h
1.083333 1.378333 m
1.003185 1.378333 0.933451 1.399659 0.883374 1.426135 c
0.836092 1.451133 0.814971 1.475661 0.810810 1.480863 c
0.805378 1.487653 0.836667 1.447279 0.836667 1.354167 c
3.496667 1.354167 l
3.496667 2.544304 2.677790 4.038333 1.083333 4.038333 c
1.083333 1.378333 l
h
f
n
Q
Q
q
q
1.000000 0.000000 -0.000000 1.000000 11.749980 16.805582 cm
1.000000 1.000000 1.000000 scn
1.083333 0.000000 m
1.681642 0.000000 2.166667 0.606281 2.166667 1.354167 c
2.166667 2.102052 1.681642 2.708333 1.083333 2.708333 c
0.485025 2.708333 0.000000 2.102052 0.000000 1.354167 c
0.000000 0.606281 0.485025 0.000000 1.083333 0.000000 c
h
f
n
Q
12.833313 16.805584 m
13.431622 16.805584 13.916647 17.411863 13.916647 18.159748 c
13.916647 18.907635 13.431622 19.513916 12.833313 19.513916 c
12.235004 19.513916 11.749980 18.907635 11.749980 18.159748 c
11.749980 17.411863 12.235004 16.805584 12.833313 16.805584 c
h
W*
n
q
1.000000 0.000000 -0.000000 1.000000 11.749980 16.805582 cm
0.905882 0.582745 0.098039 scn
0.836667 1.354167 m
0.836667 1.261054 0.805378 1.220680 0.810810 1.227471 c
0.814971 1.232672 0.836092 1.257200 0.883374 1.282198 c
0.933451 1.308675 1.003185 1.330000 1.083333 1.330000 c
1.083333 -1.330000 l
2.677790 -1.330000 3.496667 0.164029 3.496667 1.354167 c
0.836667 1.354167 l
h
1.083333 1.330000 m
1.163481 1.330000 1.233215 1.308675 1.283293 1.282198 c
1.330575 1.257200 1.351696 1.232672 1.355857 1.227471 c
1.361289 1.220680 1.330000 1.261054 1.330000 1.354167 c
-1.330000 1.354167 l
-1.330000 0.164029 -0.511123 -1.330000 1.083333 -1.330000 c
1.083333 1.330000 l
h
1.330000 1.354167 m
1.330000 1.447279 1.361289 1.487653 1.355857 1.480863 c
1.351696 1.475661 1.330575 1.451133 1.283293 1.426135 c
1.233215 1.399659 1.163481 1.378333 1.083333 1.378333 c
1.083333 4.038333 l
-0.511123 4.038333 -1.330000 2.544304 -1.330000 1.354167 c
1.330000 1.354167 l
h
1.083333 1.378333 m
1.003185 1.378333 0.933451 1.399659 0.883374 1.426135 c
0.836092 1.451133 0.814971 1.475661 0.810810 1.480863 c
0.805378 1.487653 0.836667 1.447279 0.836667 1.354167 c
3.496667 1.354167 l
3.496667 2.544304 2.677790 4.038333 1.083333 4.038333 c
1.083333 1.378333 l
h
f
n
Q
Q
endstream
endobj
3 0 obj
7739
endobj
4 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 30.000000 30.000000 ]
/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
0000007829 00000 n
0000007852 00000 n
0000008025 00000 n
0000008099 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
8158
%%EOF

View File

@ -0,0 +1,9 @@
{
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"provides-namespace" : true
}
}

View File

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "greeting_30.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,132 @@
%PDF-1.7
1 0 obj
<< >>
endobj
2 0 obj
<< /Length 3 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
0.707107 0.707107 -0.707107 0.707107 21.364445 -3.965183 cm
0.913725 0.364706 0.266667 scn
8.477501 26.956133 m
7.981826 26.956133 7.580001 26.554308 7.580001 26.058632 c
7.580001 24.808632 l
7.580001 20.121132 l
7.580001 18.246132 l
7.580001 17.878864 7.282270 17.581133 6.915001 17.581133 c
6.547732 17.581133 6.250001 17.878864 6.250001 18.246132 c
6.250001 20.121132 l
6.250001 24.808632 l
6.250001 25.304308 5.848176 25.706133 5.352501 25.706133 c
4.856825 25.706133 4.455001 25.304308 4.455001 24.808632 c
4.455001 22.308632 l
4.455001 18.871132 l
4.455001 17.621132 l
4.455001 17.253864 4.157270 16.956133 3.790001 16.956133 c
3.422732 16.956133 3.125001 17.253864 3.125001 17.621132 c
3.125001 18.871132 l
3.125001 22.308632 l
3.125001 22.804308 2.723176 23.206133 2.227501 23.206133 c
1.731825 23.206133 1.330001 22.804308 1.330001 22.308632 c
1.330001 15.746132 l
1.330001 15.155248 1.330360 14.891902 1.344635 14.674103 c
1.568969 11.251431 4.295299 8.525101 7.717971 8.300766 c
7.935771 8.286491 8.199116 8.286133 8.790001 8.286133 c
11.187643 8.286133 13.360397 9.698147 14.334173 11.889143 c
17.002613 17.893135 l
17.168566 18.266527 17.011471 18.704405 16.645998 18.887142 c
16.268457 19.075912 15.809368 18.922882 15.620598 18.545341 c
13.759795 14.823736 l
13.621869 14.547884 13.312377 14.403064 13.012215 14.473922 c
12.712053 14.544781 12.500001 14.812721 12.500001 15.121133 c
12.500001 24.808632 l
12.500001 25.304308 12.098177 25.706133 11.602501 25.706133 c
11.106825 25.706133 10.705001 25.304308 10.705001 24.808632 c
10.705001 18.871132 l
10.705001 18.246132 l
10.705001 17.878864 10.407270 17.581133 10.040001 17.581133 c
9.672731 17.581133 9.375001 17.878864 9.375001 18.246132 c
9.375001 18.871132 l
9.375001 24.808632 l
9.375001 26.058632 l
9.375001 26.554308 8.973177 26.956133 8.477501 26.956133 c
h
10.582383 26.789337 m
10.279950 27.660648 9.451770 28.286133 8.477501 28.286133 c
7.503232 28.286133 6.675053 27.660648 6.372619 26.789337 c
6.066981 26.947069 5.720144 27.036133 5.352501 27.036133 c
4.122287 27.036133 3.125001 26.038847 3.125001 24.808632 c
3.125001 24.347933 l
2.850438 24.468945 2.546816 24.536133 2.227501 24.536133 c
0.997287 24.536133 0.000000 23.538847 0.000000 22.308632 c
0.000000 15.746132 l
0.000000 15.713078 l
0.000000 15.713053 l
-0.000006 15.163960 -0.000010 14.854001 0.017483 14.587116 c
0.285469 10.498438 3.542306 7.241600 7.630985 6.973614 c
7.897878 6.956120 8.207848 6.956123 8.756974 6.956131 c
8.790001 6.956131 l
11.713245 6.956131 14.362301 8.677685 15.549542 11.348978 c
18.217983 17.352970 l
18.672722 18.376133 18.242252 19.576000 17.240791 20.076729 c
16.206259 20.593996 14.948276 20.174667 14.431009 19.140135 c
13.830001 17.938118 l
13.830001 24.808632 l
13.830001 26.038847 12.832715 27.036133 11.602501 27.036133 c
11.234859 27.036133 10.888021 26.947069 10.582383 26.789337 c
h
f*
n
Q
endstream
endobj
3 0 obj
2901
endobj
4 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 30.000000 30.000000 ]
/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
0000002991 00000 n
0000003014 00000 n
0000003187 00000 n
0000003261 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
3320
%%EOF

View File

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "clock_30.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,89 @@
%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 4.334991 4.334961 cm
0.674510 0.392157 0.952941 scn
1.330000 10.665078 m
1.330000 15.820656 5.509422 20.000078 10.665000 20.000078 c
15.820578 20.000078 20.000000 15.820656 20.000000 10.665078 c
20.000000 5.509501 15.820578 1.330078 10.665000 1.330078 c
5.509422 1.330078 1.330000 5.509501 1.330000 10.665078 c
h
10.665000 21.330078 m
4.774883 21.330078 0.000000 16.555195 0.000000 10.665078 c
0.000000 4.774961 4.774883 0.000076 10.665000 0.000076 c
16.555117 0.000076 21.330002 4.774961 21.330002 10.665078 c
21.330002 16.555195 16.555117 21.330078 10.665000 21.330078 c
h
11.330000 17.165077 m
11.330000 17.532347 11.032269 17.830078 10.665000 17.830078 c
10.297730 17.830078 10.000000 17.532347 10.000000 17.165077 c
10.000000 11.114144 l
10.000000 10.638557 10.203376 10.185671 10.558834 9.869707 c
14.723198 6.168051 l
14.997698 5.924050 15.418027 5.948775 15.662027 6.223276 c
15.906028 6.497777 15.881302 6.918105 15.606802 7.162106 c
11.442438 10.863762 l
11.370919 10.927334 11.330000 11.018456 11.330000 11.114144 c
11.330000 17.165077 l
h
f*
n
Q
endstream
endobj
3 0 obj
1125
endobj
4 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 30.000000 30.000000 ]
/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
0000001215 00000 n
0000001238 00000 n
0000001411 00000 n
0000001485 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
1544
%%EOF

View File

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "location_30.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,131 @@
%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 6.562500 2.419922 cm
0.000000 0.478431 1.000000 scn
16.209999 15.392578 m
16.209999 12.542053 14.812269 9.154825 13.054974 6.448694 c
12.181865 5.104156 11.240838 3.960510 10.379677 3.161890 c
9.948750 2.762260 9.550818 2.461168 9.203439 2.263494 c
8.847299 2.060837 8.593635 1.995079 8.437500 1.995079 c
8.437500 0.665079 l
8.918997 0.665079 9.407229 0.849205 9.861220 1.107544 c
10.323971 1.370867 10.804404 1.741882 11.284050 2.186693 c
12.244032 3.076956 13.252973 4.311531 14.170422 5.724348 c
15.994245 8.532929 17.540001 12.176950 17.540001 15.392578 c
16.209999 15.392578 l
h
8.437500 1.995079 m
8.281365 1.995079 8.027701 2.060837 7.671562 2.263494 c
7.324182 2.461168 6.926250 2.762260 6.495324 3.161890 c
5.634162 3.960510 4.693136 5.104156 3.820026 6.448694 c
2.062731 9.154825 0.665000 12.542053 0.665000 15.392578 c
-0.665000 15.392578 l
-0.665000 12.176950 0.880755 8.532929 2.704578 5.724348 c
3.622028 4.311531 4.630968 3.076956 5.590950 2.186693 c
6.070596 1.741882 6.551029 1.370867 7.013780 1.107544 c
7.467771 0.849205 7.956003 0.665079 8.437500 0.665079 c
8.437500 1.995079 l
h
0.665000 15.392578 m
0.665000 19.685211 4.144866 23.165077 8.437500 23.165077 c
8.437500 24.495079 l
3.410328 24.495079 -0.665000 20.419750 -0.665000 15.392578 c
0.665000 15.392578 l
h
8.437500 23.165077 m
12.730133 23.165077 16.209999 19.685211 16.209999 15.392578 c
17.540001 15.392578 l
17.540001 20.419750 13.464672 24.495079 8.437500 24.495079 c
8.437500 23.165077 l
h
f
n
Q
q
1.000000 0.000000 -0.000000 1.000000 11.625061 13.107422 cm
0.000000 0.478431 1.000000 scn
6.085000 4.705078 m
6.085000 3.208386 4.871692 1.995078 3.375000 1.995078 c
3.375000 0.665078 l
5.606230 0.665078 7.415000 2.473848 7.415000 4.705078 c
6.085000 4.705078 l
h
3.375000 1.995078 m
1.878308 1.995078 0.665000 3.208386 0.665000 4.705078 c
-0.665000 4.705078 l
-0.665000 2.473848 1.143770 0.665078 3.375000 0.665078 c
3.375000 1.995078 l
h
0.665000 4.705078 m
0.665000 6.201770 1.878308 7.415078 3.375000 7.415078 c
3.375000 8.745078 l
1.143770 8.745078 -0.665000 6.936308 -0.665000 4.705078 c
0.665000 4.705078 l
h
3.375000 7.415078 m
4.871692 7.415078 6.085000 6.201770 6.085000 4.705078 c
7.415000 4.705078 l
7.415000 6.936308 5.606230 8.745078 3.375000 8.745078 c
3.375000 7.415078 l
h
f
n
Q
endstream
endobj
3 0 obj
2346
endobj
4 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 30.000000 30.000000 ]
/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
0000002436 00000 n
0000002459 00000 n
0000002632 00000 n
0000002706 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
2765
%%EOF

View File

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "arrowshape_30.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,163 @@
%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 24.973328 5.818359 cm
0.768627 0.337255 0.682353 scn
10.631250 12.931641 m
10.631250 12.266641 l
10.998520 12.266641 11.296250 12.564371 11.296250 12.931641 c
10.631250 12.931641 l
h
10.631250 5.431641 m
11.296250 5.431641 l
11.296250 5.608009 11.226188 5.777155 11.101477 5.901867 c
10.976765 6.026578 10.807619 6.096641 10.631250 6.096641 c
10.631250 5.431641 l
h
1.188047 1.543245 m
0.685782 1.979084 l
1.188047 1.543245 l
h
12.315193 1.385338 m
12.770014 0.900196 l
12.315193 1.385338 l
h
19.853075 9.911179 m
19.398254 9.426036 l
19.853075 9.911179 l
h
19.853075 8.452104 m
19.398254 8.937245 l
19.853075 8.452104 l
h
12.315191 16.977945 m
12.770013 17.463087 l
12.315191 16.977945 l
h
11.296250 12.931641 m
11.296250 16.248409 l
9.966250 16.248409 l
9.966250 12.931641 l
11.296250 12.931641 l
h
11.860371 16.492804 m
19.398254 9.426036 l
20.307896 10.396320 l
12.770013 17.463087 l
11.860371 16.492804 l
h
19.398254 8.937245 m
11.860373 1.870480 l
12.770014 0.900196 l
20.307896 7.966961 l
19.398254 8.937245 l
h
11.296250 2.114872 m
11.296250 5.431641 l
9.966250 5.431641 l
9.966250 2.114872 l
11.296250 2.114872 l
h
10.631250 6.096641 m
5.284963 6.096641 2.224191 3.751969 0.685782 1.979084 c
1.690313 1.107409 l
3.019733 2.639451 5.732319 4.766641 10.631250 4.766641 c
10.631250 6.096641 l
h
0.751247 1.844767 m
0.928412 3.653876 1.448427 6.281533 2.899223 8.440295 c
4.323280 10.559272 6.666468 12.266641 10.631250 12.266641 c
10.631250 13.596641 l
6.198088 13.596641 3.451934 11.647133 1.795346 9.182156 c
0.165498 6.756965 -0.386434 3.873591 -0.572421 1.974394 c
0.751247 1.844767 l
h
0.685782 1.979084 m
0.708566 2.005341 0.730995 2.010473 0.729708 2.010210 c
0.724951 2.009233 0.709156 2.008541 0.691761 2.014082 c
0.673009 2.020056 0.683957 2.022552 0.705669 1.995995 c
0.717778 1.981184 0.731929 1.958406 0.741572 1.928011 c
0.751477 1.896788 0.753460 1.867371 0.751247 1.844767 c
-0.572421 1.974394 l
-0.639368 1.290768 -0.129882 0.879953 0.288116 0.746813 c
0.703101 0.614634 1.296561 0.653643 1.690313 1.107409 c
0.685782 1.979084 l
h
11.860373 1.870480 m
11.646417 1.669897 11.296250 1.821604 11.296250 2.114872 c
9.966250 2.114872 l
9.966250 0.657263 11.706638 -0.096720 12.770014 0.900196 c
11.860373 1.870480 l
h
19.398254 9.426036 m
19.539427 9.293686 19.539427 9.069594 19.398254 8.937245 c
20.307896 7.966961 l
21.009548 8.624760 21.009546 9.738523 20.307896 10.396320 c
19.398254 9.426036 l
h
11.296250 16.248409 m
11.296250 16.541679 11.646418 16.693384 11.860371 16.492804 c
12.770013 17.463087 l
11.706634 18.460005 9.966250 17.706017 9.966250 16.248409 c
11.296250 16.248409 l
h
f
n
Q
endstream
endobj
3 0 obj
2685
endobj
4 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 30.000000 30.000000 ]
/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
0000002775 00000 n
0000002798 00000 n
0000002971 00000 n
0000003045 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
3104
%%EOF

View File

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "bubble_30.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,191 @@
%PDF-1.7
1 0 obj
<< /Type /XObject
/Length 2 0 R
/Group << /Type /Group
/S /Transparency
>>
/Subtype /Form
/Resources << >>
/BBox [ 0.000000 0.000000 30.000000 30.000000 ]
>>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 5.000000 4.484373 cm
1.000000 1.000000 1.000000 scn
10.000000 20.135622 m
15.522848 20.135622 20.000000 16.065483 20.000000 11.044713 c
20.000000 6.023943 15.522848 1.953804 10.000000 1.953804 c
9.153261 1.953804 8.331102 2.049475 7.545889 2.229576 c
7.397357 2.263645 7.228708 2.107862 6.947171 1.847807 c
6.606689 1.533304 6.101101 1.066292 5.266314 0.598133 c
4.199766 0.000000 2.722059 0.051891 2.471971 0.156792 c
2.232201 0.257364 2.416753 0.457279 2.741760 0.809345 c
2.966608 1.052914 3.258681 1.369303 3.523984 1.775997 c
4.172771 2.770552 3.904685 3.954582 3.613619 4.167679 c
1.337573 5.834023 0.000000 8.181211 0.000000 11.044713 c
0.000000 16.065483 4.477152 20.135622 10.000000 20.135622 c
h
4.495019 14.850605 m
4.127750 14.850605 3.830019 15.148335 3.830019 15.515605 c
3.830019 15.882874 4.127750 16.180605 4.495019 16.180605 c
9.495019 16.180605 l
9.763987 16.180605 10.006470 16.018583 10.109399 15.770090 c
10.212329 15.521596 10.155434 15.235567 9.965245 15.045379 c
6.100471 11.180605 l
9.495019 11.180605 l
9.862288 11.180605 10.160019 10.882874 10.160019 10.515605 c
10.160019 10.148335 9.862288 9.850605 9.495019 9.850605 c
4.495019 9.850605 l
4.226052 9.850605 3.983569 10.012627 3.880640 10.261120 c
3.777710 10.509614 3.834605 10.795643 4.024793 10.985830 c
7.889567 14.850605 l
4.495019 14.850605 l
h
11.495019 9.850605 m
11.127749 9.850605 10.830019 10.148335 10.830019 10.515605 c
10.830019 10.882874 11.127749 11.180605 11.495019 11.180605 c
15.495020 11.180605 l
15.763987 11.180605 16.006470 11.018583 16.109400 10.770090 c
16.212328 10.521596 16.155434 10.235567 15.965245 10.045380 c
13.100471 7.180605 l
15.495020 7.180605 l
15.862289 7.180605 16.160019 6.882874 16.160019 6.515605 c
16.160019 6.148335 15.862289 5.850605 15.495020 5.850605 c
11.495019 5.850605 l
11.226052 5.850605 10.983569 6.012627 10.880639 6.261120 c
10.777710 6.509614 10.834604 6.795643 11.024794 6.985831 c
13.889567 9.850605 l
11.495019 9.850605 l
h
f*
n
Q
endstream
endobj
2 0 obj
2037
endobj
3 0 obj
<< /Type /XObject
/Length 4 0 R
/Group << /Type /Group
/S /Transparency
>>
/Subtype /Form
/Resources << >>
/BBox [ 0.000000 0.000000 30.000000 30.000000 ]
>>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 0.000000 0.000000 cm
0.000000 0.000000 0.000000 scn
0.000000 18.799999 m
0.000000 22.720367 0.000000 24.680552 0.762954 26.177933 c
1.434068 27.495068 2.504932 28.565931 3.822066 29.237045 c
5.319448 30.000000 7.279633 30.000000 11.200000 30.000000 c
18.799999 30.000000 l
22.720367 30.000000 24.680552 30.000000 26.177933 29.237045 c
27.495068 28.565931 28.565931 27.495068 29.237045 26.177933 c
30.000000 24.680552 30.000000 22.720367 30.000000 18.799999 c
30.000000 11.200001 l
30.000000 7.279633 30.000000 5.319448 29.237045 3.822067 c
28.565931 2.504932 27.495068 1.434069 26.177933 0.762955 c
24.680552 0.000000 22.720367 0.000000 18.799999 0.000000 c
11.200000 0.000000 l
7.279633 0.000000 5.319448 0.000000 3.822066 0.762955 c
2.504932 1.434069 1.434068 2.504932 0.762954 3.822067 c
0.000000 5.319448 0.000000 7.279633 0.000000 11.200001 c
0.000000 18.799999 l
h
f
n
Q
endstream
endobj
4 0 obj
944
endobj
5 0 obj
<< /XObject << /X1 1 0 R >>
/ExtGState << /E1 << /SMask << /Type /Mask
/G 3 0 R
/S /Alpha
>>
/Type /ExtGState
>> >>
>>
endobj
6 0 obj
<< /Length 7 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
/E1 gs
/X1 Do
Q
endstream
endobj
7 0 obj
46
endobj
8 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 30.000000 30.000000 ]
/Resources 5 0 R
/Contents 6 0 R
/Parent 9 0 R
>>
endobj
9 0 obj
<< /Kids [ 8 0 R ]
/Count 1
/Type /Pages
>>
endobj
10 0 obj
<< /Pages 9 0 R
/Type /Catalog
>>
endobj
xref
0 11
0000000000 65535 f
0000000010 00000 n
0000002295 00000 n
0000002318 00000 n
0000003510 00000 n
0000003532 00000 n
0000003830 00000 n
0000003932 00000 n
0000003953 00000 n
0000004126 00000 n
0000004200 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 10 0 R
/Size 11
>>
startxref
4260
%%EOF

View File

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "bots_30.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,219 @@
%PDF-1.7
1 0 obj
<< /Type /XObject
/Length 2 0 R
/Group << /Type /Group
/S /Transparency
>>
/Subtype /Form
/Resources << >>
/BBox [ 0.000000 0.000000 30.000000 30.000000 ]
>>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 6.116440 6.694427 cm
1.000000 1.000000 1.000000 scn
9.064154 18.416666 m
13.152596 18.416666 16.466932 15.102329 16.466932 11.013888 c
16.466932 3.783070 l
16.466932 1.693737 14.773193 0.000000 12.683863 0.000000 c
0.541667 0.000000 l
0.242512 0.000000 0.000000 0.242512 0.000000 0.541666 c
0.000000 0.653757 0.034775 0.763088 0.099529 0.854584 c
1.130555 2.311378 l
1.475911 2.799352 1.661376 3.382448 1.661376 3.980268 c
1.661376 11.013888 l
1.661376 15.102329 4.975713 18.416666 9.064154 18.416666 c
h
9.064154 16.611111 m
5.873175 16.611111 3.466932 14.024311 3.466932 10.833333 c
3.466932 9.750000 l
3.466932 8.553383 4.436981 7.583333 5.633598 7.583333 c
12.494710 7.583333 l
13.691326 7.583333 14.661376 8.553383 14.661376 9.750000 c
14.661376 10.833333 l
14.661376 14.024311 12.255133 16.611111 9.064154 16.611111 c
h
f*
n
Q
q
1.000000 0.000000 -0.000000 1.000000 24.027679 10.305583 cm
1.000000 1.000000 1.000000 scn
1.263889 7.583333 m
1.961915 7.583333 2.527778 7.017471 2.527778 6.319444 c
2.527778 1.263889 l
2.527778 0.565862 1.961915 0.000000 1.263889 0.000000 c
0.565862 0.000000 0.000000 0.565862 0.000000 1.263889 c
0.000000 6.319444 l
0.000000 7.017471 0.565862 7.583333 1.263889 7.583333 c
h
f*
n
Q
q
1.000000 0.000000 -0.000000 1.000000 3.805634 10.305583 cm
1.000000 1.000000 1.000000 scn
1.263889 7.583333 m
1.961915 7.583333 2.527778 7.017471 2.527778 6.319444 c
2.527778 1.263889 l
2.527778 0.565862 1.961915 0.000000 1.263889 0.000000 c
0.565862 0.000000 0.000000 0.565862 0.000000 1.263889 c
0.000000 6.319444 l
-0.000000 7.017471 0.565862 7.583333 1.263889 7.583333 c
h
f*
n
Q
q
1.000000 0.000000 -0.000000 1.000000 16.444336 16.805582 cm
1.000000 1.000000 1.000000 scn
1.083333 0.000000 m
1.681642 0.000000 2.166667 0.606281 2.166667 1.354167 c
2.166667 2.102052 1.681642 2.708333 1.083333 2.708333 c
0.485025 2.708333 0.000000 2.102052 0.000000 1.354167 c
0.000000 0.606281 0.485025 0.000000 1.083333 0.000000 c
h
f
n
Q
q
1.000000 0.000000 -0.000000 1.000000 11.749985 16.805582 cm
1.000000 1.000000 1.000000 scn
1.083333 0.000000 m
1.681642 0.000000 2.166667 0.606281 2.166667 1.354167 c
2.166667 2.102052 1.681642 2.708333 1.083333 2.708333 c
0.485025 2.708333 0.000000 2.102052 0.000000 1.354167 c
0.000000 0.606281 0.485025 0.000000 1.083333 0.000000 c
h
f
n
Q
endstream
endobj
2 0 obj
2362
endobj
3 0 obj
<< /Type /XObject
/Length 4 0 R
/Group << /Type /Group
/S /Transparency
>>
/Subtype /Form
/Resources << >>
/BBox [ 0.000000 0.000000 30.000000 30.000000 ]
>>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 0.000000 0.000000 cm
0.000000 0.000000 0.000000 scn
0.000000 18.799999 m
0.000000 22.720367 0.000000 24.680552 0.762954 26.177933 c
1.434068 27.495068 2.504932 28.565931 3.822066 29.237045 c
5.319448 30.000000 7.279633 30.000000 11.200000 30.000000 c
18.799999 30.000000 l
22.720367 30.000000 24.680552 30.000000 26.177933 29.237045 c
27.495068 28.565931 28.565931 27.495068 29.237045 26.177933 c
30.000000 24.680552 30.000000 22.720367 30.000000 18.799999 c
30.000000 11.200001 l
30.000000 7.279633 30.000000 5.319448 29.237045 3.822067 c
28.565931 2.504932 27.495068 1.434069 26.177933 0.762955 c
24.680552 0.000000 22.720367 0.000000 18.799999 0.000000 c
11.200000 0.000000 l
7.279633 0.000000 5.319448 0.000000 3.822066 0.762955 c
2.504932 1.434069 1.434068 2.504932 0.762954 3.822067 c
0.000000 5.319448 0.000000 7.279633 0.000000 11.200001 c
0.000000 18.799999 l
h
f
n
Q
endstream
endobj
4 0 obj
944
endobj
5 0 obj
<< /XObject << /X1 1 0 R >>
/ExtGState << /E1 << /SMask << /Type /Mask
/G 3 0 R
/S /Alpha
>>
/Type /ExtGState
>> >>
>>
endobj
6 0 obj
<< /Length 7 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
/E1 gs
/X1 Do
Q
endstream
endobj
7 0 obj
46
endobj
8 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 30.000000 30.000000 ]
/Resources 5 0 R
/Contents 6 0 R
/Parent 9 0 R
>>
endobj
9 0 obj
<< /Kids [ 8 0 R ]
/Count 1
/Type /Pages
>>
endobj
10 0 obj
<< /Pages 9 0 R
/Type /Catalog
>>
endobj
xref
0 11
0000000000 65535 f
0000000010 00000 n
0000002620 00000 n
0000002643 00000 n
0000003835 00000 n
0000003857 00000 n
0000004155 00000 n
0000004257 00000 n
0000004278 00000 n
0000004451 00000 n
0000004525 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 10 0 R
/Size 11
>>
startxref
4585
%%EOF

View File

@ -0,0 +1,9 @@
{
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"provides-namespace" : true
}
}

View File

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "hand_30.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,179 @@
%PDF-1.7
1 0 obj
<< /Type /XObject
/Length 2 0 R
/Group << /Type /Group
/S /Transparency
>>
/Subtype /Form
/Resources << >>
/BBox [ 0.000000 0.000000 30.000000 30.000000 ]
>>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 -1.000000 4.320007 27.950363 cm
1.000000 1.000000 1.000000 scn
10.373090 22.946411 m
8.050101 21.317602 6.380871 19.247253 3.543569 16.667921 c
2.650327 15.855877 1.641354 14.993408 0.459726 14.078381 c
-0.718856 13.199763 0.605010 11.424451 1.780190 12.300733 c
4.284061 14.316495 l
6.457295 16.066059 l
6.992327 16.464846 7.617038 15.710186 7.164680 15.251328 c
4.466011 12.361161 l
1.629065 9.322921 l
0.624206 8.311307 2.149370 6.786903 3.158343 7.802631 c
5.809480 10.646939 l
8.512617 13.547057 l
8.970664 14.011757 9.717809 13.382321 9.318110 12.852367 c
6.570284 9.038799 l
3.620909 4.945528 l
2.785100 3.800510 4.518925 2.518438 5.364432 3.676554 c
8.200414 7.617077 l
10.914721 11.388600 l
11.343113 11.956994 12.225388 11.391698 11.897746 10.766022 c
10.236183 7.393740 l
8.358699 3.583269 l
7.680109 2.287586 9.637981 1.253119 10.320378 2.555761 c
11.154462 4.237940 11.866668 5.668703 12.507628 6.913046 c
13.583075 9.000764 14.458188 10.563708 15.372758 11.909208 c
13.810371 13.033404 13.260308 15.011283 13.271937 16.524057 c
13.275494 17.002668 13.960785 17.091639 14.085300 16.628412 c
14.549137 14.900733 15.014801 13.949447 16.730040 13.483326 c
17.129435 11.600307 17.395174 10.225099 17.659185 9.251877 c
17.974030 8.091170 19.216747 7.441628 20.352520 7.854834 c
20.763288 8.004285 20.978806 8.471420 20.833063 8.896205 c
19.358934 13.192146 19.128235 15.167385 19.061663 19.011932 c
18.995647 23.248255 13.450435 25.104208 10.373090 22.946411 c
h
f
n
Q
endstream
endobj
2 0 obj
1535
endobj
3 0 obj
<< /Type /XObject
/Length 4 0 R
/Group << /Type /Group
/S /Transparency
>>
/Subtype /Form
/Resources << >>
/BBox [ 0.000000 0.000000 30.000000 30.000000 ]
>>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 0.000000 0.000000 cm
0.000000 0.000000 0.000000 scn
0.000000 18.799999 m
0.000000 22.720367 0.000000 24.680552 0.762954 26.177933 c
1.434068 27.495068 2.504932 28.565931 3.822066 29.237045 c
5.319448 30.000000 7.279633 30.000000 11.200000 30.000000 c
18.799999 30.000000 l
22.720367 30.000000 24.680552 30.000000 26.177933 29.237045 c
27.495068 28.565931 28.565931 27.495068 29.237045 26.177933 c
30.000000 24.680552 30.000000 22.720367 30.000000 18.799999 c
30.000000 11.200001 l
30.000000 7.279633 30.000000 5.319448 29.237045 3.822067 c
28.565931 2.504932 27.495068 1.434069 26.177933 0.762955 c
24.680552 0.000000 22.720367 0.000000 18.799999 0.000000 c
11.200000 0.000000 l
7.279633 0.000000 5.319448 0.000000 3.822066 0.762955 c
2.504932 1.434069 1.434068 2.504932 0.762954 3.822067 c
0.000000 5.319448 0.000000 7.279633 0.000000 11.200001 c
0.000000 18.799999 l
h
f
n
Q
endstream
endobj
4 0 obj
944
endobj
5 0 obj
<< /XObject << /X1 1 0 R >>
/ExtGState << /E1 << /SMask << /Type /Mask
/G 3 0 R
/S /Alpha
>>
/Type /ExtGState
>> >>
>>
endobj
6 0 obj
<< /Length 7 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
/E1 gs
/X1 Do
Q
endstream
endobj
7 0 obj
46
endobj
8 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 30.000000 30.000000 ]
/Resources 5 0 R
/Contents 6 0 R
/Parent 9 0 R
>>
endobj
9 0 obj
<< /Kids [ 8 0 R ]
/Count 1
/Type /Pages
>>
endobj
10 0 obj
<< /Pages 9 0 R
/Type /Catalog
>>
endobj
xref
0 11
0000000000 65535 f
0000000010 00000 n
0000001793 00000 n
0000001816 00000 n
0000003008 00000 n
0000003030 00000 n
0000003328 00000 n
0000003430 00000 n
0000003451 00000 n
0000003624 00000 n
0000003698 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 10 0 R
/Size 11
>>
startxref
3758
%%EOF

View File

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "clock_30.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,163 @@
%PDF-1.7
1 0 obj
<< /Type /XObject
/Length 2 0 R
/Group << /Type /Group
/S /Transparency
>>
/Subtype /Form
/Resources << >>
/BBox [ 0.000000 0.000000 30.000000 30.000000 ]
>>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 6.000000 6.000000 cm
1.000000 1.000000 1.000000 scn
9.000000 0.000000 m
13.970563 0.000000 18.000000 4.029437 18.000000 9.000000 c
18.000000 13.970563 13.970563 18.000000 9.000000 18.000000 c
4.029437 18.000000 0.000000 13.970563 0.000000 9.000000 c
0.000000 4.029437 4.029437 0.000000 9.000000 0.000000 c
h
9.830000 14.500002 m
9.830000 14.958399 9.458396 15.330002 9.000000 15.330002 c
8.541604 15.330002 8.170000 14.958399 8.170000 14.500002 c
8.170000 9.000048 l
8.170000 8.779921 8.257444 8.568808 8.413097 8.413153 c
11.913097 4.913105 l
12.237230 4.588968 12.762757 4.588964 13.086895 4.913097 c
13.411032 5.237230 13.411036 5.762757 13.086903 6.086895 c
9.830000 9.343842 l
9.830000 14.500002 l
h
f*
n
Q
endstream
endobj
2 0 obj
779
endobj
3 0 obj
<< /Type /XObject
/Length 4 0 R
/Group << /Type /Group
/S /Transparency
>>
/Subtype /Form
/Resources << >>
/BBox [ 0.000000 0.000000 30.000000 30.000000 ]
>>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 0.000000 0.000000 cm
0.000000 0.000000 0.000000 scn
0.000000 18.799999 m
0.000000 22.720367 0.000000 24.680552 0.762954 26.177933 c
1.434068 27.495068 2.504932 28.565931 3.822066 29.237045 c
5.319448 30.000000 7.279633 30.000000 11.200000 30.000000 c
18.799999 30.000000 l
22.720367 30.000000 24.680552 30.000000 26.177933 29.237045 c
27.495068 28.565931 28.565931 27.495068 29.237045 26.177933 c
30.000000 24.680552 30.000000 22.720367 30.000000 18.799999 c
30.000000 11.200001 l
30.000000 7.279633 30.000000 5.319448 29.237045 3.822067 c
28.565931 2.504932 27.495068 1.434069 26.177933 0.762955 c
24.680552 0.000000 22.720367 0.000000 18.799999 0.000000 c
11.200000 0.000000 l
7.279633 0.000000 5.319448 0.000000 3.822066 0.762955 c
2.504932 1.434069 1.434068 2.504932 0.762954 3.822067 c
0.000000 5.319448 0.000000 7.279633 0.000000 11.200001 c
0.000000 18.799999 l
h
f
n
Q
endstream
endobj
4 0 obj
944
endobj
5 0 obj
<< /XObject << /X1 1 0 R >>
/ExtGState << /E1 << /SMask << /Type /Mask
/G 3 0 R
/S /Alpha
>>
/Type /ExtGState
>> >>
>>
endobj
6 0 obj
<< /Length 7 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
/E1 gs
/X1 Do
Q
endstream
endobj
7 0 obj
46
endobj
8 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 30.000000 30.000000 ]
/Resources 5 0 R
/Contents 6 0 R
/Parent 9 0 R
>>
endobj
9 0 obj
<< /Kids [ 8 0 R ]
/Count 1
/Type /Pages
>>
endobj
10 0 obj
<< /Pages 9 0 R
/Type /Catalog
>>
endobj
xref
0 11
0000000000 65535 f
0000000010 00000 n
0000001037 00000 n
0000001059 00000 n
0000002251 00000 n
0000002273 00000 n
0000002571 00000 n
0000002673 00000 n
0000002694 00000 n
0000002867 00000 n
0000002941 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 10 0 R
/Size 11
>>
startxref
3001
%%EOF

View File

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "location_30.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,158 @@
%PDF-1.7
1 0 obj
<< /Type /XObject
/Length 2 0 R
/Group << /Type /Group
/S /Transparency
>>
/Subtype /Form
/Resources << >>
/BBox [ 0.000000 0.000000 30.000000 30.000000 ]
>>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 7.500000 5.000000 cm
1.000000 1.000000 1.000000 scn
7.500000 0.000002 m
9.767136 0.000002 15.000000 7.107865 15.000000 12.500000 c
15.000000 16.642136 11.642136 20.000000 7.500000 20.000000 c
3.357864 20.000000 0.000000 16.642136 0.000000 12.500000 c
0.000000 7.107865 5.232864 0.000002 7.500000 0.000002 c
h
7.500003 9.500000 m
9.156857 9.500000 10.500003 10.843146 10.500003 12.500000 c
10.500003 14.156855 9.156857 15.500000 7.500003 15.500000 c
5.843149 15.500000 4.500003 14.156855 4.500003 12.500000 c
4.500003 10.843146 5.843149 9.500000 7.500003 9.500000 c
h
f*
n
Q
endstream
endobj
2 0 obj
641
endobj
3 0 obj
<< /Type /XObject
/Length 4 0 R
/Group << /Type /Group
/S /Transparency
>>
/Subtype /Form
/Resources << >>
/BBox [ 0.000000 0.000000 30.000000 30.000000 ]
>>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 0.000000 0.000000 cm
0.000000 0.000000 0.000000 scn
0.000000 18.799999 m
0.000000 22.720367 0.000000 24.680552 0.762954 26.177933 c
1.434068 27.495068 2.504932 28.565931 3.822066 29.237045 c
5.319448 30.000000 7.279633 30.000000 11.200000 30.000000 c
18.799999 30.000000 l
22.720367 30.000000 24.680552 30.000000 26.177933 29.237045 c
27.495068 28.565931 28.565931 27.495068 29.237045 26.177933 c
30.000000 24.680552 30.000000 22.720367 30.000000 18.799999 c
30.000000 11.200001 l
30.000000 7.279633 30.000000 5.319448 29.237045 3.822067 c
28.565931 2.504932 27.495068 1.434069 26.177933 0.762955 c
24.680552 0.000000 22.720367 0.000000 18.799999 0.000000 c
11.200000 0.000000 l
7.279633 0.000000 5.319448 0.000000 3.822066 0.762955 c
2.504932 1.434069 1.434068 2.504932 0.762954 3.822067 c
0.000000 5.319448 0.000000 7.279633 0.000000 11.200001 c
0.000000 18.799999 l
h
f
n
Q
endstream
endobj
4 0 obj
944
endobj
5 0 obj
<< /XObject << /X1 1 0 R >>
/ExtGState << /E1 << /SMask << /Type /Mask
/G 3 0 R
/S /Alpha
>>
/Type /ExtGState
>> >>
>>
endobj
6 0 obj
<< /Length 7 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
/E1 gs
/X1 Do
Q
endstream
endobj
7 0 obj
46
endobj
8 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 30.000000 30.000000 ]
/Resources 5 0 R
/Contents 6 0 R
/Parent 9 0 R
>>
endobj
9 0 obj
<< /Kids [ 8 0 R ]
/Count 1
/Type /Pages
>>
endobj
10 0 obj
<< /Pages 9 0 R
/Type /Catalog
>>
endobj
xref
0 11
0000000000 65535 f
0000000010 00000 n
0000000899 00000 n
0000000921 00000 n
0000002113 00000 n
0000002135 00000 n
0000002433 00000 n
0000002535 00000 n
0000002556 00000 n
0000002729 00000 n
0000002803 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 10 0 R
/Size 11
>>
startxref
2863
%%EOF

View File

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "stories_30.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,158 @@
%PDF-1.7
1 0 obj
<< /Type /XObject
/Length 2 0 R
/Group << /Type /Group
/S /Transparency
>>
/Subtype /Form
/Resources << >>
/BBox [ 0.000000 0.000000 30.000000 30.000000 ]
>>
stream
/DeviceRGB CS
/DeviceRGB cs
q
-1.000000 -0.000000 -0.000000 1.000000 24.973145 8.079893 cm
1.000000 1.000000 1.000000 scn
10.631250 11.165106 m
10.631250 14.481874 l
10.631250 15.357313 11.676526 15.810160 12.315191 15.211411 c
19.853075 8.144644 l
20.274487 7.749570 20.274487 7.080643 19.853075 6.685569 c
12.315193 -0.381197 l
11.676527 -0.979946 10.631250 -0.527102 10.631250 0.348337 c
10.631250 3.665106 l
5.508641 3.665106 2.621962 1.429175 1.188047 -0.223289 c
0.842637 -0.621346 0.038047 -0.381472 0.089413 0.143045 c
0.452566 3.851353 2.233306 11.165106 10.631250 11.165106 c
h
f*
n
Q
endstream
endobj
2 0 obj
595
endobj
3 0 obj
<< /Type /XObject
/Length 4 0 R
/Group << /Type /Group
/S /Transparency
>>
/Subtype /Form
/Resources << >>
/BBox [ 0.000000 0.000000 30.000000 30.000000 ]
>>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 0.000000 0.000000 cm
0.000000 0.000000 0.000000 scn
0.000000 18.799999 m
0.000000 22.720367 0.000000 24.680552 0.762954 26.177933 c
1.434068 27.495068 2.504932 28.565931 3.822066 29.237045 c
5.319448 30.000000 7.279633 30.000000 11.200000 30.000000 c
18.799999 30.000000 l
22.720367 30.000000 24.680552 30.000000 26.177933 29.237045 c
27.495068 28.565931 28.565931 27.495068 29.237045 26.177933 c
30.000000 24.680552 30.000000 22.720367 30.000000 18.799999 c
30.000000 11.200001 l
30.000000 7.279633 30.000000 5.319448 29.237045 3.822067 c
28.565931 2.504932 27.495068 1.434069 26.177933 0.762955 c
24.680552 0.000000 22.720367 0.000000 18.799999 0.000000 c
11.200000 0.000000 l
7.279633 0.000000 5.319448 0.000000 3.822066 0.762955 c
2.504932 1.434069 1.434068 2.504932 0.762954 3.822067 c
0.000000 5.319448 0.000000 7.279633 0.000000 11.200001 c
0.000000 18.799999 l
h
f
n
Q
endstream
endobj
4 0 obj
944
endobj
5 0 obj
<< /XObject << /X1 1 0 R >>
/ExtGState << /E1 << /SMask << /Type /Mask
/G 3 0 R
/S /Alpha
>>
/Type /ExtGState
>> >>
>>
endobj
6 0 obj
<< /Length 7 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
/E1 gs
/X1 Do
Q
endstream
endobj
7 0 obj
46
endobj
8 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 30.000000 30.000000 ]
/Resources 5 0 R
/Contents 6 0 R
/Parent 9 0 R
>>
endobj
9 0 obj
<< /Kids [ 8 0 R ]
/Count 1
/Type /Pages
>>
endobj
10 0 obj
<< /Pages 9 0 R
/Type /Catalog
>>
endobj
xref
0 11
0000000000 65535 f
0000000010 00000 n
0000000853 00000 n
0000000875 00000 n
0000002067 00000 n
0000002089 00000 n
0000002387 00000 n
0000002489 00000 n
0000002510 00000 n
0000002683 00000 n
0000002757 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 10 0 R
/Size 11
>>
startxref
2817
%%EOF

View File

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "business.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,196 @@
%PDF-1.7
1 0 obj
<< /Type /XObject
/Length 2 0 R
/Group << /Type /Group
/S /Transparency
>>
/Subtype /Form
/Resources << >>
/BBox [ 0.000000 0.000000 30.000000 30.000000 ]
>>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 4.110800 5.913044 cm
1.000000 1.000000 1.000000 scn
4.498568 19.173912 m
3.994308 19.173912 3.585524 18.765129 3.585524 18.260868 c
3.585524 17.756609 3.994307 17.347824 4.498567 17.347824 c
17.281176 17.347824 l
17.785437 17.347824 18.194220 17.756609 18.194220 18.260868 c
18.194220 18.765129 17.785437 19.173912 17.281176 19.173912 c
4.498568 19.173912 l
h
3.730381 16.434782 m
2.984531 16.434782 2.270933 16.130634 1.754408 15.592587 c
0.442120 14.225620 l
0.115654 13.885551 -0.098236 13.421371 0.045616 12.972446 c
0.335989 12.066267 1.157089 11.413042 2.124654 11.413042 c
3.334878 11.413042 4.315958 12.435001 4.315958 13.695651 c
4.315958 12.435001 5.297039 11.413042 6.507263 11.413042 c
7.717486 11.413042 8.698567 12.435001 8.698567 13.695651 c
8.698567 12.435001 9.679648 11.413042 10.889872 11.413042 c
12.100096 11.413042 13.081176 12.435001 13.081176 13.695651 c
13.081176 12.435001 14.062256 11.413042 15.272481 11.413042 c
16.482704 11.413042 17.463785 12.435001 17.463785 13.695651 c
17.463785 12.435001 18.444864 11.413042 19.655088 11.413042 c
20.622656 11.413042 21.443754 12.066267 21.734129 12.972446 c
21.877979 13.421371 21.664089 13.885552 21.337624 14.225621 c
20.025335 15.592587 l
19.508810 16.130634 18.795212 16.434782 18.049362 16.434782 c
3.730381 16.434782 l
h
3.585524 10.043478 m
4.089784 10.043478 4.498567 9.634694 4.498567 9.130434 c
4.498567 6.370934 l
4.509398 5.876081 4.913934 5.478260 5.411387 5.478260 c
16.367910 5.478260 l
16.872171 5.478260 17.280952 5.887042 17.280952 6.391302 c
17.280952 8.217390 l
17.281176 8.237780 l
17.281176 9.130434 l
17.281176 9.634694 17.689960 10.043478 18.194220 10.043478 c
18.698479 10.043478 19.107264 9.634694 19.107264 9.130434 c
19.107264 6.391304 l
19.107264 1.826086 l
19.107264 0.817568 18.289698 0.000000 17.281178 0.000000 c
4.498567 0.000000 l
3.490047 0.000000 2.672480 0.817568 2.672480 1.826088 c
2.672480 6.355992 l
2.672257 6.391302 l
2.672257 8.217390 l
2.672480 8.237768 l
2.672480 9.130434 l
2.672480 9.634694 3.081264 10.043478 3.585524 10.043478 c
h
f*
n
Q
endstream
endobj
2 0 obj
2125
endobj
3 0 obj
<< /Type /XObject
/Length 4 0 R
/Group << /Type /Group
/S /Transparency
>>
/Subtype /Form
/Resources << >>
/BBox [ 0.000000 0.000000 30.000000 30.000000 ]
>>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 0.000000 0.000000 cm
0.000000 0.000000 0.000000 scn
0.000000 18.799999 m
0.000000 22.720367 0.000000 24.680552 0.762954 26.177933 c
1.434068 27.495068 2.504932 28.565931 3.822066 29.237045 c
5.319448 30.000000 7.279633 30.000000 11.200000 30.000000 c
18.799999 30.000000 l
22.720367 30.000000 24.680552 30.000000 26.177933 29.237045 c
27.495068 28.565931 28.565931 27.495068 29.237045 26.177933 c
30.000000 24.680552 30.000000 22.720367 30.000000 18.799999 c
30.000000 11.200001 l
30.000000 7.279633 30.000000 5.319448 29.237045 3.822067 c
28.565931 2.504932 27.495068 1.434069 26.177933 0.762955 c
24.680552 0.000000 22.720367 0.000000 18.799999 0.000000 c
11.200000 0.000000 l
7.279633 0.000000 5.319448 0.000000 3.822066 0.762955 c
2.504932 1.434069 1.434068 2.504932 0.762954 3.822067 c
0.000000 5.319448 0.000000 7.279633 0.000000 11.200001 c
0.000000 18.799999 l
h
f
n
Q
endstream
endobj
4 0 obj
944
endobj
5 0 obj
<< /XObject << /X1 1 0 R >>
/ExtGState << /E1 << /SMask << /Type /Mask
/G 3 0 R
/S /Alpha
>>
/Type /ExtGState
>> >>
>>
endobj
6 0 obj
<< /Length 7 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
/E1 gs
/X1 Do
Q
endstream
endobj
7 0 obj
46
endobj
8 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 30.000000 30.000000 ]
/Resources 5 0 R
/Contents 6 0 R
/Parent 9 0 R
>>
endobj
9 0 obj
<< /Kids [ 8 0 R ]
/Count 1
/Type /Pages
>>
endobj
10 0 obj
<< /Pages 9 0 R
/Type /Catalog
>>
endobj
xref
0 11
0000000000 65535 f
0000000010 00000 n
0000002383 00000 n
0000002406 00000 n
0000003598 00000 n
0000003620 00000 n
0000003918 00000 n
0000004020 00000 n
0000004041 00000 n
0000004214 00000 n
0000004288 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 10 0 R
/Size 11
>>
startxref
4348
%%EOF

View File

@ -1884,7 +1884,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
}
public func makeBusinessSetupScreen(context: AccountContext) -> ViewController {
return BusinessSetupScreen(context: context)
return PremiumIntroScreen(context: context, mode: .business, source: .settings, modal: false, forceDark: false)
}
public func makeChatbotSetupScreen(context: AccountContext) -> ViewController {
@ -1981,7 +1981,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
case .messageTags:
mappedSource = .messageTags
}
let controller = PremiumIntroScreen(context: context, modal: modal, source: mappedSource, forceDark: forceDark)
let controller = PremiumIntroScreen(context: context, source: mappedSource, modal: modal, forceDark: forceDark)
controller.wasDismissed = dismissed
return controller
}