This commit is contained in:
isaac 2026-04-28 00:44:58 +04:00
commit 49709e3231
194 changed files with 15216 additions and 4159 deletions

View file

@ -1635,7 +1635,6 @@ plist_fragment(
</array>
<key>UIAppFonts</key>
<array>
<string>SFCompactRounded-Semibold.otf</string>
<string>AremacFS-Regular.otf</string>
<string>AremacFS-Semibold.otf</string>
</array>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 712 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 455 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 788 B

View file

@ -67,6 +67,8 @@ public final class ChatMessageItemAssociatedData: Equatable {
public let isSuspiciousPeer: Bool
public let showTextAsPlaceholder: Bool
public let accountCountry: String?
public let isParticipant: Bool
public let invitedOn: Int32?
public init(
automaticDownloadPeerType: MediaAutoDownloadPeerType,
@ -104,7 +106,9 @@ public final class ChatMessageItemAssociatedData: Equatable {
showSensitiveContent: Bool = false,
isSuspiciousPeer: Bool = false,
showTextAsPlaceholder: Bool = false,
accountCountry: String? = nil
accountCountry: String? = nil,
isParticipant: Bool = false,
invitedOn: Int32? = nil
) {
self.automaticDownloadPeerType = automaticDownloadPeerType
self.automaticDownloadPeerId = automaticDownloadPeerId
@ -142,6 +146,8 @@ public final class ChatMessageItemAssociatedData: Equatable {
self.isSuspiciousPeer = isSuspiciousPeer
self.showTextAsPlaceholder = showTextAsPlaceholder
self.accountCountry = accountCountry
self.isParticipant = isParticipant
self.invitedOn = invitedOn
}
public static func == (lhs: ChatMessageItemAssociatedData, rhs: ChatMessageItemAssociatedData) -> Bool {
@ -241,6 +247,12 @@ public final class ChatMessageItemAssociatedData: Equatable {
if lhs.accountCountry != rhs.accountCountry {
return false
}
if lhs.isParticipant != rhs.isParticipant {
return false
}
if lhs.invitedOn != rhs.invitedOn {
return false
}
return true
}
}

File diff suppressed because it is too large Load diff

View file

@ -343,6 +343,8 @@ private func trimStart(_ input: RichText) -> RichText {
}
case .image:
break
case .formula:
break
}
return text
}
@ -385,6 +387,8 @@ private func trimEnd(_ input: RichText) -> RichText {
}
case .image:
break
case .formula:
break
}
return text
}
@ -428,6 +432,8 @@ private func trim(_ input: RichText) -> RichText {
}
case .image:
break
case .formula:
break
}
return text
}
@ -470,6 +476,8 @@ private func addNewLine(_ input: RichText) -> RichText {
}
case .image:
break
case let .formula(latex):
text = .concat([.formula(latex: latex), .plain("\n")])
}
return text
}

View file

@ -331,7 +331,7 @@ func chatContextMenuItems(context: AccountContext, peerId: PeerId, promoInfo: Ch
}
return filters
}).startStandalone()
chatListController?.present(UndoOverlayController( presentationData: presentationData, content: .chatAddedToFolder(context: context, chatTitle: peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), folderTitle: title.rawAttributedString), elevatedLayout: false, animateInAsReplacement: true, action: { _ in
chatListController?.present(UndoOverlayController(presentationData: presentationData, content: .chatAddedToFolder(context: context, chatTitle: peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), folderTitle: title.rawAttributedString), elevatedLayout: false, animateInAsReplacement: true, action: { _ in
return false
}), in: .current)
})
@ -1023,7 +1023,7 @@ public func savedMessagesPeerMenuItems(context: AccountContext, threadId: Int64,
}
private func openCustomMute(context: AccountContext, peerId: EnginePeer.Id, threadId: Int64, baseController: ViewController) {
let controller = ChatTimerScreen(context: context, updatedPresentationData: nil, style: .default, mode: .mute, currentTime: nil, dismissByTapOutside: true, completion: { [weak baseController] value in
let controller = ChatTimerScreen(context: context, updatedPresentationData: nil, style: .default, mode: .mute, currentTime: nil, completion: { [weak baseController] value in
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
if value <= 0 {

View file

@ -1901,12 +1901,12 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
chatController.canReadHistory.set(false)
source = .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node, navigationController: strongSelf.navigationController as? NavigationController))
let contextController = makeContextController(presentationData: strongSelf.presentationData, source: source, items: chatForumTopicMenuItems(context: strongSelf.context, peerId: peer.peerId, threadId: threadId, isPinned: nil, isClosed: nil, chatListController: strongSelf, joined: joined, canSelect: false) |> map { ContextController.Items(content: .list($0)) }, gesture: gesture)
let contextController = makeContextController(context: strongSelf.context, presentationData: strongSelf.presentationData, source: source, items: chatForumTopicMenuItems(context: strongSelf.context, peerId: peer.peerId, threadId: threadId, isPinned: nil, isClosed: nil, chatListController: strongSelf, joined: joined, canSelect: false) |> map { ContextController.Items(content: .list($0)) }, gesture: gesture)
strongSelf.presentInGlobalOverlay(contextController)
} else {
let chatListController = ChatListControllerImpl(context: strongSelf.context, location: .forum(peerId: channel.id), controlsHistoryPreload: false, hideNetworkActivityStatus: true, previewing: true, enableDebugActions: false)
chatListController.navigationPresentation = .master
let contextController = makeContextController(presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatListController, sourceNode: node, navigationController: strongSelf.navigationController as? NavigationController)), items: chatContextMenuItems(context: strongSelf.context, peerId: peer.peerId, promoInfo: promoInfo, source: .chatList(filter: strongSelf.chatListDisplayNode.mainContainerNode.currentItemNode.chatListFilter), chatListController: strongSelf, joined: joined) |> map { ContextController.Items(content: .list($0)) }, gesture: gesture)
let contextController = makeContextController(context: strongSelf.context, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatListController, sourceNode: node, navigationController: strongSelf.navigationController as? NavigationController)), items: chatContextMenuItems(context: strongSelf.context, peerId: peer.peerId, promoInfo: promoInfo, source: .chatList(filter: strongSelf.chatListDisplayNode.mainContainerNode.currentItemNode.chatListFilter), chatListController: strongSelf, joined: joined) |> map { ContextController.Items(content: .list($0)) }, gesture: gesture)
strongSelf.presentInGlobalOverlay(contextController)
}
} else if let peer = peer.peer, peer.id == strongSelf.context.account.peerId, peerData.displayAsTopicList {
@ -1918,7 +1918,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
source = .controller(ContextControllerContentSourceImpl(controller: peerInfoController, sourceNode: node, navigationController: strongSelf.navigationController as? NavigationController))
}
let contextController = makeContextController(presentationData: strongSelf.presentationData, source: source, items: chatContextMenuItems(context: strongSelf.context, peerId: peer.id, promoInfo: promoInfo, source: .chatList(filter: strongSelf.chatListDisplayNode.mainContainerNode.currentItemNode.chatListFilter), chatListController: strongSelf, joined: joined) |> map { ContextController.Items(content: .list($0)) }, gesture: gesture)
let contextController = makeContextController(context: strongSelf.context, presentationData: strongSelf.presentationData, source: source, items: chatContextMenuItems(context: strongSelf.context, peerId: peer.id, promoInfo: promoInfo, source: .chatList(filter: strongSelf.chatListDisplayNode.mainContainerNode.currentItemNode.chatListFilter), chatListController: strongSelf, joined: joined) |> map { ContextController.Items(content: .list($0)) }, gesture: gesture)
strongSelf.presentInGlobalOverlay(contextController)
}
} else {
@ -1970,7 +1970,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
chatController.canReadHistory.set(false)
source = .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node, navigationController: strongSelf.navigationController as? NavigationController))
let contextController = makeContextController(presentationData: strongSelf.presentationData, source: source, items: chatForumTopicMenuItems(context: strongSelf.context, peerId: peer.peerId, threadId: threadId, isPinned: isPinned, isClosed: threadInfo?.isClosed, chatListController: strongSelf, joined: joined, canSelect: true) |> map { ContextController.Items(content: .list($0)) }, gesture: gesture)
let contextController = makeContextController(context: strongSelf.context, presentationData: strongSelf.presentationData, source: source, items: chatForumTopicMenuItems(context: strongSelf.context, peerId: peer.peerId, threadId: threadId, isPinned: isPinned, isClosed: threadInfo?.isClosed, chatListController: strongSelf, joined: joined, canSelect: true) |> map { ContextController.Items(content: .list($0)) }, gesture: gesture)
strongSelf.presentInGlobalOverlay(contextController)
}
}
@ -2005,7 +2005,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
if case let .channel(channel) = peer, channel.isForumOrMonoForum {
let chatListController = ChatListControllerImpl(context: strongSelf.context, location: .forum(peerId: channel.id), controlsHistoryPreload: false, hideNetworkActivityStatus: true, previewing: true, enableDebugActions: false)
chatListController.navigationPresentation = .master
let contextController = makeContextController(presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatListController, sourceNode: node, navigationController: strongSelf.navigationController as? NavigationController)), items: chatContextMenuItems(context: strongSelf.context, peerId: peer.id, promoInfo: nil, source: .search(source), chatListController: strongSelf, joined: false) |> map { ContextController.Items(content: .list($0)) }, gesture: gesture)
let contextController = makeContextController(context: strongSelf.context, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatListController, sourceNode: node, navigationController: strongSelf.navigationController as? NavigationController)), items: chatContextMenuItems(context: strongSelf.context, peerId: peer.id, promoInfo: nil, source: .search(source), chatListController: strongSelf, joined: false) |> map { ContextController.Items(content: .list($0)) }, gesture: gesture)
strongSelf.presentInGlobalOverlay(contextController)
} else {
let contextContentSource: ContextContentSource

View file

@ -225,15 +225,13 @@ public func chatListItemStrings(strings: PresentationStrings, nameDisplayOrder:
break inner
case let .Audio(isVoice, _, title, performer, _):
if !message.text.isEmpty {
messageText = "🎤 \(messageText)"
processed = true
} else if isVoice {
if message.text.isEmpty {
messageText = strings.Message_Audio
} else {
if enableMediaEmoji {
messageText = "🎤 \(messageText)"
}
processed = true
} else if isVoice {
messageText = strings.Message_Audio
processed = true
break inner
} else {
let descriptionString: String

View file

@ -224,7 +224,7 @@ public struct Font {
} else {
let font: UIFont
switch design {
case .regular:
case .regular, .round:
if traits.contains(.italic) {
if let descriptor = UIFont.systemFont(ofSize: size, weight: weight.weight).fontDescriptor.withSymbolicTraits([.traitItalic]) {
font = UIFont(descriptor: descriptor, size: size)
@ -254,8 +254,6 @@ public struct Font {
} else {
font = UIFont(name: "Menlo", size: size - 1.0) ?? UIFont.systemFont(ofSize: size)
}
case .round:
font = UIFont(name: ".SFCompactRounded-Semibold", size: size) ?? UIFont.systemFont(ofSize: size)
case .camera:
func encodeText(string: String, key: Int16) -> String {
let nsString = string as NSString

View file

@ -29,6 +29,7 @@ swift_library(
"//submodules/UndoUI:UndoUI",
"//submodules/TranslateUI:TranslateUI",
"//submodules/Tuples:Tuples",
"//third-party/SwiftMath:SwiftMath",
],
visibility = [
"//visibility:public",

View file

@ -0,0 +1,185 @@
import Foundation
import UIKit
import TelegramCore
import AsyncDisplayKit
import Display
import TelegramPresentationData
import TelegramUIPreferences
import AccountContext
import ContextUI
final class InstantPageFormulaNode: ASImageNode, InstantPageNode {
let attachment: InstantPageMathAttachment
init(attachment: InstantPageMathAttachment) {
self.attachment = attachment
super.init()
self.isUserInteractionEnabled = false
self.displaysAsynchronously = false
self.image = attachment.rendered.image
}
func updateIsVisible(_ isVisible: Bool) {
}
func transitionNode(media: InstantPageMedia) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
return nil
}
func updateHiddenMedia(media: InstantPageMedia?) {
}
func update(strings: PresentationStrings, theme: InstantPageTheme) {
}
func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition) {
}
}
final class InstantPageTextFormulaItem: InstantPageItem {
var frame: CGRect
let attachment: InstantPageMathAttachment
let wantsNode: Bool = true
let separatesTiles: Bool = false
let medias: [InstantPageMedia] = []
init(frame: CGRect, attachment: InstantPageMathAttachment) {
self.frame = frame
self.attachment = attachment
}
func matchesAnchor(_ anchor: String) -> Bool {
return false
}
func drawInTile(context: CGContext) {
}
func node(context: AccountContext, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, theme: InstantPageTheme, sourceLocation: InstantPageSourceLocation, openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void, activatePinchPreview: ((PinchSourceContainerNode) -> Void)?, pinchPreviewFinished: ((InstantPageNode) -> Void)?, openPeer: @escaping (EnginePeer) -> Void, openUrl: @escaping (InstantPageUrlItem) -> Void, updateWebEmbedHeight: @escaping (CGFloat) -> Void, updateDetailsExpanded: @escaping (Bool) -> Void, currentExpandedDetails: [Int : Bool]?, getPreloadedResource: @escaping (String) -> Data?) -> InstantPageNode? {
return InstantPageFormulaNode(attachment: self.attachment)
}
func matchesNode(_ node: InstantPageNode) -> Bool {
guard let node = node as? InstantPageFormulaNode else {
return false
}
return self.attachment.isEqual(to: node.attachment)
}
func linkSelectionRects(at point: CGPoint) -> [CGRect] {
return []
}
func distanceThresholdGroup() -> Int? {
return nil
}
func distanceThresholdWithGroupCount(_ count: Int) -> CGFloat {
return 0.0
}
}
final class InstantPageFormulaItem: InstantPageItem {
var frame: CGRect
let attachment: InstantPageMathAttachment
let wantsNode: Bool = true
let separatesTiles: Bool = false
let medias: [InstantPageMedia] = []
init(frame: CGRect, attachment: InstantPageMathAttachment) {
self.frame = frame
self.attachment = attachment
}
func matchesAnchor(_ anchor: String) -> Bool {
return false
}
func drawInTile(context: CGContext) {
}
func node(context: AccountContext, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, theme: InstantPageTheme, sourceLocation: InstantPageSourceLocation, openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void, activatePinchPreview: ((PinchSourceContainerNode) -> Void)?, pinchPreviewFinished: ((InstantPageNode) -> Void)?, openPeer: @escaping (EnginePeer) -> Void, openUrl: @escaping (InstantPageUrlItem) -> Void, updateWebEmbedHeight: @escaping (CGFloat) -> Void, updateDetailsExpanded: @escaping (Bool) -> Void, currentExpandedDetails: [Int : Bool]?, getPreloadedResource: @escaping (String) -> Data?) -> InstantPageNode? {
return InstantPageFormulaNode(attachment: self.attachment)
}
func matchesNode(_ node: InstantPageNode) -> Bool {
guard let node = node as? InstantPageFormulaNode else {
return false
}
return self.attachment.isEqual(to: node.attachment)
}
func linkSelectionRects(at point: CGPoint) -> [CGRect] {
return []
}
func distanceThresholdGroup() -> Int? {
return nil
}
func distanceThresholdWithGroupCount(_ count: Int) -> CGFloat {
return 0.0
}
}
final class InstantPageScrollableFormulaItem: InstantPageScrollableItem {
var frame: CGRect
let attachment: InstantPageMathAttachment
let totalWidth: CGFloat
let horizontalInset: CGFloat
let medias: [InstantPageMedia] = []
let wantsNode: Bool = true
let separatesTiles: Bool = false
let isRTL: Bool = false
init(frame: CGRect, attachment: InstantPageMathAttachment, totalWidth: CGFloat, horizontalInset: CGFloat) {
self.frame = frame
self.attachment = attachment
self.totalWidth = totalWidth
self.horizontalInset = horizontalInset
}
var contentSize: CGSize {
return CGSize(width: self.totalWidth, height: self.frame.height)
}
func matchesAnchor(_ anchor: String) -> Bool {
return false
}
func drawInTile(context: CGContext) {
}
func node(context: AccountContext, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, theme: InstantPageTheme, sourceLocation: InstantPageSourceLocation, openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void, activatePinchPreview: ((PinchSourceContainerNode) -> Void)?, pinchPreviewFinished: ((InstantPageNode) -> Void)?, openPeer: @escaping (EnginePeer) -> Void, openUrl: @escaping (InstantPageUrlItem) -> Void, updateWebEmbedHeight: @escaping (CGFloat) -> Void, updateDetailsExpanded: @escaping (Bool) -> Void, currentExpandedDetails: [Int : Bool]?, getPreloadedResource: @escaping (String) -> Data?) -> InstantPageNode? {
let node = InstantPageFormulaNode(attachment: self.attachment)
node.frame = CGRect(origin: .zero, size: self.attachment.rendered.size)
return InstantPageScrollableNode(item: self, additionalNodes: [node])
}
func matchesNode(_ node: InstantPageNode) -> Bool {
if let node = node as? InstantPageScrollableNode {
return node.item === self
}
return false
}
func linkSelectionRects(at point: CGPoint) -> [CGRect] {
return []
}
func distanceThresholdGroup() -> Int? {
return nil
}
func distanceThresholdWithGroupCount(_ count: Int) -> CGFloat {
return 0.0
}
func textItemAtLocation(_ location: CGPoint) -> (InstantPageTextItem, CGPoint)? {
return nil
}
}

View file

@ -291,6 +291,37 @@ public func layoutInstantPageBlock(webpage: TelegramMediaWebpage, userLocation:
setupStyleStack(styleStack, theme: theme, attributes: theme.headingTextAttributes(level: level, link: false))
let (_, items, contentSize) = layoutTextItemWithString(attributedStringForRichText(text, styleStack: styleStack), boundingWidth: boundingWidth - horizontalInset * 2.0, offset: CGPoint(x: horizontalInset, y: 0.0), media: media, webpage: webpage)
return InstantPageLayout(origin: CGPoint(), contentSize: contentSize, items: items)
case let .formula(latex):
let styleStack = InstantPageTextStyleStack()
setupStyleStack(styleStack, theme: theme, category: .paragraph, link: false)
let attributes = styleStack.textAttributes()
let textColor = (attributes[NSAttributedString.Key.foregroundColor] as? UIColor) ?? theme.textCategories.paragraph.color
let fontSize = (attributes[NSAttributedString.Key.font] as? UIFont)?.pointSize ?? theme.textCategories.paragraph.font.size
guard let attachment = instantPageMathAttachment(latex: latex, fontSize: fontSize, textColor: textColor, mode: .block) else {
let (_, items, contentSize) = layoutTextItemWithString(attributedStringForRichText(.plain(latex), styleStack: styleStack), boundingWidth: boundingWidth - horizontalInset * 2.0, offset: CGPoint(x: horizontalInset, y: 0.0), media: media, webpage: webpage)
return InstantPageLayout(origin: CGPoint(), contentSize: contentSize, items: items)
}
let availableWidth = boundingWidth - horizontalInset * 2.0
if attachment.rendered.size.width > availableWidth {
let scrollableItem = InstantPageScrollableFormulaItem(
frame: CGRect(origin: .zero, size: CGSize(width: boundingWidth, height: attachment.rendered.size.height)),
attachment: attachment,
totalWidth: attachment.rendered.size.width,
horizontalInset: horizontalInset
)
return InstantPageLayout(origin: CGPoint(), contentSize: scrollableItem.frame.size, items: [scrollableItem])
} else {
let item = InstantPageFormulaItem(
frame: CGRect(
origin: CGPoint(x: horizontalInset + floor((availableWidth - attachment.rendered.size.width) / 2.0), y: 0.0),
size: attachment.rendered.size
),
attachment: attachment
)
return InstantPageLayout(origin: CGPoint(), contentSize: CGSize(width: boundingWidth, height: attachment.rendered.size.height), items: [item])
}
case let .paragraph(text):
let styleStack = InstantPageTextStyleStack()
setupStyleStack(styleStack, theme: theme, category: .paragraph, link: false)

View file

@ -27,20 +27,38 @@ func spacingBetweenBlocks(upper: InstantPageBlock?, lower: InstantPageBlock?) ->
return 31.0
case (.preformatted, .paragraph):
return 19.0
case (.formula, .paragraph):
return 19.0
case (.paragraph, .paragraph):
return 25.0
case (_, .paragraph):
return 20.0
case (.title, .formula), (.authorDate, .formula):
return 34.0
case (.header, .formula), (.subheader, .formula), (.heading, .formula):
return 25.0
case (.list, .formula):
return 31.0
case (.preformatted, .formula):
return 19.0
case (.paragraph, .formula):
return 19.0
case (_, .formula):
return 20.0
case (.title, .list), (.authorDate, .list):
return 34.0
case (.header, .list), (.subheader, .list), (.heading, .list):
return 31.0
case (.preformatted, .list):
return 19.0
case (.formula, .list):
return 25.0
case (_, .list):
return 25.0
case (.paragraph, .preformatted):
return 19.0
case (.formula, .preformatted):
return 19.0
case (_, .preformatted):
return 20.0
case (_, .header), (_, .subheader), (_, .heading):

View file

@ -0,0 +1,79 @@
import Foundation
import UIKit
import SwiftMath
enum InstantPageMathMode {
case inline
case block
}
struct InstantPageMathRenderResult {
let image: UIImage
let size: CGSize
let width: CGFloat
let ascent: CGFloat
let descent: CGFloat
}
final class InstantPageMathAttachment: NSObject {
let latex: String
let fontSize: CGFloat
let textColor: UIColor
let mode: InstantPageMathMode
let rendered: InstantPageMathRenderResult
init(latex: String, fontSize: CGFloat, textColor: UIColor, mode: InstantPageMathMode, rendered: InstantPageMathRenderResult) {
self.latex = latex
self.fontSize = fontSize
self.textColor = textColor
self.mode = mode
self.rendered = rendered
}
func isEqual(to other: InstantPageMathAttachment) -> Bool {
return self.latex == other.latex
&& self.fontSize == other.fontSize
&& self.mode == other.mode
&& self.textColor.isEqual(other.textColor)
&& self.rendered.size == other.rendered.size
&& self.rendered.ascent == other.rendered.ascent
&& self.rendered.descent == other.rendered.descent
}
}
func instantPageMathAttachment(latex: String, fontSize: CGFloat, textColor: UIColor, mode: InstantPageMathMode) -> InstantPageMathAttachment? {
let effectiveFontSize: CGFloat
let multiplier: CGFloat = 1.12
switch mode {
case .inline:
effectiveFontSize = fontSize * multiplier
case .block:
effectiveFontSize = fontSize * multiplier
}
guard let rendered = instantPageRenderMath(latex: latex, fontSize: effectiveFontSize, textColor: textColor, mode: mode) else {
return nil
}
return InstantPageMathAttachment(latex: latex, fontSize: effectiveFontSize, textColor: textColor, mode: mode, rendered: rendered)
}
private func instantPageRenderMath(latex: String, fontSize: CGFloat, textColor: UIColor, mode: InstantPageMathMode) -> InstantPageMathRenderResult? {
let renderMode: MTMathUILabelMode
switch mode {
case .inline:
renderMode = .text
case .block:
renderMode = .display
}
guard let rendered = MTMathRenderer.render(latex: latex, fontSize: fontSize, textColor: textColor, mode: renderMode) else {
return nil
}
return InstantPageMathRenderResult(
image: rendered.image,
size: rendered.size,
width: rendered.width,
ascent: rendered.ascent,
descent: rendered.descent
)
}

View file

@ -26,6 +26,7 @@ public final class InstantPageUrlItem: Equatable {
struct InstantPageTextMarkedItem {
let frame: CGRect
let color: UIColor
let range: NSRange
}
struct InstantPageTextStrikethroughItem {
@ -38,6 +39,12 @@ struct InstantPageTextImageItem {
let id: EngineMedia.Id
}
struct InstantPageTextFormulaRun {
let frame: CGRect
let range: NSRange
let attachment: InstantPageMathAttachment
}
public struct InstantPageTextAnchorItem {
public let name: String
public let anchorText: NSAttributedString?
@ -63,16 +70,18 @@ public final class InstantPageTextLine {
let strikethroughItems: [InstantPageTextStrikethroughItem]
let markedItems: [InstantPageTextMarkedItem]
let imageItems: [InstantPageTextImageItem]
let formulaItems: [InstantPageTextFormulaRun]
public let anchorItems: [InstantPageTextAnchorItem]
let isRTL: Bool
init(line: CTLine, range: NSRange, frame: CGRect, strikethroughItems: [InstantPageTextStrikethroughItem], markedItems: [InstantPageTextMarkedItem], imageItems: [InstantPageTextImageItem], anchorItems: [InstantPageTextAnchorItem], isRTL: Bool) {
init(line: CTLine, range: NSRange, frame: CGRect, strikethroughItems: [InstantPageTextStrikethroughItem], markedItems: [InstantPageTextMarkedItem], imageItems: [InstantPageTextImageItem], formulaItems: [InstantPageTextFormulaRun], anchorItems: [InstantPageTextAnchorItem], isRTL: Bool) {
self.line = line
self.range = range
self.frame = frame
self.strikethroughItems = strikethroughItems
self.markedItems = markedItems
self.imageItems = imageItems
self.formulaItems = formulaItems
self.anchorItems = anchorItems
self.isRTL = isRTL
}
@ -88,6 +97,75 @@ private func frameForLine(_ line: InstantPageTextLine, boundingWidth: CGFloat, a
return lineFrame
}
private func expandedFrameForLine(_ line: InstantPageTextLine, boundingWidth: CGFloat, alignment: NSTextAlignment) -> CGRect {
var lineFrame = line.frame
for imageItem in line.imageItems {
if imageItem.frame.minY < lineFrame.minY {
let delta = lineFrame.minY - imageItem.frame.minY - 2.0
lineFrame = CGRect(x: lineFrame.minX, y: lineFrame.minY - delta, width: lineFrame.width, height: lineFrame.height + delta)
}
if imageItem.frame.maxY > lineFrame.maxY {
let delta = imageItem.frame.maxY - lineFrame.maxY - 2.0
lineFrame = CGRect(x: lineFrame.minX, y: lineFrame.minY, width: lineFrame.width, height: lineFrame.height + delta)
}
}
for formulaItem in line.formulaItems {
if formulaItem.frame.minY < lineFrame.minY {
let delta = lineFrame.minY - formulaItem.frame.minY - 2.0
lineFrame = CGRect(x: lineFrame.minX, y: lineFrame.minY - delta, width: lineFrame.width, height: lineFrame.height + delta)
}
if formulaItem.frame.maxY > lineFrame.maxY {
let delta = formulaItem.frame.maxY - lineFrame.maxY - 2.0
lineFrame = CGRect(x: lineFrame.minX, y: lineFrame.minY, width: lineFrame.width, height: lineFrame.height + delta)
}
}
lineFrame = lineFrame.insetBy(dx: 0.0, dy: -4.0)
if alignment == .center {
lineFrame.origin.x = floor((boundingWidth - lineFrame.size.width) / 2.0)
} else if alignment == .right || (alignment == .natural && line.isRTL) {
lineFrame.origin.x = boundingWidth - lineFrame.size.width
}
return lineFrame
}
private func alignedAttachmentFrame(_ frame: CGRect, line: InstantPageTextLine, boundingWidth: CGFloat, alignment: NSTextAlignment) -> CGRect {
let lineFrame = frameForLine(line, boundingWidth: boundingWidth, alignment: alignment)
return frame.offsetBy(dx: lineFrame.minX - line.frame.minX, dy: 0.0)
}
private func localAttachmentBoundsForRange(_ range: NSRange, imageItems: [InstantPageTextImageItem], formulaItems: [InstantPageTextFormulaRun]) -> CGRect? {
var result: CGRect?
for imageItem in imageItems {
if NSIntersectionRange(range, imageItem.range).length != 0 {
if let current = result {
result = current.union(imageItem.frame)
} else {
result = imageItem.frame
}
}
}
for formulaItem in formulaItems {
if NSIntersectionRange(range, formulaItem.range).length != 0 {
if let current = result {
result = current.union(formulaItem.frame)
} else {
result = formulaItem.frame
}
}
}
return result
}
private func attachmentBoundsForRange(_ range: NSRange, line: InstantPageTextLine, boundingWidth: CGFloat, alignment: NSTextAlignment) -> CGRect? {
guard let localBounds = localAttachmentBoundsForRange(range, imageItems: line.imageItems, formulaItems: line.formulaItems) else {
return nil
}
return alignedAttachmentFrame(localBounds, line: line, boundingWidth: boundingWidth, alignment: alignment)
}
public final class InstantPageTextItem: InstantPageItem {
let attributedString: NSAttributedString
public let lines: [InstantPageTextLine]
@ -197,7 +275,7 @@ public final class InstantPageTextItem: InstantPageItem {
for i in 0 ..< self.lines.count {
let line = self.lines[i]
let lineFrame = frameForLine(line, boundingWidth: boundsWidth, alignment: self.alignment)
let lineFrame = expandedFrameForLine(line, boundingWidth: boundsWidth, alignment: self.alignment)
if lineFrame.insetBy(dx: -5.0, dy: -5.0).contains(transformedPoint) {
var index = CTLineGetStringIndexForPosition(line.line, CGPoint(x: transformedPoint.x - lineFrame.minX, y: transformedPoint.y - lineFrame.minY))
if index == self.attributedString.length {
@ -238,8 +316,20 @@ public final class InstantPageTextItem: InstantPageItem {
}
let lineFrame = frameForLine(line, boundingWidth: boundsWidth, alignment: self.alignment)
let width = abs(rightOffset - leftOffset)
var rect: CGRect?
if width > 1.0 {
rects.append(CGRect(origin: CGPoint(x: lineFrame.minX + (leftOffset < rightOffset ? leftOffset : rightOffset), y: lineFrame.minY), size: CGSize(width: width, height: lineFrame.size.height)))
rect = CGRect(origin: CGPoint(x: lineFrame.minX + (leftOffset < rightOffset ? leftOffset : rightOffset), y: lineFrame.minY), size: CGSize(width: width, height: lineFrame.size.height))
}
if let attachmentBounds = attachmentBoundsForRange(lineRange, line: line, boundingWidth: boundsWidth, alignment: self.alignment) {
if rect != nil {
rect = rect!.union(attachmentBounds)
} else {
rect = attachmentBounds
}
}
if let rect, rect.width > 1.0 {
rects.append(rect)
}
}
}
@ -304,25 +394,7 @@ public final class InstantPageTextItem: InstantPageItem {
}
}
var lineFrame = line.frame
for imageItem in line.imageItems {
if imageItem.frame.minY < lineFrame.minY {
let delta = lineFrame.minY - imageItem.frame.minY - 2.0
lineFrame = CGRect(x: lineFrame.minX, y: lineFrame.minY - delta, width: lineFrame.width, height: lineFrame.height + delta)
}
if imageItem.frame.maxY > lineFrame.maxY {
let delta = imageItem.frame.maxY - lineFrame.maxY - 2.0
lineFrame = CGRect(x: lineFrame.minX, y: lineFrame.minY, width: lineFrame.width, height: lineFrame.height + delta)
}
}
lineFrame = lineFrame.insetBy(dx: 0.0, dy: -4.0)
if self.alignment == .center {
lineFrame.origin.x = floor((boundsWidth - lineFrame.size.width) / 2.0)
} else if self.alignment == .right {
lineFrame.origin.x = boundsWidth - lineFrame.size.width
} else if self.alignment == .natural && self.rtlLineIndices.contains(i) {
lineFrame.origin.x = boundsWidth - lineFrame.size.width
}
let lineFrame = expandedFrameForLine(line, boundingWidth: boundsWidth, alignment: self.alignment)
let width = max(0.0, abs(rightOffset - leftOffset))
@ -368,25 +440,7 @@ public final class InstantPageTextItem: InstantPageItem {
for i in 0 ..< self.lines.count {
let line = self.lines[i]
var lineFrame = line.frame
for imageItem in line.imageItems {
if imageItem.frame.minY < lineFrame.minY {
let delta = lineFrame.minY - imageItem.frame.minY - 2.0
lineFrame = CGRect(x: lineFrame.minX, y: lineFrame.minY - delta, width: lineFrame.width, height: lineFrame.height + delta)
}
if imageItem.frame.maxY > lineFrame.maxY {
let delta = imageItem.frame.maxY - lineFrame.maxY - 2.0
lineFrame = CGRect(x: lineFrame.minX, y: lineFrame.minY, width: lineFrame.width, height: lineFrame.height + delta)
}
}
lineFrame = lineFrame.insetBy(dx: 0.0, dy: -4.0)
if self.alignment == .center {
lineFrame.origin.x = floor((boundsWidth - lineFrame.size.width) / 2.0)
} else if self.alignment == .right {
lineFrame.origin.x = boundsWidth - lineFrame.size.width
} else if self.alignment == .natural && self.rtlLineIndices.contains(i) {
lineFrame.origin.x = boundsWidth - lineFrame.size.width
}
let lineFrame = expandedFrameForLine(line, boundingWidth: boundsWidth, alignment: self.alignment)
if lineFrame.minX < topLeft.x {
topLeft = CGPoint(x: lineFrame.minX, y: topLeft.y)
@ -633,6 +687,43 @@ func attributedStringForRichText(_ text: RichText, styleStack: InstantPageTextSt
let mutableAttributedString = attributedStringForRichText(.plain(" "), styleStack: styleStack, url: url).mutableCopy() as! NSMutableAttributedString
mutableAttributedString.addAttributes(attrDictionaryDelegate, range: NSMakeRange(0, mutableAttributedString.length))
return mutableAttributedString
case let .formula(latex):
let attributes = styleStack.textAttributes()
let textColor = (attributes[NSAttributedString.Key.foregroundColor] as? UIColor) ?? UIColor.black
let fontSize = (attributes[NSAttributedString.Key.font] as? UIFont)?.pointSize ?? 16.0
guard let attachment = instantPageMathAttachment(latex: latex, fontSize: fontSize, textColor: textColor, mode: .inline) else {
var fallbackAttributes = attributes
if let url = url {
fallbackAttributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)] = url
}
return NSAttributedString(string: latex, attributes: fallbackAttributes)
}
struct RunStruct {
let ascent: CGFloat
let descent: CGFloat
let width: CGFloat
}
let extentBuffer = UnsafeMutablePointer<RunStruct>.allocate(capacity: 1)
extentBuffer.initialize(to: RunStruct(ascent: attachment.rendered.ascent, descent: attachment.rendered.descent, width: attachment.rendered.size.width))
var callbacks = CTRunDelegateCallbacks(version: kCTRunDelegateVersion1, dealloc: { _ in
}, getAscent: { pointer -> CGFloat in
let data = pointer.assumingMemoryBound(to: RunStruct.self)
return data.pointee.ascent
}, getDescent: { pointer -> CGFloat in
let data = pointer.assumingMemoryBound(to: RunStruct.self)
return data.pointee.descent
}, getWidth: { pointer -> CGFloat in
let data = pointer.assumingMemoryBound(to: RunStruct.self)
return data.pointee.width
})
let delegate = CTRunDelegateCreate(&callbacks, extentBuffer)
let mutableAttributedString = attributedStringForRichText(.plain(" "), styleStack: styleStack, url: url).mutableCopy() as! NSMutableAttributedString
mutableAttributedString.addAttributes([
kCTRunDelegateAttributeName as NSAttributedString.Key: delegate as Any,
NSAttributedString.Key(rawValue: InstantPageFormulaAttribute): attachment
], range: NSMakeRange(0, mutableAttributedString.length))
return mutableAttributedString
case let .anchor(text, name):
var empty = false
var text = text
@ -655,6 +746,7 @@ func layoutTextItemWithString(_ string: NSAttributedString, boundingWidth: CGFlo
var lines: [InstantPageTextLine] = []
var imageItems: [InstantPageTextImageItem] = []
var formulaItems: [InstantPageTextFormulaItem] = []
var font = string.attribute(NSAttributedString.Key.font, at: 0, effectiveRange: nil) as? UIFont
if font == nil {
let range = NSMakeRange(0, string.length)
@ -665,7 +757,8 @@ func layoutTextItemWithString(_ string: NSAttributedString, boundingWidth: CGFlo
}
}
let image = string.attribute(NSAttributedString.Key.init(rawValue: InstantPageMediaIdAttribute), at: 0, effectiveRange: nil)
guard font != nil || image != nil else {
let formula = string.attribute(NSAttributedString.Key(rawValue: InstantPageFormulaAttribute), at: 0, effectiveRange: nil)
guard font != nil || image != nil || formula != nil else {
return (nil, [], CGSize())
}
@ -686,7 +779,6 @@ func layoutTextItemWithString(_ string: NSAttributedString, boundingWidth: CGFlo
var hasAnchors = false
var maxLineWidth: CGFloat = 0.0
var maxImageHeight: CGFloat = 0.0
var extraDescent: CGFloat = 0.0
let text = string.string
var indexOffset: CFIndex?
@ -741,6 +833,8 @@ func layoutTextItemWithString(_ string: NSAttributedString, boundingWidth: CGFlo
let hadExtraDescent = extraDescent > 0.0
extraDescent = 0.0
var lineImageItems: [InstantPageTextImageItem] = []
var lineFormulaItems: [InstantPageTextFormulaRun] = []
var lineMaxAttachmentHeight: CGFloat = 0.0
var isRTL = false
if let glyphRuns = CTLineGetGlyphRuns(line) as? [CTRun], !glyphRuns.isEmpty {
if let run = glyphRuns.first, CTRunGetStatus(run).contains(CTRunStatus.rightToLeft) {
@ -769,20 +863,49 @@ func layoutTextItemWithString(_ string: NSAttributedString, boundingWidth: CGFlo
if !fontLineHeight.isZero {
extraDescent = max(extraDescent, imageFrame.maxY - (workingLineOrigin.y + fontLineHeight + minSpacing))
}
maxImageHeight = max(maxImageHeight, imageFrame.height)
lineMaxAttachmentHeight = max(lineMaxAttachmentHeight, imageFrame.height)
lineImageItems.append(InstantPageTextImageItem(frame: imageFrame, range: range, id: EngineMedia.Id(namespace: Namespaces.Media.CloudFile, id: id)))
} else if let attachment = attributes[NSAttributedString.Key(rawValue: InstantPageFormulaAttribute)] as? InstantPageMathAttachment {
let xOffset = CTLineGetOffsetForStringIndex(line, range.location, nil)
let baselineOffset = (attributes[NSAttributedString.Key.baselineOffset] as? CGFloat) ?? 0.0
var formulaFrame = CGRect(
origin: CGPoint(
x: workingLineOrigin.x + xOffset,
y: workingLineOrigin.y + fontLineHeight + baselineOffset - attachment.rendered.ascent
),
size: attachment.rendered.size
)
let minSpacing = fontLineSpacing - 4.0
let delta = workingLineOrigin.y - minSpacing - formulaFrame.minY - appliedLineOffset
if !fontAscent.isZero && delta > 0.0 {
workingLineOrigin.y += delta
appliedLineOffset += delta
formulaFrame.origin = formulaFrame.origin.offsetBy(dx: 0.0, dy: delta)
}
if !fontLineHeight.isZero {
extraDescent = max(extraDescent, formulaFrame.maxY - (workingLineOrigin.y + fontLineHeight + minSpacing))
}
lineMaxAttachmentHeight = max(lineMaxAttachmentHeight, formulaFrame.height)
lineFormulaItems.append(InstantPageTextFormulaRun(frame: formulaFrame, range: range, attachment: attachment))
}
}
}
}
if substring.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty && lineImageItems.count > 0 {
if substring.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty && (!lineImageItems.isEmpty || !lineFormulaItems.isEmpty) {
extraDescent += max(6.0, fontLineSpacing / 2.0)
}
if !minimizeWidth && !hadIndexOffset && lineCharacterCount > 1 && lineWidth > currentMaxWidth + 5.0, let imageItem = lineImageItems.last {
indexOffset = -(lastIndex + lineCharacterCount - imageItem.range.lowerBound)
continue
if !minimizeWidth && !hadIndexOffset && lineCharacterCount > 1 && lineWidth > currentMaxWidth + 5.0 {
if let imageItem = lineImageItems.last {
indexOffset = -(lastIndex + lineCharacterCount - imageItem.range.lowerBound)
continue
}
if let formulaItem = lineFormulaItems.last {
indexOffset = -(lastIndex + lineCharacterCount - formulaItem.range.lowerBound)
continue
}
}
var strikethroughItems: [InstantPageTextStrikethroughItem] = []
@ -807,7 +930,7 @@ func layoutTextItemWithString(_ string: NSAttributedString, boundingWidth: CGFlo
let lowerX = floor(CTLineGetOffsetForStringIndex(line, range.location, nil))
let upperX = ceil(CTLineGetOffsetForStringIndex(line, range.location + range.length, nil))
let x = lowerX < upperX ? lowerX : upperX
markedItems.append(InstantPageTextMarkedItem(frame: CGRect(x: workingLineOrigin.x + x, y: workingLineOrigin.y + delta, width: abs(upperX - lowerX), height: lineHeight), color: color))
markedItems.append(InstantPageTextMarkedItem(frame: CGRect(x: workingLineOrigin.x + x, y: workingLineOrigin.y + delta, width: abs(upperX - lowerX), height: lineHeight), color: color, range: range))
}
if let item = attributes[NSAttributedString.Key.init(rawValue: InstantPageAnchorAttribute)] as? Dictionary<String, Any>, let name = item["name"] as? String, let empty = item["empty"] as? Bool {
anchorItems.append(InstantPageTextAnchorItem(name: name, anchorText: item["text"] as? NSAttributedString, empty: empty))
@ -822,11 +945,35 @@ func layoutTextItemWithString(_ string: NSAttributedString, boundingWidth: CGFlo
workingLineOrigin.y += fontLineSpacing
}
let height = !fontLineHeight.isZero ? fontLineHeight : maxImageHeight
let textLine = InstantPageTextLine(line: line, range: lineRange, frame: CGRect(x: workingLineOrigin.x, y: workingLineOrigin.y, width: lineWidth, height: height), strikethroughItems: strikethroughItems, markedItems: markedItems, imageItems: lineImageItems, anchorItems: anchorItems, isRTL: isRTL)
let height = !fontLineHeight.isZero ? max(fontLineHeight, lineMaxAttachmentHeight) : lineMaxAttachmentHeight
if !lineFormulaItems.isEmpty {
let baselineAdjustment = height - fontLineHeight
if !baselineAdjustment.isZero {
lineFormulaItems = lineFormulaItems.map { item in
InstantPageTextFormulaRun(
frame: item.frame.offsetBy(dx: 0.0, dy: baselineAdjustment),
range: item.range,
attachment: item.attachment
)
}
}
}
if !markedItems.isEmpty {
markedItems = markedItems.map { item in
if let attachmentBounds = localAttachmentBoundsForRange(item.range, imageItems: lineImageItems, formulaItems: lineFormulaItems) {
return InstantPageTextMarkedItem(frame: attachmentBounds, color: item.color, range: item.range)
} else {
return item
}
}
}
let textLine = InstantPageTextLine(line: line, range: lineRange, frame: CGRect(x: workingLineOrigin.x, y: workingLineOrigin.y, width: lineWidth, height: height), strikethroughItems: strikethroughItems, markedItems: markedItems, imageItems: lineImageItems, formulaItems: lineFormulaItems, anchorItems: anchorItems, isRTL: isRTL)
lines.append(textLine)
imageItems.append(contentsOf: lineImageItems)
for formulaItem in lineFormulaItems {
formulaItems.append(InstantPageTextFormulaItem(frame: formulaItem.frame, attachment: formulaItem.attachment))
}
if lineWidth > maxLineWidth {
maxLineWidth = lineWidth
@ -853,7 +1000,7 @@ func layoutTextItemWithString(_ string: NSAttributedString, boundingWidth: CGFlo
var textWidth = boundingWidth
var requiresScroll = false
if !imageItems.isEmpty && maxLineWidth > boundingWidth + 10.0 {
if (!imageItems.isEmpty || !formulaItems.isEmpty) && maxLineWidth > boundingWidth + 10.0 {
textWidth = maxLineWidth
requiresScroll = true
}
@ -870,13 +1017,13 @@ func layoutTextItemWithString(_ string: NSAttributedString, boundingWidth: CGFlo
var topInset: CGFloat = 0.0
var bottomInset: CGFloat = 0.0
var additionalItems: [InstantPageItem] = []
if let webpage = webpage {
let offset = requiresScroll ? CGPoint() : offset
for line in textItem.lines {
let lineFrame = frameForLine(line, boundingWidth: boundingWidth, alignment: alignment)
let effectiveOffset = requiresScroll ? CGPoint() : offset
for line in textItem.lines {
let lineFrame = frameForLine(line, boundingWidth: boundingWidth, alignment: alignment)
if let webpage = webpage {
for imageItem in line.imageItems {
if let media = media[imageItem.id] {
let item = InstantPageImageItem(frame: imageItem.frame.offsetBy(dx: lineFrame.minX + offset.x, dy: offset.y), webPage: webpage, media: InstantPageMedia(index: -1, media: media, url: nil, caption: nil, credit: nil), interactive: false, roundCorners: false, fit: false)
let item = InstantPageImageItem(frame: imageItem.frame.offsetBy(dx: lineFrame.minX + effectiveOffset.x, dy: effectiveOffset.y), webPage: webpage, media: InstantPageMedia(index: -1, media: media, url: nil, caption: nil, credit: nil), interactive: false, roundCorners: false, fit: false)
additionalItems.append(item)
if item.frame.minY < topInset {
@ -888,6 +1035,17 @@ func layoutTextItemWithString(_ string: NSAttributedString, boundingWidth: CGFlo
}
}
}
for formulaItem in line.formulaItems {
let item = InstantPageTextFormulaItem(frame: formulaItem.frame.offsetBy(dx: lineFrame.minX + effectiveOffset.x, dy: effectiveOffset.y), attachment: formulaItem.attachment)
additionalItems.append(item)
if item.frame.minY < topInset {
topInset = item.frame.minY
}
if item.frame.maxY > height {
bottomInset = max(bottomInset, item.frame.maxY - height)
}
}
}
if requiresScroll {

View file

@ -28,6 +28,7 @@ let InstantPageMarkerColorAttribute = "MarkerColorAttribute"
let InstantPageMediaIdAttribute = "MediaIdAttribute"
let InstantPageMediaDimensionsAttribute = "MediaDimensionsAttribute"
let InstantPageAnchorAttribute = "AnchorAttribute"
let InstantPageFormulaAttribute = "FormulaAttribute"
final class InstantPageTextStyleStack {
private var items: [InstantPageTextStyle] = []

View file

@ -355,7 +355,7 @@ private enum InviteLinksEditEntry: ItemListNodeEntry {
case let .timeHeader(_, text):
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
case let .timePicker(_, value, enabled):
return ItemListInviteLinkTimeLimitItem(theme: presentationData.theme, strings: presentationData.strings, value: value, enabled: enabled, sectionId: self.section, updated: { value in
return ItemListInviteLinkTimeLimitItem(theme: presentationData.theme, systemStyle: .glass, strings: presentationData.strings, value: value, enabled: enabled, sectionId: self.section, updated: { value in
arguments.updateState({ state in
var updatedState = state
if value != updatedState.time {
@ -418,7 +418,7 @@ private enum InviteLinksEditEntry: ItemListNodeEntry {
case let .usageHeader(_, text):
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
case let .usagePicker(_, dateTimeFormat, value, enabled):
return ItemListInviteLinkUsageLimitItem(theme: presentationData.theme, strings: presentationData.strings, dateTimeFormat: dateTimeFormat, value: value, enabled: enabled, sectionId: self.section, updated: { value in
return ItemListInviteLinkUsageLimitItem(theme: presentationData.theme, systemStyle: .glass, strings: presentationData.strings, dateTimeFormat: dateTimeFormat, value: value, enabled: enabled, sectionId: self.section, updated: { value in
arguments.dismissInput()
arguments.updateState({ state in
var updatedState = state

View file

@ -73,14 +73,16 @@ enum InviteLinkTimeLimit: Equatable {
final class ItemListInviteLinkTimeLimitItem: ListViewItem, ItemListItem {
let theme: PresentationTheme
let systemStyle: ItemListSystemStyle
let strings: PresentationStrings
let value: InviteLinkTimeLimit
let enabled: Bool
let sectionId: ItemListSectionId
let updated: (InviteLinkTimeLimit) -> Void
init(theme: PresentationTheme, strings: PresentationStrings, value: InviteLinkTimeLimit, enabled: Bool, sectionId: ItemListSectionId, updated: @escaping (InviteLinkTimeLimit) -> Void) {
init(theme: PresentationTheme, systemStyle: ItemListSystemStyle, strings: PresentationStrings, value: InviteLinkTimeLimit, enabled: Bool, sectionId: ItemListSectionId, updated: @escaping (InviteLinkTimeLimit) -> Void) {
self.theme = theme
self.systemStyle = systemStyle
self.strings = strings
self.value = value
self.enabled = enabled
@ -326,7 +328,7 @@ private final class ItemListInviteLinkTimeLimitItemNode: ListViewItemNode {
strongSelf.bottomStripeNode.isHidden = hasCorners
}
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners, glass: item.systemStyle == .glass) : nil
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight)))
strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0)

View file

@ -87,6 +87,7 @@ enum InviteLinkUsageLimit: Equatable {
final class ItemListInviteLinkUsageLimitItem: ListViewItem, ItemListItem {
let theme: PresentationTheme
let systemStyle: ItemListSystemStyle
let strings: PresentationStrings
let dateTimeFormat: PresentationDateTimeFormat
let value: InviteLinkUsageLimit
@ -94,8 +95,9 @@ final class ItemListInviteLinkUsageLimitItem: ListViewItem, ItemListItem {
let sectionId: ItemListSectionId
let updated: (InviteLinkUsageLimit) -> Void
init(theme: PresentationTheme, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, value: InviteLinkUsageLimit, enabled: Bool, sectionId: ItemListSectionId, updated: @escaping (InviteLinkUsageLimit) -> Void) {
init(theme: PresentationTheme, systemStyle: ItemListSystemStyle, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, value: InviteLinkUsageLimit, enabled: Bool, sectionId: ItemListSectionId, updated: @escaping (InviteLinkUsageLimit) -> Void) {
self.theme = theme
self.systemStyle = systemStyle
self.strings = strings
self.dateTimeFormat = dateTimeFormat
self.value = value
@ -336,7 +338,7 @@ private final class ItemListInviteLinkUsageLimitItemNode: ListViewItemNode {
strongSelf.bottomStripeNode.isHidden = hasCorners
}
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners, glass: item.systemStyle == .glass) : nil
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight)))
strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

View file

@ -116,13 +116,9 @@ UIFont *TGFixedSystemFontOfSize(CGFloat size)
+ (UIFont *)roundedFontOfSize:(CGFloat)size
{
if (@available(iOSApplicationExtension 13.0, iOS 13.0, *)) {
UIFontDescriptor *descriptor = [UIFont boldSystemFontOfSize:size].fontDescriptor;
descriptor = [descriptor fontDescriptorWithDesign:UIFontDescriptorSystemDesignRounded];
return [UIFont fontWithDescriptor:descriptor size:size];
} else {
return [UIFont fontWithName:@".SFCompactRounded-Semibold" size:size];
}
UIFontDescriptor *descriptor = [UIFont boldSystemFontOfSize:size].fontDescriptor;
descriptor = [descriptor fontDescriptorWithDesign:UIFontDescriptorSystemDesignRounded];
return [UIFont fontWithDescriptor:descriptor size:size];
}
@end

View file

@ -330,11 +330,7 @@ typedef enum
_circleWrapperView.alpha = 0.0f;
_circleWrapperView.clipsToBounds = false;
[_wrapperView addSubview:_circleWrapperView];
_shadowView = [[UIImageView alloc] initWithImage:TGComponentsImageNamed(@"VideoMessageShadow")];
_shadowView.frame = _circleWrapperView.bounds;
[_circleWrapperView addSubview:_shadowView];
_circleView = [[UIView alloc] initWithFrame:CGRectInset(_circleWrapperView.bounds, shadowSize, shadowSize)];
_circleView.clipsToBounds = true;
_circleView.layer.cornerRadius = _circleView.frame.size.width / 2.0f;

View file

@ -677,6 +677,9 @@ UIImage *normalizeImage(UIImage *image)
NSString *recognizeMRZ(UIImage *input, CGRect *outBoundingRect)
{
if (@"".length == 0) {
return nil;
}
input = normalizeImage(input);
UIImage *binaryImage;

View file

@ -303,7 +303,7 @@ public func globalAutoremoveScreen(context: AccountContext, initialValue: Int32,
},
openCustomValue: {
let currentValue = stateValue.with({ $0 }).updatedValue
let controller = ChatTimerScreen(context: context, updatedPresentationData: nil, style: .default, mode: .autoremove, currentTime: currentValue == 0 ? nil : currentValue, dismissByTapOutside: true, completion: { value in
let controller = ChatTimerScreen(context: context, updatedPresentationData: nil, style: .default, mode: .autoremove, currentTime: currentValue == 0 ? nil : currentValue, completion: { value in
updateValue(value)
})
presentControllerImpl?(controller, nil)

View file

@ -35,7 +35,8 @@ union InstantPageBlock_Value {
InstantPageBlock_Details,
InstantPageBlock_RelatedArticles,
InstantPageBlock_Map,
InstantPageBlock_Heading
InstantPageBlock_Heading,
InstantPageBlock_Formula
}
table InstantPageBlock {
@ -191,6 +192,10 @@ table InstantPageBlock_Heading {
level:int32 (id: 1);
}
table InstantPageBlock_Formula {
latex:string (id: 0, required);
}
table InstantPageCaption {
text:RichText (id: 0, required);
credit:RichText (id: 1, required);

View file

@ -19,7 +19,8 @@ union RichText_Value {
RichText_Marked,
RichText_Phone,
RichText_Image,
RichText_Anchor
RichText_Anchor,
RichText_Formula
}
table RichText {
@ -92,4 +93,8 @@ table RichText_Image {
table RichText_Anchor {
text:RichText (id: 0, required);
name:string (id: 1, required);
}
}
table RichText_Formula {
latex:string (id: 0, required);
}

View file

@ -988,35 +988,24 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId,
forwardInfo = StoreMessageForwardInfo(authorId: sourceForwardInfo.author?.id, sourceId: sourceForwardInfo.source?.id, sourceMessageId: sourceForwardInfo.sourceMessageId, date: sourceForwardInfo.date, authorSignature: sourceForwardInfo.authorSignature, psaType: nil, flags: [])
} else {
if sourceMessage.id.peerId != account.peerId {
var hasHiddenForwardMedia = false
for media in sourceMessage.media {
if let file = media as? TelegramMediaFile {
if file.isMusic {
hasHiddenForwardMedia = true
}
var sourceId: PeerId? = nil
var sourceMessageId: MessageId? = nil
if case let .channel(peer) = messageMainPeer(EngineMessage(sourceMessage)), case .broadcast = peer.info {
sourceId = peer.id
sourceMessageId = sourceMessage.id
}
var authorSignature: String?
for attribute in sourceMessage.attributes {
if let attribute = attribute as? AuthorSignatureMessageAttribute {
authorSignature = attribute.signature
break
}
}
if !hasHiddenForwardMedia {
var sourceId: PeerId? = nil
var sourceMessageId: MessageId? = nil
if case let .channel(peer) = messageMainPeer(EngineMessage(sourceMessage)), case .broadcast = peer.info {
sourceId = peer.id
sourceMessageId = sourceMessage.id
}
var authorSignature: String?
for attribute in sourceMessage.attributes {
if let attribute = attribute as? AuthorSignatureMessageAttribute {
authorSignature = attribute.signature
break
}
}
let psaType: String? = nil
forwardInfo = StoreMessageForwardInfo(authorId: author.id, sourceId: sourceId, sourceMessageId: sourceMessageId, date: sourceMessage.timestamp, authorSignature: authorSignature, psaType: psaType, flags: [])
}
let psaType: String? = nil
forwardInfo = StoreMessageForwardInfo(authorId: author.id, sourceId: sourceId, sourceMessageId: sourceMessageId, date: sourceMessage.timestamp, authorSignature: authorSignature, psaType: psaType, flags: [])
} else {
forwardInfo = nil
}

View file

@ -33,6 +33,7 @@ private enum InstantPageBlockType: Int32 {
case relatedArticles = 26
case map = 27
case heading = 28
case formula = 29
}
private func decodeListItems(_ decoder: PostboxDecoder) -> [InstantPageListItem] {
@ -62,6 +63,7 @@ public indirect enum InstantPageBlock: PostboxCoding, Equatable {
case header(RichText)
case subheader(RichText)
case heading(text: RichText, level: Int32)
case formula(latex: String)
case paragraph(RichText)
case preformatted(text: RichText, language: String?)
case footer(RichText)
@ -101,6 +103,8 @@ public indirect enum InstantPageBlock: PostboxCoding, Equatable {
self = .subheader(decoder.decodeObjectForKey("t", decoder: { RichText(decoder: $0) }) as! RichText)
case InstantPageBlockType.heading.rawValue:
self = .heading(text: decoder.decodeObjectForKey("t", decoder: { RichText(decoder: $0) }) as! RichText, level: decoder.decodeInt32ForKey("l", orElse: 3))
case InstantPageBlockType.formula.rawValue:
self = .formula(latex: decoder.decodeStringForKey("l", orElse: ""))
case InstantPageBlockType.paragraph.rawValue:
self = .paragraph(decoder.decodeObjectForKey("t", decoder: { RichText(decoder: $0) }) as! RichText)
case InstantPageBlockType.preformatted.rawValue:
@ -195,6 +199,9 @@ public indirect enum InstantPageBlock: PostboxCoding, Equatable {
encoder.encodeInt32(InstantPageBlockType.heading.rawValue, forKey: "r")
encoder.encodeObject(text, forKey: "t")
encoder.encodeInt32(level, forKey: "l")
case let .formula(latex):
encoder.encodeInt32(InstantPageBlockType.formula.rawValue, forKey: "r")
encoder.encodeString(latex, forKey: "l")
case let .paragraph(text):
encoder.encodeInt32(InstantPageBlockType.paragraph.rawValue, forKey: "r")
encoder.encodeObject(text, forKey: "t")
@ -396,6 +403,12 @@ public indirect enum InstantPageBlock: PostboxCoding, Equatable {
} else {
return false
}
case let .formula(lhsLatex):
if case let .formula(rhsLatex) = rhs, lhsLatex == rhsLatex {
return true
} else {
return false
}
case let .paragraph(text):
if case .paragraph(text) = rhs {
return true
@ -572,6 +585,11 @@ public indirect enum InstantPageBlock: PostboxCoding, Equatable {
throw FlatBuffersError.missingRequiredField()
}
self = .heading(text: try RichText(flatBuffersObject: value.text), level: value.level)
case .instantpageblockFormula:
guard let value = flatBuffersObject.value(type: TelegramCore_InstantPageBlock_Formula.self) else {
throw FlatBuffersError.missingRequiredField()
}
self = .formula(latex: value.latex)
case .instantpageblockParagraph:
guard let value = flatBuffersObject.value(type: TelegramCore_InstantPageBlock_Paragraph.self) else {
throw FlatBuffersError.missingRequiredField()
@ -732,6 +750,12 @@ public indirect enum InstantPageBlock: PostboxCoding, Equatable {
TelegramCore_InstantPageBlock_Heading.add(text: textOffset, &builder)
TelegramCore_InstantPageBlock_Heading.add(level: level, &builder)
offset = TelegramCore_InstantPageBlock_Heading.endInstantPageBlock_Heading(&builder, start: start)
case let .formula(latex):
valueType = .instantpageblockFormula
let latexOffset = builder.create(string: latex)
let start = TelegramCore_InstantPageBlock_Formula.startInstantPageBlock_Formula(&builder)
TelegramCore_InstantPageBlock_Formula.add(latex: latexOffset, &builder)
offset = TelegramCore_InstantPageBlock_Formula.endInstantPageBlock_Formula(&builder, start: start)
case let .paragraph(text):
valueType = .instantpageblockParagraph
let textOffset = text.encodeToFlatBuffers(builder: &builder)

View file

@ -19,6 +19,7 @@ private enum RichTextTypes: Int32 {
case phone = 13
case image = 14
case anchor = 15
case formula = 16
}
public indirect enum RichText: PostboxCoding, Equatable {
@ -38,6 +39,7 @@ public indirect enum RichText: PostboxCoding, Equatable {
case phone(text: RichText, phone: String)
case image(id: MediaId, dimensions: PixelDimensions)
case anchor(text: RichText, name: String)
case formula(latex: String)
public init(decoder: PostboxDecoder) {
switch decoder.decodeInt32ForKey("r", orElse: 0) {
@ -79,6 +81,8 @@ public indirect enum RichText: PostboxCoding, Equatable {
self = .image(id: MediaId(namespace: decoder.decodeInt32ForKey("i.n", orElse: 0), id: decoder.decodeInt64ForKey("i.i", orElse: 0)), dimensions: PixelDimensions(width: decoder.decodeInt32ForKey("sw", orElse: 0), height: decoder.decodeInt32ForKey("sh", orElse: 0)))
case RichTextTypes.anchor.rawValue:
self = .anchor(text: decoder.decodeObjectForKey("t", decoder: { RichText(decoder: $0) }) as! RichText, name: decoder.decodeStringForKey("n", orElse: ""))
case RichTextTypes.formula.rawValue:
self = .formula(latex: decoder.decodeStringForKey("l", orElse: ""))
default:
self = .empty
}
@ -147,6 +151,9 @@ public indirect enum RichText: PostboxCoding, Equatable {
encoder.encodeInt32(RichTextTypes.anchor.rawValue, forKey: "r")
encoder.encodeObject(text, forKey: "t")
encoder.encodeString(name, forKey: "n")
case let .formula(latex):
encoder.encodeInt32(RichTextTypes.formula.rawValue, forKey: "r")
encoder.encodeString(latex, forKey: "l")
}
}
@ -248,6 +255,12 @@ public indirect enum RichText: PostboxCoding, Equatable {
} else {
return false
}
case let .formula(lhsLatex):
if case let .formula(rhsLatex) = rhs, lhsLatex == rhsLatex {
return true
} else {
return false
}
}
}
}
@ -291,6 +304,8 @@ public extension RichText {
return ""
case let .anchor(text, _):
return text.plainText
case let .formula(latex):
return latex
}
}
}
@ -378,6 +393,11 @@ extension RichText {
}
self = .anchor(text: try RichText(flatBuffersObject: value.text),
name: value.name)
case .richtextFormula:
guard let value = flatBuffersObject.value(type: TelegramCore_RichText_Formula.self) else {
throw FlatBuffersError.missingRequiredField()
}
self = .formula(latex: value.latex)
case .none_:
self = .empty
}
@ -494,6 +514,12 @@ extension RichText {
TelegramCore_RichText_Anchor.add(text: textOffset, &builder)
TelegramCore_RichText_Anchor.add(name: nameOffset, &builder)
offset = TelegramCore_RichText_Anchor.endRichText_Anchor(&builder, start: start)
case let .formula(latex):
valueType = .richtextFormula
let latexOffset = builder.create(string: latex)
let start = TelegramCore_RichText_Formula.startRichText_Formula(&builder)
TelegramCore_RichText_Formula.add(latex: latexOffset, &builder)
offset = TelegramCore_RichText_Formula.endRichText_Formula(&builder, start: start)
}
return TelegramCore_RichText.createRichText(&builder, valueType: valueType, valueOffset: offset)

View file

@ -3,6 +3,38 @@ import Postbox
import TelegramApi
import SwiftSignalKit
public enum SendBotGameError {
case generic
}
func _internal_sendBotGame(account: Account, botPeerId: PeerId, game: String, to peerId: PeerId, threadId: Int64?) -> Signal<Void, SendBotGameError> {
return account.postbox.transaction { transaction -> Signal<Void, SendBotGameError> in
guard !game.isEmpty, let botPeer = transaction.getPeer(botPeerId), let inputBot = apiInputUser(botPeer), let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) else {
return .fail(.generic)
}
var flags: Int32 = 1 << 7
var replyTo: Api.InputReplyTo?
if let threadId {
flags |= 1 << 0
let threadMessageId = Int32(clamping: threadId)
let replyFlags: Int32 = 1 << 0
replyTo = .inputReplyToMessage(.init(flags: replyFlags, replyToMsgId: threadMessageId, topMsgId: threadMessageId, replyToPeerId: nil, quoteText: nil, quoteEntities: nil, quoteOffset: nil, monoforumPeerId: nil, todoItemId: nil, pollOption: nil))
}
return account.network.request(Api.functions.messages.sendMedia(flags: flags, peer: inputPeer, replyTo: replyTo, media: .inputMediaGame(.init(id: .inputGameShortName(.init(botId: inputBot, shortName: game)))), message: "", randomId: Int64.random(in: Int64.min ... Int64.max), replyMarkup: nil, entities: nil, scheduleDate: nil, scheduleRepeatPeriod: nil, sendAs: nil, quickReplyShortcut: nil, effect: nil, allowPaidStars: nil, suggestedPost: nil))
|> mapError { _ -> SendBotGameError in
return .generic
}
|> mapToSignal { updates -> Signal<Void, SendBotGameError> in
account.stateManager.addUpdates(updates)
return .complete()
}
}
|> castError(SendBotGameError.self)
|> switchToLatest
}
func _internal_forwardGameWithScore(account: Account, messageId: MessageId, to peerId: PeerId, threadId: Int64?, as sendAsPeerId: PeerId?) -> Signal<Void, NoError> {
return account.postbox.transaction { transaction -> Signal<Void, NoError> in
if let _ = transaction.getMessage(messageId), let fromPeer = transaction.getPeer(messageId.peerId), let fromInputPeer = apiInputPeer(fromPeer), let toPeer = transaction.getPeer(peerId), let toInputPeer = apiInputPeer(toPeer) {

View file

@ -219,6 +219,10 @@ public extension TelegramEngine {
return _internal_forwardGameWithScore(account: self.account, messageId: messageId, to: peerId, threadId: threadId, as: senderPeerId)
}
public func sendBotGame(botPeerId: PeerId, game: String, to peerId: PeerId, threadId: Int64?) -> Signal<Void, SendBotGameError> {
return _internal_sendBotGame(account: self.account, botPeerId: botPeerId, game: game, to: peerId, threadId: threadId)
}
public func requestUpdatePinnedMessage(peerId: PeerId, update: PinnedMessageUpdate) -> Signal<Void, UpdatePinnedMessageError> {
return _internal_requestUpdatePinnedMessage(account: self.account, peerId: peerId, update: update)
}

View file

@ -379,9 +379,7 @@ private final class AdminUserActionsContentComponent: Component {
func update(component: AdminUserActionsContentComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<ViewControllerComponentContainer.Environment>, transition: ComponentTransition) -> CGSize {
let environment = environment[ViewControllerComponentContainer.Environment.self].value
let sideInset: CGFloat = 16.0
var contentHeight: CGFloat = 76.0
contentHeight += 15.0
var contentHeight: CGFloat = 76.0 + 15.0
let availableOptions = availableAdminUserActionOptionSections(
accountPeerId: component.context.account.peerId,

View file

@ -222,6 +222,7 @@ public final class ChatInputMessageAccessoryPanel: Component {
let contents: Contents
let chatPeerId: EnginePeer.Id?
let action: ((UIView) -> Void)?
let longPressAction: ((UIView) -> Void)?
let dismiss: (UIView) -> Void
public init(
@ -229,12 +230,14 @@ public final class ChatInputMessageAccessoryPanel: Component {
contents: Contents,
chatPeerId: EnginePeer.Id?,
action: ((UIView) -> Void)?,
longPressAction: ((UIView) -> Void)? = nil,
dismiss: @escaping (UIView) -> Void
) {
self.context = context
self.contents = contents
self.chatPeerId = chatPeerId
self.action = action
self.longPressAction = longPressAction
self.dismiss = dismiss
}
@ -251,12 +254,16 @@ public final class ChatInputMessageAccessoryPanel: Component {
if (lhs.action == nil) != (rhs.action == nil) {
return false
}
if (lhs.longPressAction == nil) != (rhs.longPressAction == nil) {
return false
}
return true
}
public final class View: UIView, ChatInputAccessoryPanelView {
private let closeButton: HighlightTrackingButton
private let closeButtonIcon: GlassBackgroundView.ContentImageView
private let longPressGestureRecognizer: UILongPressGestureRecognizer
private let lineView: UIImageView
private let titleNode: CompositeTextNode
@ -295,6 +302,7 @@ public final class ChatInputMessageAccessoryPanel: Component {
self.closeButton = HighlightTrackingButton()
self.closeButtonIcon = GlassBackgroundView.ContentImageView()
self.longPressGestureRecognizer = UILongPressGestureRecognizer()
self.lineView = UIImageView()
self.titleNode = CompositeTextNode()
@ -311,6 +319,10 @@ public final class ChatInputMessageAccessoryPanel: Component {
self.closeButton.addTarget(self, action: #selector(self.closeButtonPressed), for: .touchUpInside)
self.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:))))
self.longPressGestureRecognizer.addTarget(self, action: #selector(self.longPressGesture(_:)))
self.longPressGestureRecognizer.isEnabled = false
self.addGestureRecognizer(self.longPressGestureRecognizer)
}
required public init?(coder: NSCoder) {
@ -330,6 +342,15 @@ public final class ChatInputMessageAccessoryPanel: Component {
}
}
@objc private func longPressGesture(_ recognizer: UILongPressGestureRecognizer) {
guard let component = self.component else {
return
}
if case .began = recognizer.state {
component.longPressAction?(self)
}
}
@objc private func closeButtonPressed() {
guard let component = self.component else {
return
@ -384,6 +405,7 @@ public final class ChatInputMessageAccessoryPanel: Component {
self.component = component
self.state = state
self.environment = environment
self.longPressGestureRecognizer.isEnabled = component.longPressAction != nil
if self.closeButtonIcon.image == nil {
self.closeButtonIcon.image = generateCloseIcon()

View file

@ -1766,9 +1766,7 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
if let forwardInfo = item.content.firstMessage.forwardInfo, forwardInfo.source == nil, forwardInfo.author?.id.namespace == Namespaces.Peer.CloudUser {
for media in item.content.firstMessage.media {
if let file = media as? TelegramMediaFile {
if file.isMusic {
ignoreForward = true
} else if file.isInstantVideo {
if file.isInstantVideo {
isInstantVideo = true
}
break

View file

@ -772,7 +772,7 @@ public final class ChatMessageInteractiveFileNode: ASDisplayNode {
displayTranscribe = false
} else if arguments.message.id.peerId.namespace != Namespaces.Peer.SecretChat && !isViewOnceMessage && !arguments.presentationData.isPreview {
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: arguments.context.currentAppConfiguration.with { $0 })
if arguments.associatedData.isPremium {
if arguments.associatedData.isPremium || arguments.associatedData.alwaysDisplayTranscribeButton.providedByGroupBoost {
displayTranscribe = true
} else if premiumConfiguration.audioTransciptionTrialCount > 0 {
if arguments.incoming {
@ -786,8 +786,6 @@ public final class ChatMessageInteractiveFileNode: ASDisplayNode {
} else if arguments.incoming && isConsumed == false && arguments.associatedData.alwaysDisplayTranscribeButton.displayForNotConsumed {
displayTranscribe = true
}
} else if arguments.associatedData.alwaysDisplayTranscribeButton.providedByGroupBoost {
displayTranscribe = true
}
}
@ -2227,4 +2225,3 @@ public final class FileMessageSelectionNode: ASDisplayNode {
self.checkNode.frame = CGRect(origin: checkOrigin, size: checkSize)
}
}

View file

@ -840,7 +840,7 @@ public class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
var displayTranscribe = false
if item.message.id.peerId.namespace != Namespaces.Peer.SecretChat && statusDisplayType == .free && !isViewOnceMessage && !item.presentationData.isPreview {
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: item.context.currentAppConfiguration.with { $0 })
if item.associatedData.isPremium {
if item.associatedData.isPremium || item.associatedData.alwaysDisplayTranscribeButton.providedByGroupBoost {
displayTranscribe = true
} else if premiumConfiguration.audioTransciptionTrialCount > 0 {
if incoming {
@ -852,8 +852,6 @@ public class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
} else {
displayTranscribe = false
}
} else if item.associatedData.alwaysDisplayTranscribeButton.providedByGroupBoost {
displayTranscribe = true
}
}

View file

@ -2690,6 +2690,14 @@ public class ChatMessagePollBubbleContentNode: ChatMessageBubbleContentNode {
if !poll.countries.isEmpty, let accountCountry = item.associatedData.accountCountry, !poll.countries.contains(accountCountry) {
isRestricted = true
}
if poll.restrictToSubscribers {
let period: Int32 = item.context.account.testingEnvironment ? 5 * 60 : 24 * 60 * 60
if !item.associatedData.isParticipant {
isRestricted = true
} else if let invitedOn = item.associatedData.invitedOn, invitedOn + period > Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970) {
isRestricted = true
}
}
orderedPollOptions = resolvedOptionOrder(for: item)

View file

@ -1487,7 +1487,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
}
private func presentAutoremoveSetup() {
/*let controller = ChatTimerScreen(context: self.context, updatedPresentationData: self.controller?.updatedPresentationData, peerId: self.peer.id, style: .default, mode: .autoremove, currentTime: currentValue, dismissByTapOutside: true, completion: { [weak self] value in
/*let controller = ChatTimerScreen(context: self.context, updatedPresentationData: self.controller?.updatedPresentationData, peerId: self.peer.id, style: .default, mode: .autoremove, currentTime: currentValue, completion: { [weak self] value in
guard let strongSelf = self else {
return
}

View file

@ -613,12 +613,12 @@ private final class ChatScheduleTimeSheetContentComponent: Component {
component: AnyComponent(ButtonComponent(
background: ButtonComponent.Background(
style: .glass,
color: environment.theme.list.itemDestructiveColor.withMultipliedAlpha(0.1),
foreground: environment.theme.list.itemDestructiveColor,
pressedColor: environment.theme.list.itemDestructiveColor.withMultipliedAlpha(0.8),
color: environment.theme.list.itemAccentColor.withMultipliedAlpha(0.1),
foreground: environment.theme.list.itemAccentColor,
pressedColor: environment.theme.list.itemAccentColor.withMultipliedAlpha(0.8),
),
content: AnyComponentWithIdentity(id: AnyHashable(0 as Int), component: AnyComponent(
Text(text: strings.Conversation_FormatDate_RemoveDate, font: Font.semibold(17.0), color: environment.theme.list.itemDestructiveColor)
Text(text: strings.Conversation_FormatDate_RemoveDate, font: Font.semibold(17.0), color: environment.theme.list.itemAccentColor)
)),
isEnabled: true,
displaysProgress: false,

View file

@ -11,14 +11,18 @@ swift_library(
],
deps = [
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
"//submodules/AsyncDisplayKit:AsyncDisplayKit",
"//submodules/Display:Display",
"//submodules/TelegramCore:TelegramCore",
"//submodules/AccountContext:AccountContext",
"//submodules/TelegramPresentationData:TelegramPresentationData",
"//submodules/SolidRoundedButtonNode:SolidRoundedButtonNode",
"//submodules/PresentationDataUtils:PresentationDataUtils",
"//submodules/TelegramStringFormatting:TelegramStringFormatting",
"//submodules/ComponentFlow",
"//submodules/Components/ViewControllerComponent",
"//submodules/Components/SheetComponent",
"//submodules/TelegramUI/Components/ButtonComponent",
"//submodules/Components/BundleIconComponent",
"//submodules/TelegramUI/Components/GlassBarButtonComponent",
],
visibility = [
"//visibility:public",

View file

@ -1498,7 +1498,6 @@ final class ComposePollScreenComponent: Component {
pollTextSectionItems.append(AnyComponentWithIdentity(id: 0, component: AnyComponent(ListComposePollOptionComponent(
externalState: self.pollTextInputState,
context: component.context,
style: .glass,
theme: theme,
strings: environment.strings,
resetText: self.resetPollText.flatMap { resetText in
@ -1534,7 +1533,6 @@ final class ComposePollScreenComponent: Component {
pollTextSectionItems.append(AnyComponentWithIdentity(id: 1, component: AnyComponent(ListComposePollOptionComponent(
externalState: self.pollDescriptionInputState,
context: component.context,
style: .glass,
theme: theme,
strings: environment.strings,
resetText: nil,
@ -1650,7 +1648,6 @@ final class ComposePollScreenComponent: Component {
pollOptionsSectionItems.append(AnyComponentWithIdentity(id: pollOption.id, component: AnyComponent(ListComposePollOptionComponent(
externalState: pollOption.textInputState,
context: component.context,
style: .glass,
theme: theme,
strings: environment.strings,
resetText: pollOption.resetText.flatMap { resetText in
@ -2499,7 +2496,6 @@ final class ComposePollScreenComponent: Component {
AnyComponentWithIdentity(id: 0, component: AnyComponent(ListComposePollOptionComponent(
externalState: self.quizAnswerTextInputState,
context: component.context,
style: .glass,
theme: theme,
strings: environment.strings,
resetText: self.resetQuizAnswerText.flatMap { resetText in

View file

@ -784,7 +784,6 @@ final class ComposeTodoScreenComponent: Component {
todoTextSectionItems.append(AnyComponentWithIdentity(id: 0, component: AnyComponent(ListComposePollOptionComponent(
externalState: self.todoTextInputState,
context: component.context,
style: .glass,
theme: theme,
strings: environment.strings,
isEnabled: canEdit,
@ -874,7 +873,6 @@ final class ComposeTodoScreenComponent: Component {
todoItemsSectionItems.append(AnyComponentWithIdentity(id: todoItem.id, component: AnyComponent(ListComposePollOptionComponent(
externalState: todoItem.textInputState,
context: component.context,
style: .glass,
theme: theme,
strings: environment.strings,
isEnabled: isEnabled,

View file

@ -716,7 +716,6 @@ final class NewContactScreenComponent: Component {
ListComposePollOptionComponent(
externalState: nil,
context: component.context,
style: .glass,
theme: theme,
strings: strings,
placeholder: NSAttributedString(string: strings.AddContact_NotePlaceholder, font: Font.regular(17.0), textColor: theme.list.itemPlaceholderTextColor),

View file

@ -22,11 +22,6 @@ import EmojiTextAttachmentView
import TextFormat
public final class ListComposePollOptionComponent: Component {
public enum Style {
case glass
case legacy
}
public final class ResetText: Equatable {
public let value: NSAttributedString
@ -117,7 +112,6 @@ public final class ListComposePollOptionComponent: Component {
public let externalState: TextFieldComponent.ExternalState?
public let context: AccountContext
public let style: Style
public let theme: PresentationTheme
public let strings: PresentationStrings
public let placeholder: NSAttributedString?
@ -148,7 +142,6 @@ public final class ListComposePollOptionComponent: Component {
public init(
externalState: TextFieldComponent.ExternalState?,
context: AccountContext,
style: Style = .legacy,
theme: PresentationTheme,
strings: PresentationStrings,
placeholder: NSAttributedString? = nil,
@ -178,7 +171,6 @@ public final class ListComposePollOptionComponent: Component {
) {
self.externalState = externalState
self.context = context
self.style = style
self.theme = theme
self.strings = strings
self.placeholder = placeholder
@ -214,9 +206,6 @@ public final class ListComposePollOptionComponent: Component {
if lhs.context !== rhs.context {
return false
}
if lhs.style != rhs.style {
return false
}
if lhs.theme !== rhs.theme {
return false
}
@ -690,10 +679,7 @@ public final class ListComposePollOptionComponent: Component {
self.component = component
self.state = state
var verticalInset: CGFloat = 12.0
if case .glass = component.style {
verticalInset = 16.0
}
let verticalInset: CGFloat = 16.0
var leftInset: CGFloat = 16.0
var rightInset: CGFloat = 16.0
let modeSelectorSize = CGSize(width: 32.0, height: 32.0)
@ -1372,10 +1358,7 @@ public final class ListComposePollOptionComponent: Component {
return
}
var verticalInset: CGFloat = 12.0
if case .glass = component.style {
verticalInset = 16.0
}
let verticalInset: CGFloat = 16.0
var leftInset: CGFloat = 16.0
let rightInset: CGFloat = 16.0

View file

@ -3056,7 +3056,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
}
func openAutoremove(currentValue: Int32?) {
let controller = ChatTimerScreen(context: self.context, updatedPresentationData: self.controller?.updatedPresentationData, style: .default, mode: .autoremove, currentTime: currentValue, dismissByTapOutside: true, completion: { [weak self] value in
let controller = ChatTimerScreen(context: self.context, updatedPresentationData: self.controller?.updatedPresentationData, style: .default, mode: .autoremove, currentTime: currentValue, completion: { [weak self] value in
guard let strongSelf = self else {
return
}
@ -3085,7 +3085,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
}
func openCustomMute() {
let controller = ChatTimerScreen(context: self.context, updatedPresentationData: self.controller?.updatedPresentationData, style: .default, mode: .mute, currentTime: nil, dismissByTapOutside: true, completion: { [weak self] value in
let controller = ChatTimerScreen(context: self.context, updatedPresentationData: self.controller?.updatedPresentationData, style: .default, mode: .mute, currentTime: nil, completion: { [weak self] value in
guard let strongSelf = self, let peer = strongSelf.data?.peer else {
return
}

View file

@ -466,13 +466,10 @@ final class PeerSelectionControllerNode: ASDisplayNode {
}
var isDice = false
var isMusic = false
for media in message.media {
if let media = media as? TelegramMediaFile, media.isMusic {
isMusic = true
} else if media is TelegramMediaDice {
if media is TelegramMediaDice {
isDice = true
} else {
} else if (media as? TelegramMediaFile)?.isMusic != true {
if !message.text.isEmpty {
if media is TelegramMediaImage || media is TelegramMediaFile {
hasCaptions = true
@ -480,7 +477,7 @@ final class PeerSelectionControllerNode: ASDisplayNode {
}
}
}
if !isDice && !isMusic {
if !isDice {
hasOther = true
}
}

View file

@ -2914,12 +2914,12 @@ final class StoryItemSetContainerSendMessage: @unchecked(Sendable) {
})
}
private func presentTimerPicker(view: StoryItemSetContainerComponent.View, peer: EnginePeer, style: ChatTimerScreenStyle = .default, selectedTime: Int32? = nil, dismissByTapOutside: Bool = true, completion: @escaping (Int32) -> Void) {
private func presentTimerPicker(view: StoryItemSetContainerComponent.View, peer: EnginePeer, style: ChatTimerScreenStyle = .default, selectedTime: Int32? = nil, completion: @escaping (Int32) -> Void) {
guard let component = view.component else {
return
}
let theme = component.theme
let controller = ChatTimerScreen(context: component.context, updatedPresentationData: (component.context.sharedContext.currentPresentationData.with({ $0 }).withUpdated(theme: theme), component.context.sharedContext.presentationData |> map { $0.withUpdated(theme: theme) }), style: style, currentTime: selectedTime, dismissByTapOutside: dismissByTapOutside, completion: { time in
let controller = ChatTimerScreen(context: component.context, updatedPresentationData: (component.context.sharedContext.currentPresentationData.with({ $0 }).withUpdated(theme: theme), component.context.sharedContext.presentationData |> map { $0.withUpdated(theme: theme) }), style: style, currentTime: selectedTime, completion: { time in
completion(time)
})
view.endEditing(true)

View file

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 503 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 782 B

View file

@ -1,22 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "CallCancelIcon@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "CallCancelIcon@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 644 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 814 B

View file

@ -1,22 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "CallRouteBluetooth@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "CallRouteBluetooth@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View file

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

View file

@ -1,22 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "submodules_TelegramUI_Images.xcassets_Call_CallRouteSpeaker.imageset_CallRouteSpeaker@2x_Before_b542dc3fd7b381de80e554286a94ccd5b8d02154.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "submodules_TelegramUI_Images.xcassets_Call_CallRouteSpeaker.imageset_CallRouteSpeaker@3x_Before_c8c1c96f16a3977d2a6d1956a0aeb31768c6bb23.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,177 +0,0 @@
%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 3.334961 3.205170 cm
0.000000 0.000000 0.000000 scn
1.135289 17.265064 m
0.875590 17.524763 0.454536 17.524763 0.194837 17.265064 c
-0.064862 17.005365 -0.064862 16.584312 0.194837 16.324614 c
16.194838 0.324612 l
16.454536 0.064913 16.875591 0.064913 17.135290 0.324612 c
17.394989 0.584311 17.394989 1.005365 17.135290 1.265064 c
15.270563 3.129791 l
15.665111 3.129791 l
16.032377 3.129791 16.330109 3.427522 16.330109 3.794791 c
16.330109 4.162061 16.032377 4.459791 15.665111 4.459791 c
13.940563 4.459791 l
7.330003 11.070351 l
7.330003 12.694838 l
7.330004 12.718859 l
7.330019 12.978289 7.330032 13.211649 7.314171 13.405788 c
7.297186 13.613665 7.258753 13.834405 7.148529 14.050732 c
6.988900 14.364021 6.734188 14.618734 6.420897 14.778363 c
6.204570 14.888588 5.983830 14.927021 5.775954 14.944005 c
5.581833 14.959866 5.348500 14.959853 5.089100 14.959841 c
5.089095 14.959841 l
5.089057 14.959841 l
5.089017 14.959841 l
5.065003 14.959841 l
3.440514 14.959841 l
1.135289 17.265064 l
h
4.770516 13.629837 m
6.000003 12.400351 l
6.000003 12.694838 l
6.000003 12.985837 5.999486 13.164092 5.988588 13.297483 c
5.983510 13.359637 5.977127 13.397297 5.971728 13.420219 c
5.969160 13.431128 5.967000 13.437864 5.965689 13.441540 c
5.964900 13.443751 5.964303 13.445174 5.963926 13.446011 c
5.963701 13.446509 5.963554 13.446799 5.963490 13.446924 c
5.931373 13.509958 5.880125 13.561207 5.817090 13.593325 c
5.816755 13.593495 5.815236 13.594263 5.811705 13.595523 c
5.808031 13.596835 5.801293 13.598994 5.790386 13.601562 c
5.767462 13.606961 5.729803 13.613344 5.667649 13.618422 c
5.534258 13.629320 5.356003 13.629837 5.065003 13.629837 c
4.770516 13.629837 l
h
0.181478 14.050732 m
0.267737 14.220026 0.381761 14.372214 0.517790 14.501538 c
1.459741 13.559587 l
1.420951 13.529512 1.389032 13.491115 1.366516 13.446924 c
1.366346 13.446590 1.365578 13.445070 1.364318 13.441540 c
1.363006 13.437864 1.360847 13.431128 1.358278 13.420219 c
1.352880 13.397297 1.346497 13.359637 1.341419 13.297483 c
1.330521 13.164092 1.330003 12.985837 1.330003 12.694838 c
1.330003 9.894837 l
1.330003 9.603838 1.330521 9.425583 1.341419 9.292192 c
1.346497 9.230038 1.352880 9.192378 1.358278 9.169455 c
1.360847 9.158547 1.363006 9.151810 1.364318 9.148135 c
1.365578 9.144605 1.366346 9.143085 1.366516 9.142751 c
1.398634 9.079716 1.449882 9.028467 1.512917 8.996350 c
1.513251 8.996180 1.514771 8.995412 1.518302 8.994151 c
1.521976 8.992840 1.528713 8.990681 1.539621 8.988112 c
1.562544 8.982714 1.600204 8.976331 1.662358 8.971252 c
1.795749 8.960355 1.974004 8.959837 2.265003 8.959837 c
5.065003 8.959837 l
5.356003 8.959837 5.534258 8.960355 5.667649 8.971252 c
5.729803 8.976331 5.767462 8.982714 5.790386 8.988112 c
5.801293 8.990681 5.808031 8.992840 5.811705 8.994151 c
5.815236 8.995412 5.816755 8.996180 5.817090 8.996350 c
5.861280 9.018866 5.899678 9.050784 5.929753 9.089574 c
6.871704 8.147623 l
6.742380 8.011595 6.590191 7.897571 6.420897 7.811312 c
6.204570 7.701087 5.983830 7.662654 5.775953 7.645670 c
5.581820 7.629809 5.348469 7.629822 5.089050 7.629836 c
5.089025 7.629836 l
5.065003 7.629837 l
2.265003 7.629837 l
2.240981 7.629836 l
2.240957 7.629836 l
1.981538 7.629822 1.748187 7.629809 1.554053 7.645670 c
1.346177 7.662654 1.125436 7.701087 0.909109 7.811312 c
0.595819 7.970941 0.341107 8.225653 0.181478 8.538943 c
0.071253 8.755270 0.032820 8.976010 0.015836 9.183887 c
-0.000024 9.378011 -0.000013 9.611347 0.000001 9.870750 c
0.000001 9.870787 l
0.000001 9.870823 l
0.000001 9.894837 l
0.000001 12.694838 l
0.000001 12.718851 l
0.000001 12.718889 l
0.000001 12.718924 l
-0.000013 12.978327 -0.000024 13.211664 0.015836 13.405788 c
0.032820 13.613665 0.071253 13.834405 0.181478 14.050732 c
h
1.665110 4.459791 m
10.559536 4.459791 l
11.889536 3.129791 l
1.665110 3.129791 l
1.297841 3.129791 1.000110 3.427522 1.000110 3.794791 c
1.000110 4.162061 1.297841 4.459791 1.665110 4.459791 c
h
10.665111 14.459792 m
10.297841 14.459792 10.000111 14.162062 10.000111 13.794792 c
10.000111 13.427523 10.297841 13.129791 10.665111 13.129791 c
15.665111 13.129791 l
16.032377 13.129791 16.330109 13.427523 16.330109 13.794792 c
16.330109 14.162062 16.032377 14.459792 15.665111 14.459792 c
10.665111 14.459792 l
h
12.665111 9.459791 m
12.297841 9.459791 12.000111 9.162061 12.000111 8.794791 c
12.000111 8.427522 12.297841 8.129791 12.665111 8.129791 c
15.665111 8.129791 l
16.032377 8.129791 16.330109 8.427522 16.330109 8.794791 c
16.330109 9.162061 16.032377 9.459791 15.665111 9.459791 c
12.665111 9.459791 l
h
f*
n
Q
endstream
endobj
3 0 obj
4618
endobj
4 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 24.000000 24.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
0000004708 00000 n
0000004731 00000 n
0000004904 00000 n
0000004978 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
5037
%%EOF

View file

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

View file

@ -1,169 +0,0 @@
%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 3.334961 6.334900 cm
0.000000 0.000000 0.000000 scn
2.265003 11.830077 m
2.240989 11.830077 l
2.240949 11.830077 l
1.981532 11.830091 1.748184 11.830104 1.554052 11.814242 c
1.346176 11.797258 1.125435 11.758825 0.909108 11.648602 c
0.595819 11.488972 0.341106 11.234260 0.181477 10.920970 c
0.071253 10.704642 0.032820 10.483902 0.015835 10.276026 c
-0.000026 10.081894 -0.000013 9.848544 0.000001 9.589127 c
0.000001 9.589089 l
0.000001 9.565076 l
0.000001 6.765075 l
0.000001 6.741061 l
0.000001 6.741024 l
-0.000013 6.481606 -0.000026 6.248257 0.015835 6.054125 c
0.032820 5.846249 0.071253 5.625508 0.181477 5.409181 c
0.341106 5.095891 0.595819 4.841178 0.909108 4.681550 c
1.125435 4.571325 1.346176 4.532892 1.554052 4.515908 c
1.748192 4.500046 1.981551 4.500060 2.240980 4.500074 c
2.265002 4.500075 l
5.065003 4.500075 l
5.089025 4.500074 l
5.348454 4.500060 5.581814 4.500046 5.775953 4.515908 c
5.983829 4.532892 6.204570 4.571325 6.420897 4.681550 c
6.734187 4.841178 6.988900 5.095891 7.148529 5.409181 c
7.258753 5.625508 7.297186 5.846249 7.314170 6.054125 c
7.330032 6.248264 7.330019 6.481624 7.330004 6.741053 c
7.330003 6.765075 l
7.330003 9.565075 l
7.330004 9.589098 l
7.330019 9.848527 7.330032 10.081886 7.314170 10.276026 c
7.297186 10.483902 7.258753 10.704642 7.148529 10.920970 c
6.988900 11.234260 6.734187 11.488972 6.420897 11.648602 c
6.204570 11.758825 5.983829 11.797258 5.775953 11.814242 c
5.581822 11.830104 5.348474 11.830091 5.089057 11.830077 c
5.089017 11.830077 l
5.065003 11.830077 l
2.265003 11.830077 l
h
1.512916 10.463563 m
1.513250 10.463733 1.514770 10.464500 1.518301 10.465761 c
1.521975 10.467072 1.528712 10.469232 1.539620 10.471801 c
1.562544 10.477199 1.600203 10.483582 1.662357 10.488660 c
1.795748 10.499558 1.974003 10.500075 2.265003 10.500075 c
5.065003 10.500075 l
5.356002 10.500075 5.534257 10.499558 5.667649 10.488660 c
5.729803 10.483582 5.767462 10.477199 5.790385 10.471801 c
5.801293 10.469232 5.808030 10.467072 5.811704 10.465761 c
5.815235 10.464500 5.816755 10.463733 5.817090 10.463563 c
5.880124 10.431445 5.931373 10.380197 5.963490 10.317163 c
5.963660 10.316828 5.964428 10.315308 5.965689 10.311777 c
5.967000 10.308103 5.969159 10.301366 5.971728 10.290458 c
5.977127 10.267534 5.983509 10.229876 5.988587 10.167721 c
5.999485 10.034330 6.000003 9.856074 6.000003 9.565075 c
6.000003 6.765075 l
6.000003 6.474076 5.999485 6.295821 5.988587 6.162429 c
5.983509 6.100276 5.977127 6.062616 5.971728 6.039693 c
5.969159 6.028785 5.967000 6.022048 5.965689 6.018374 c
5.964428 6.014843 5.963660 6.013323 5.963490 6.012989 c
5.931373 5.949954 5.880124 5.898705 5.817090 5.866588 c
5.816755 5.866418 5.815235 5.865650 5.811705 5.864389 c
5.808030 5.863078 5.801293 5.860919 5.790385 5.858350 c
5.767462 5.852952 5.729803 5.846569 5.667649 5.841491 c
5.534257 5.830593 5.356002 5.830075 5.065003 5.830075 c
2.265002 5.830075 l
1.974003 5.830075 1.795748 5.830593 1.662357 5.841491 c
1.600203 5.846569 1.562544 5.852952 1.539620 5.858350 c
1.528712 5.860919 1.521975 5.863078 1.518301 5.864389 c
1.514770 5.865650 1.513250 5.866418 1.512916 5.866588 c
1.449882 5.898705 1.398633 5.949954 1.366516 6.012989 c
1.366345 6.013323 1.365577 6.014843 1.364317 6.018373 c
1.363005 6.022048 1.360846 6.028785 1.358277 6.039693 c
1.352879 6.062616 1.346496 6.100276 1.341418 6.162429 c
1.330520 6.295821 1.330003 6.474076 1.330003 6.765075 c
1.330003 9.565076 l
1.330003 9.856075 1.330520 10.034330 1.341418 10.167721 c
1.346496 10.229876 1.352879 10.267534 1.358277 10.290458 c
1.360846 10.301366 1.363005 10.308103 1.364317 10.311777 c
1.365577 10.315308 1.366345 10.316828 1.366516 10.317163 c
1.398633 10.380197 1.449882 10.431445 1.512916 10.463563 c
h
10.665110 11.330029 m
10.297840 11.330029 10.000110 11.032299 10.000110 10.665030 c
10.000110 10.297760 10.297840 10.000030 10.665110 10.000030 c
15.665110 10.000030 l
16.032377 10.000030 16.330109 10.297760 16.330109 10.665030 c
16.330109 11.032299 16.032377 11.330029 15.665110 11.330029 c
10.665110 11.330029 l
h
10.665110 6.330029 m
10.297840 6.330029 10.000110 6.032299 10.000110 5.665030 c
10.000110 5.297760 10.297840 5.000030 10.665110 5.000030 c
15.665110 5.000030 l
16.032377 5.000030 16.330109 5.297760 16.330109 5.665030 c
16.330109 6.032299 16.032377 6.330029 15.665110 6.330029 c
10.665110 6.330029 l
h
1.000109 0.665030 m
1.000109 1.032299 1.297840 1.330029 1.665109 1.330029 c
15.665110 1.330029 l
16.032377 1.330029 16.330109 1.032299 16.330109 0.665030 c
16.330109 0.297760 16.032377 0.000030 15.665110 0.000030 c
1.665109 0.000030 l
1.297840 0.000030 1.000109 0.297760 1.000109 0.665030 c
h
f*
n
Q
endstream
endobj
3 0 obj
4706
endobj
4 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 24.000000 24.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
0000004796 00000 n
0000004819 00000 n
0000004992 00000 n
0000005066 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
5125
%%EOF

View file

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

View file

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

View file

@ -1,169 +0,0 @@
%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 3.835083 3.834961 cm
0.000000 0.000000 0.000000 scn
5.436178 16.330017 m
5.465000 16.330017 l
10.865000 16.330017 l
10.893822 16.330017 l
11.709461 16.330023 12.362126 16.330027 12.889546 16.286936 c
13.430926 16.242702 13.898637 16.149773 14.328876 15.930555 c
15.018489 15.579180 15.579163 15.018506 15.930539 14.328892 c
16.149757 13.898653 16.242687 13.430943 16.286919 12.889563 c
16.330009 12.362154 16.330006 11.709505 16.330000 10.893888 c
16.330000 10.893824 l
16.330000 10.865017 l
16.330000 5.465017 l
16.330000 5.436212 l
16.330000 5.436146 l
16.330006 4.620529 16.330009 3.967880 16.286919 3.440471 c
16.242687 2.899091 16.149757 2.431380 15.930539 2.001142 c
15.579163 1.311528 15.018489 0.750854 14.328876 0.399478 c
13.898637 0.180260 13.430927 0.087330 12.889546 0.043098 c
12.362138 0.000008 11.709489 0.000011 10.893871 0.000017 c
10.893806 0.000017 l
10.865000 0.000017 l
5.465000 0.000017 l
5.436194 0.000017 l
5.436130 0.000017 l
4.620512 0.000011 3.967863 0.000008 3.440454 0.043098 c
2.899074 0.087330 2.431364 0.180260 2.001125 0.399478 c
1.311511 0.750854 0.750837 1.311528 0.399461 2.001142 c
0.180244 2.431380 0.087314 2.899090 0.043081 3.440471 c
-0.000010 3.967890 -0.000006 4.620555 0.000000 5.436195 c
0.000000 5.465017 l
0.000000 10.865017 l
0.000000 10.893839 l
-0.000006 11.709478 -0.000010 12.362144 0.043081 12.889563 c
0.087314 13.430943 0.180244 13.898653 0.399461 14.328892 c
0.750837 15.018506 1.311511 15.579180 2.001125 15.930555 c
2.431364 16.149773 2.899074 16.242702 3.440454 16.286936 c
3.967873 16.330027 4.620538 16.330023 5.436178 16.330017 c
h
3.548759 14.961352 m
3.089627 14.923841 2.816429 14.853280 2.604933 14.745517 c
2.165574 14.521652 1.808364 14.164443 1.584500 13.725084 c
1.476737 13.513588 1.406177 13.240391 1.368664 12.781259 c
1.330518 12.314363 1.330000 11.716068 1.330000 10.865017 c
1.330000 5.465017 l
1.330000 4.613965 1.330518 4.015671 1.368664 3.548775 c
1.406177 3.089643 1.476737 2.816445 1.584500 2.604949 c
1.808364 2.165591 2.165574 1.808381 2.604933 1.584517 c
2.816429 1.476754 3.089627 1.406194 3.548759 1.368681 c
4.015654 1.330534 4.613948 1.330017 5.465000 1.330017 c
10.865000 1.330017 l
11.716052 1.330017 12.314346 1.330534 12.781242 1.368681 c
13.240374 1.406194 13.513572 1.476754 13.725068 1.584517 c
14.164426 1.808381 14.521636 2.165591 14.745501 2.604949 c
14.853263 2.816445 14.923823 3.089643 14.961336 3.548776 c
14.999483 4.015671 15.000000 4.613965 15.000000 5.465017 c
15.000000 10.865017 l
15.000000 11.716068 14.999483 12.314363 14.961336 12.781259 c
14.923823 13.240391 14.853263 13.513588 14.745501 13.725084 c
14.521636 14.164443 14.164426 14.521652 13.725068 14.745517 c
13.513572 14.853280 13.240374 14.923841 12.781241 14.961352 c
12.314346 14.999499 11.716052 15.000017 10.865000 15.000017 c
5.465000 15.000017 l
4.613948 15.000017 4.015654 14.999499 3.548759 14.961352 c
h
7.829878 12.164894 m
7.829878 12.532164 7.532147 12.829895 7.164878 12.829895 c
6.797609 12.829895 6.499878 12.532164 6.499878 12.164894 c
6.499878 10.770347 l
4.635104 12.635120 l
4.375406 12.894819 3.954351 12.894819 3.694653 12.635120 c
3.434954 12.375422 3.434954 11.954367 3.694653 11.694669 c
5.559426 9.829895 l
4.164878 9.829895 l
3.797609 9.829895 3.499878 9.532164 3.499878 9.164894 c
3.499878 8.797626 3.797609 8.499895 4.164878 8.499895 c
7.148878 8.499895 l
7.153147 8.499901 l
7.157188 8.499939 l
7.329931 8.497953 7.503299 8.562863 7.635104 8.694669 c
7.766910 8.826473 7.831820 8.999842 7.829834 9.172585 c
7.829872 9.176626 l
7.829878 9.180895 l
7.829878 12.164894 l
h
9.164833 3.499878 m
8.797565 3.499878 8.499834 3.797609 8.499834 4.164879 c
8.499834 7.148878 l
8.499840 7.153147 l
8.499878 7.157188 l
8.497892 7.329931 8.562802 7.503300 8.694608 7.635104 c
8.826412 7.766910 8.999781 7.831820 9.172523 7.829834 c
9.176565 7.829872 l
9.180834 7.829878 l
12.164833 7.829878 l
12.532103 7.829878 12.829834 7.532147 12.829834 7.164879 c
12.829834 6.797609 12.532103 6.499878 12.164833 6.499878 c
10.770286 6.499878 l
12.635059 4.635104 l
12.894758 4.375405 12.894758 3.954351 12.635059 3.694653 c
12.375360 3.434954 11.954307 3.434954 11.694608 3.694653 c
9.829834 5.559426 l
9.829834 4.164879 l
9.829834 3.797609 9.532103 3.499878 9.164833 3.499878 c
h
f*
n
Q
endstream
endobj
3 0 obj
4327
endobj
4 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 24.000000 24.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
0000004417 00000 n
0000004440 00000 n
0000004613 00000 n
0000004687 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
4746
%%EOF

View file

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

View file

@ -1,12 +0,0 @@
{
"images" : [
{
"filename" : "Size=24px, Type=Crossed Out.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View file

@ -1,165 +0,0 @@
%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.834961 4.361450 cm
0.000000 0.000000 0.000000 scn
0.294029 13.569108 m
0.148725 13.203500 0.079447 12.808213 0.043083 12.363134 c
-0.000009 11.835724 -0.000005 11.183071 0.000001 10.367449 c
0.000001 10.367412 l
0.000001 10.338589 l
0.000001 2.887971 l
0.000001 2.855927 l
0.000001 2.855909 l
-0.000013 2.361413 -0.000024 1.944829 0.029606 1.619491 c
0.058879 1.298060 0.124788 0.933573 0.357819 0.638192 c
0.669126 0.243593 1.142026 0.010736 1.644602 0.004579 c
2.020809 -0.000031 2.349897 0.169960 2.622518 0.342736 c
2.898462 0.517618 3.228661 0.771631 3.620616 1.073153 c
3.645996 1.092677 l
6.594922 3.361081 l
6.992292 3.666750 7.044882 3.691571 7.078142 3.700500 c
7.135041 3.715775 7.194962 3.715775 7.251861 3.700500 c
7.285121 3.691571 7.337711 3.666750 7.735081 3.361081 c
10.684008 1.092677 l
10.709353 1.073179 l
11.101323 0.771646 11.431534 0.517624 11.707485 0.342736 c
11.980106 0.169960 12.309195 -0.000031 12.685401 0.004579 c
13.008502 0.008537 13.319336 0.106193 13.582854 0.280283 c
12.355464 1.507673 l
12.146183 1.646584 11.878798 1.851580 11.494923 2.146868 c
8.545997 4.415272 l
8.477973 4.467776 l
8.477962 4.467785 l
8.199948 4.682729 7.921870 4.897722 7.596705 4.985017 c
7.313910 5.060937 7.016093 5.060937 6.733298 4.985017 c
6.408127 4.897721 6.130046 4.682723 5.852028 4.467772 c
5.784007 4.415271 l
2.835081 2.146868 l
2.410956 1.820618 2.129028 1.604588 1.910557 1.466129 c
1.735109 1.354937 1.664445 1.337146 1.654627 1.334675 c
1.654414 1.334620 l
1.557878 1.337669 1.467334 1.382254 1.406059 1.456912 c
1.405972 1.457113 l
1.401946 1.466402 1.372963 1.533260 1.354124 1.740117 c
1.330665 1.997703 1.330002 2.352881 1.330002 2.887971 c
1.330002 10.338589 l
1.330002 11.189641 1.330519 11.787935 1.368666 12.254830 c
1.375014 12.332534 1.382310 12.404911 1.390571 12.472566 c
0.294029 13.569108 l
h
12.999968 2.744075 m
12.999996 2.790545 13.000002 2.838489 13.000002 2.887970 c
13.000002 10.338589 l
13.000002 11.189640 12.999485 11.787935 12.961338 12.254830 c
12.923825 12.713963 12.853265 12.987160 12.745502 13.198656 c
12.521638 13.638015 12.164428 13.995224 11.725070 14.219089 c
11.513574 14.326852 11.240376 14.397411 10.781243 14.434924 c
10.314348 14.473071 9.716053 14.473588 8.865002 14.473588 c
5.465002 14.473588 l
4.613950 14.473588 4.015655 14.473071 3.548759 14.434924 c
3.089628 14.397411 2.816430 14.326852 2.604934 14.219089 c
2.372593 14.100705 2.163225 13.945032 1.984401 13.759640 c
1.043852 14.700190 l
1.320836 14.983611 1.643658 15.221989 2.001126 15.404127 c
2.431365 15.623345 2.899075 15.716275 3.440455 15.760508 c
3.967874 15.803599 4.620536 15.803595 5.436175 15.803589 c
5.436180 15.803589 l
5.465002 15.803589 l
8.865002 15.803589 l
8.893824 15.803589 l
9.709463 15.803595 10.362128 15.803599 10.889548 15.760508 c
11.430928 15.716275 11.898639 15.623345 12.328877 15.404127 c
13.018491 15.052752 13.579165 14.492078 13.930541 13.802464 c
14.149758 13.372225 14.242688 12.904515 14.286921 12.363134 c
14.330012 11.835714 14.330008 11.183048 14.330002 10.367406 c
14.330002 10.367395 l
14.330002 10.338589 l
14.330002 2.887970 l
14.330002 2.855918 l
14.330016 2.361417 14.330028 1.944830 14.300398 1.619491 c
14.295680 1.567688 14.290010 1.514769 14.282844 1.461199 c
12.999968 2.744075 l
h
f*
n
Q
q
1.000000 0.000000 -0.000000 1.000000 4.500000 3.540039 cm
0.000000 0.000000 0.000000 scn
0.470226 17.930187 m
0.210527 18.189886 -0.210527 18.189886 -0.470226 17.930187 c
-0.729925 17.670488 -0.729925 17.249434 -0.470226 16.989735 c
0.470226 17.930187 l
h
15.529774 0.989735 m
15.789473 0.730036 16.210527 0.730036 16.470226 0.989735 c
16.729925 1.249434 16.729925 1.670488 16.470226 1.930187 c
15.529774 0.989735 l
h
-0.470226 16.989735 m
15.529774 0.989735 l
16.470226 1.930187 l
0.470226 17.930187 l
-0.470226 16.989735 l
h
f
n
Q
endstream
endobj
3 0 obj
3871
endobj
4 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 24.000000 24.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
0000003961 00000 n
0000003984 00000 n
0000004157 00000 n
0000004231 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
4290
%%EOF

View file

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

View file

@ -1,112 +0,0 @@
%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 3.334961 1.270081 cm
0.000000 0.000000 0.000000 scn
6.330028 15.229959 m
6.330028 16.519543 7.375443 17.564959 8.665028 17.564959 c
9.954613 17.564959 11.000028 16.519543 11.000028 15.229959 c
11.000028 13.940373 9.954613 12.894958 8.665028 12.894958 c
7.375443 12.894958 6.330028 13.940373 6.330028 15.229959 c
h
8.665028 18.894958 m
6.640904 18.894958 5.000028 17.254082 5.000028 15.229959 c
5.000028 13.205835 6.640904 11.564959 8.665028 11.564959 c
10.689151 11.564959 12.330028 13.205835 12.330028 15.229959 c
12.330028 17.254082 10.689151 18.894958 8.665028 18.894958 c
h
2.847365 5.874736 m
3.182212 6.620716 3.727596 7.408447 4.622032 8.012360 c
5.052609 8.303081 5.574740 8.558434 6.209703 8.744807 c
5.164166 9.790345 l
4.686711 9.600591 4.259488 9.372349 3.877790 9.114632 c
2.736064 8.343752 2.047248 7.340033 1.633996 6.419378 c
1.238339 5.537922 1.434021 4.662781 1.966020 4.035870 c
2.481754 3.428125 3.295742 3.064959 4.165028 3.064959 c
11.889552 3.064959 l
10.559552 4.394958 l
4.165028 4.394958 l
3.653601 4.394958 3.222711 4.610523 2.980097 4.896420 c
2.753749 5.163151 2.677613 5.496559 2.847365 5.874736 c
h
14.796587 3.538785 m
17.135227 1.200146 l
17.394926 0.940447 17.394926 0.519392 17.135227 0.259693 c
16.875528 -0.000006 16.454473 -0.000006 16.194775 0.259693 c
0.194774 16.259693 l
-0.064925 16.519392 -0.064925 16.940447 0.194774 17.200146 c
0.454473 17.459845 0.875527 17.459845 1.135226 17.200146 c
7.960464 10.374907 l
8.188262 10.388149 8.423051 10.394958 8.665028 10.394958 c
10.754458 10.394958 12.307954 9.887258 13.452266 9.114632 c
14.593992 8.343751 15.282808 7.340032 15.696060 6.419377 c
16.091717 5.537921 15.896035 4.662780 15.364036 4.035870 c
15.201860 3.844761 15.010192 3.677837 14.796587 3.538785 c
h
13.815245 4.520127 m
14.036389 4.610582 14.220131 4.743431 14.349958 4.896420 c
14.576306 5.163150 14.652442 5.496557 14.482691 5.874735 c
14.147844 6.620715 13.602460 7.408447 12.708024 8.012359 c
11.919037 8.545074 10.822649 8.959038 9.287930 9.047441 c
13.815245 4.520127 l
h
f*
n
Q
endstream
endobj
3 0 obj
2105
endobj
4 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 24.000000 24.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
0000002195 00000 n
0000002218 00000 n
0000002391 00000 n
0000002465 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
2524
%%EOF

View file

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

View file

@ -1,188 +0,0 @@
%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 120.000000 120.000000 ]
>>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 26.666748 23.947998 cm
0.000000 0.000000 0.000000 scn
33.333332 67.118652 m
51.742825 67.118652 66.666664 53.551525 66.666664 36.815620 c
66.666664 20.079723 51.742825 6.512592 33.333332 6.512592 c
30.510870 6.512592 27.770340 6.831497 25.152962 7.431835 c
24.657856 7.545395 24.095694 7.026123 23.157236 6.159271 c
22.022297 5.110928 20.337004 3.554222 17.554379 1.993690 c
13.999221 -0.000084 9.073529 0.172890 8.239902 0.522552 c
7.440670 0.857796 8.055842 1.524185 9.139198 2.697731 c
9.888692 3.509621 10.862268 4.564251 11.746614 5.919903 c
13.909238 9.235085 13.015616 13.181854 12.045396 13.892178 c
4.458577 19.446659 0.000000 27.270615 0.000000 36.815620 c
0.000000 53.551525 14.923841 67.118652 33.333332 67.118652 c
h
25.627058 49.241592 m
26.466211 54.000668 31.004473 57.178391 35.763550 56.339237 c
40.522621 55.500084 43.700348 50.961823 42.861195 46.202747 c
41.652504 39.347935 l
42.190289 39.251141 42.644272 39.108437 43.057198 38.898041 c
44.186165 38.322800 45.104050 37.404915 45.679291 36.275944 c
46.333252 34.992474 46.333252 33.312317 46.333252 29.952000 c
46.333252 28.152000 l
46.333252 24.791687 46.333252 23.111526 45.679291 21.828056 c
45.104050 20.699085 44.186165 19.781200 43.057198 19.205959 c
41.773727 18.552002 40.093567 18.552002 36.733253 18.552002 c
29.933254 18.552002 l
26.572937 18.552002 24.892780 18.552002 23.609308 19.205959 c
22.480337 19.781200 21.562452 20.699085 20.987213 21.828056 c
20.333252 23.111526 20.333252 24.791687 20.333252 28.152000 c
20.333252 29.952000 l
20.333252 33.312317 20.333252 34.992474 20.987213 36.275944 c
21.562452 37.404915 22.480337 38.322800 23.609308 38.898041 c
24.892780 39.552002 26.572937 39.552002 29.933252 39.552002 c
36.733253 39.552002 l
37.045204 39.552002 37.342670 39.552002 37.626686 39.551476 c
38.921963 46.897339 l
39.377502 49.480839 37.652451 51.944466 35.068954 52.400005 c
32.485458 52.855545 30.021830 51.130497 29.566288 48.546997 c
29.436054 47.808395 l
29.244247 46.720604 28.206930 45.994267 27.119141 46.186073 c
26.031353 46.377880 25.305016 47.415199 25.496822 48.502983 c
25.627058 49.241592 l
h
f*
n
Q
endstream
endobj
2 0 obj
2182
endobj
3 0 obj
<< /Type /XObject
/Length 4 0 R
/Group << /Type /Group
/S /Transparency
>>
/Subtype /Form
/Resources << >>
/BBox [ 0.000000 0.000000 120.000000 120.000000 ]
>>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 10.000000 9.000000 cm
0.000000 0.000000 0.000000 scn
0.000000 62.666668 m
0.000000 75.734558 0.000000 82.268509 2.543181 87.259781 c
4.780226 91.650230 8.349772 95.219772 12.740221 97.456818 c
17.731495 100.000000 24.265440 100.000000 37.333332 100.000000 c
62.666668 100.000000 l
75.734558 100.000000 82.268509 100.000000 87.259781 97.456818 c
91.650230 95.219772 95.219772 91.650230 97.456818 87.259781 c
100.000000 82.268509 100.000000 75.734558 100.000000 62.666668 c
100.000000 37.333332 l
100.000000 24.265442 100.000000 17.731491 97.456818 12.740219 c
95.219772 8.349770 91.650230 4.780228 87.259781 2.543182 c
82.268509 0.000000 75.734558 0.000000 62.666668 0.000000 c
37.333332 0.000000 l
24.265440 0.000000 17.731495 0.000000 12.740221 2.543182 c
8.349772 4.780228 4.780226 8.349770 2.543181 12.740219 c
0.000000 17.731491 0.000000 24.265442 0.000000 37.333332 c
0.000000 62.666668 l
h
f
n
Q
endstream
endobj
4 0 obj
969
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 120.000000 120.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
0000002442 00000 n
0000002465 00000 n
0000003684 00000 n
0000003706 00000 n
0000004004 00000 n
0000004106 00000 n
0000004127 00000 n
0000004302 00000 n
0000004376 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 10 0 R
/Size 11
>>
startxref
4436
%%EOF

View file

@ -1,15 +0,0 @@
{
"images" : [
{
"filename" : "search_24.svg",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}

View file

@ -1,3 +0,0 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.62997 10.8C5.62997 7.94466 7.94466 5.62997 10.8 5.62997C13.6553 5.62997 15.97 7.94466 15.97 10.8C15.97 13.6553 13.6553 15.97 10.8 15.97C7.94466 15.97 5.62997 13.6553 5.62997 10.8ZM10.8 3.96997C7.02787 3.96997 3.96997 7.02787 3.96997 10.8C3.96997 14.5721 7.02787 17.63 10.8 17.63C12.3869 17.63 13.8474 17.0888 15.007 16.1808L19.0131 20.1869C19.3372 20.511 19.8627 20.511 20.1869 20.1869C20.511 19.8627 20.511 19.3372 20.1869 19.0131L16.1808 15.007C17.0888 13.8474 17.63 12.3869 17.63 10.8C17.63 7.02787 14.5721 3.96997 10.8 3.96997Z" fill="black"/>
</svg>

Before

Width:  |  Height:  |  Size: 703 B

View file

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

View file

@ -1,3 +0,0 @@
<svg width="20" height="19" viewBox="0 0 20 19" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 6.38149C0 2.7012 2.58801 0 5.93594 0C7.57828 0 8.89997 0.716446 9.8327 1.8139C10.7705 0.713816 12.0873 0 13.733 0C17.0827 0 19.66 2.70315 19.66 6.38149C19.66 10.6522 16.1276 14.6289 11.1081 17.8615L11.1028 17.8649L11.1028 17.8649C10.9482 17.9628 10.7605 18.0706 10.5643 18.1566C10.3861 18.2347 10.1191 18.3323 9.83 18.3323C9.54201 18.3323 9.27489 18.2322 9.1024 18.1566C8.90939 18.072 8.72217 17.9661 8.56756 17.8713L8.55189 17.8615C3.5324 14.6289 0 10.6522 0 6.38149ZM5.93594 1.66C3.59872 1.66 1.66 3.52118 1.66 6.38149C1.66 9.73665 4.5047 13.2787 9.44262 16.4607C9.56146 16.5332 9.67441 16.5948 9.76899 16.6363C9.79464 16.6476 9.81597 16.656 9.83309 16.6622C9.85032 16.6561 9.87184 16.6477 9.8977 16.6363C9.99044 16.5957 10.1003 16.5348 10.2121 16.464C15.1533 13.2813 18 9.73784 18 6.38149C18 3.51923 16.0684 1.66 13.733 1.66C12.3189 1.66 11.2438 2.42182 10.5587 3.67794C10.4127 3.94548 10.1319 4.11154 9.82715 4.11049C9.5224 4.10944 9.24273 3.94147 9.09864 3.67293C8.43221 2.43095 7.35055 1.66 5.93594 1.66ZM9.87749 16.6759C9.87744 16.6759 9.87681 16.6758 9.8756 16.6756Z" fill="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

View file

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

View file

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

View file

@ -1,236 +0,0 @@
%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 8.500000 7.040154 cm
0.000000 0.000000 0.000000 scn
-0.470226 1.930072 m
-0.729925 1.670374 -0.729925 1.249319 -0.470226 0.989621 c
-0.210527 0.729922 0.210527 0.729922 0.470226 0.989621 c
-0.470226 1.930072 l
h
6.470226 6.989621 m
6.729925 7.249319 6.729925 7.670374 6.470226 7.930072 c
6.210527 8.189772 5.789473 8.189772 5.529774 7.930072 c
6.470226 6.989621 l
h
0.470226 0.989621 m
6.470226 6.989621 l
5.529774 7.930072 l
-0.470226 1.930072 l
0.470226 0.989621 l
h
f
n
Q
q
1.000000 0.000000 -0.000000 1.000000 9.500000 8.170006 cm
0.000000 0.000000 0.000000 scn
0.000000 6.994994 m
-0.367269 6.994994 -0.665000 6.697264 -0.665000 6.329994 c
-0.665000 5.962725 -0.367269 5.664994 0.000000 5.664994 c
0.000000 6.994994 l
h
5.000000 6.329994 m
5.665000 6.329994 l
5.665000 6.697264 5.367270 6.994994 5.000000 6.994994 c
5.000000 6.329994 l
h
4.335000 1.329994 m
4.335000 0.962725 4.632730 0.664994 5.000000 0.664994 c
5.367270 0.664994 5.665000 0.962725 5.665000 1.329994 c
4.335000 1.329994 l
h
0.000000 5.664994 m
5.000000 5.664994 l
5.000000 6.994994 l
0.000000 6.994994 l
0.000000 5.664994 l
h
4.335000 6.329994 m
4.335000 1.329994 l
5.665000 1.329994 l
5.665000 6.329994 l
4.335000 6.329994 l
h
f
n
Q
q
1.000000 0.000000 -0.000000 1.000000 3.000000 1.668968 cm
0.000000 0.000000 0.000000 scn
4.000000 10.666032 m
4.367270 10.666032 4.665000 10.963762 4.665000 11.331032 c
4.665000 11.698301 4.367270 11.996032 4.000000 11.996032 c
4.000000 10.666032 l
h
10.665000 5.331032 m
10.665000 5.698301 10.367270 5.996032 10.000000 5.996032 c
9.632730 5.996032 9.335000 5.698301 9.335000 5.331032 c
10.665000 5.331032 l
h
8.907981 1.549019 m
9.209885 0.956499 l
8.907981 1.549019 l
h
9.782013 2.423051 m
10.374533 2.121147 l
9.782013 2.423051 l
h
1.092019 11.113045 m
0.790115 11.705564 l
1.092019 11.113045 l
h
0.217987 10.239013 m
-0.374532 10.540916 l
0.217987 10.239013 l
h
4.000000 11.996032 m
3.200000 11.996032 l
3.200000 10.666032 l
4.000000 10.666032 l
4.000000 11.996032 l
h
-0.665000 8.131032 m
-0.665000 4.531032 l
0.665000 4.531032 l
0.665000 8.131032 l
-0.665000 8.131032 l
h
3.200000 0.666032 m
6.800000 0.666032 l
6.800000 1.996032 l
3.200000 1.996032 l
3.200000 0.666032 l
h
10.665000 4.531032 m
10.665000 5.331032 l
9.335000 5.331032 l
9.335000 4.531032 l
10.665000 4.531032 l
h
6.800000 0.666032 m
7.349080 0.666032 7.800883 0.665515 8.167748 0.695489 c
8.542377 0.726097 8.886601 0.791779 9.209885 0.956499 c
8.606077 2.141538 l
8.501536 2.088272 8.351824 2.044960 8.059443 2.021071 c
7.759301 1.996549 7.371026 1.996032 6.800000 1.996032 c
6.800000 0.666032 l
h
9.335000 4.531032 m
9.335000 3.960006 9.334483 3.571731 9.309960 3.271588 c
9.286072 2.979208 9.242760 2.829495 9.189494 2.724955 c
10.374533 2.121147 l
10.539253 2.444430 10.604935 2.788655 10.635543 3.163283 c
10.665517 3.530149 10.665000 3.981952 10.665000 4.531032 c
9.335000 4.531032 l
h
9.209885 0.956499 m
9.711337 1.212002 10.119030 1.619695 10.374533 2.121147 c
9.189494 2.724955 l
9.061502 2.473758 8.857274 2.269529 8.606077 2.141538 c
9.209885 0.956499 l
h
-0.665000 4.531032 m
-0.665000 3.981952 -0.665517 3.530149 -0.635543 3.163283 c
-0.604935 2.788655 -0.539253 2.444430 -0.374532 2.121147 c
0.810506 2.724955 l
0.757240 2.829495 0.713928 2.979208 0.690040 3.271588 c
0.665517 3.571731 0.665000 3.960006 0.665000 4.531032 c
-0.665000 4.531032 l
h
3.200000 1.996032 m
2.628974 1.996032 2.240699 1.996549 1.940556 2.021071 c
1.648176 2.044960 1.498463 2.088272 1.393923 2.141538 c
0.790115 0.956499 l
1.113398 0.791779 1.457623 0.726097 1.832252 0.695489 c
2.199117 0.665515 2.650921 0.666032 3.200000 0.666032 c
3.200000 1.996032 l
h
-0.374532 2.121147 m
-0.119030 1.619695 0.288663 1.212002 0.790115 0.956499 c
1.393923 2.141538 l
1.142726 2.269529 0.938497 2.473758 0.810506 2.724955 c
-0.374532 2.121147 l
h
3.200000 11.996032 m
2.650921 11.996032 2.199117 11.996549 1.832252 11.966575 c
1.457623 11.935966 1.113398 11.870285 0.790115 11.705564 c
1.393923 10.520525 l
1.498463 10.573792 1.648176 10.617104 1.940556 10.640992 c
2.240699 10.665515 2.628974 10.666032 3.200000 10.666032 c
3.200000 11.996032 l
h
0.665000 8.131032 m
0.665000 8.702057 0.665517 9.090332 0.690040 9.390476 c
0.713928 9.682856 0.757240 9.832568 0.810506 9.937109 c
-0.374532 10.540916 l
-0.539253 10.217633 -0.604935 9.873408 -0.635543 9.498780 c
-0.665517 9.131915 -0.665000 8.680111 -0.665000 8.131032 c
0.665000 8.131032 l
h
0.790115 11.705564 m
0.288663 11.450062 -0.119030 11.042369 -0.374532 10.540916 c
0.810506 9.937109 l
0.938497 10.188306 1.142726 10.392534 1.393923 10.520525 c
0.790115 11.705564 l
h
f
n
Q
endstream
endobj
3 0 obj
4659
endobj
4 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 16.000000 16.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
0000004749 00000 n
0000004772 00000 n
0000004945 00000 n
0000005019 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
5078
%%EOF

View file

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

Some files were not shown because too many files have changed in this diff Show more