Add Assets Color

Update public timeline cell's UI
add ActionToolBar
This commit is contained in:
sunxiaojian 2021-02-01 18:06:29 +08:00
parent 313ce3e54a
commit 7c19e569c9
48 changed files with 2897 additions and 98 deletions

View File

@ -10,6 +10,11 @@
2D04F42525C255B9003F936F /* APIService+PublicTimeline.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D04F42425C255B9003F936F /* APIService+PublicTimeline.swift */; };
2D152A8C25C295CC009AA50C /* TimelinePostView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D152A8B25C295CC009AA50C /* TimelinePostView.swift */; };
2D152A9225C2980C009AA50C /* UIFont.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D152A9125C2980C009AA50C /* UIFont.swift */; };
2D42FF6125C8177C004A627A /* ActiveLabel in Frameworks */ = {isa = PBXBuildFile; productRef = 2D42FF6025C8177C004A627A /* ActiveLabel */; };
2D42FF6B25C817D2004A627A /* MastodonContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D42FF6A25C817D2004A627A /* MastodonContent.swift */; };
2D42FF7E25C82218004A627A /* ActionToolBarContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D42FF7D25C82218004A627A /* ActionToolBarContainer.swift */; };
2D42FF8525C8224F004A627A /* HitTestExpandedButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D42FF8425C8224F004A627A /* HitTestExpandedButton.swift */; };
2D42FF8F25C8228A004A627A /* UIButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D42FF8E25C8228A004A627A /* UIButton.swift */; };
2D46975E25C2A54100CF4AA9 /* NSLayoutConstraint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D46975D25C2A54100CF4AA9 /* NSLayoutConstraint.swift */; };
2D46976425C2A71500CF4AA9 /* UIIamge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D46976325C2A71500CF4AA9 /* UIIamge.swift */; };
2D61335825C188A000CAE157 /* APIService+Persist+Timeline.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D61335725C188A000CAE157 /* APIService+Persist+Timeline.swift */; };
@ -26,7 +31,6 @@
2D927F0825C7E9A8004F19B8 /* Tag.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D927F0725C7E9A8004F19B8 /* Tag.swift */; };
2D927F0E25C7E9C9004F19B8 /* History.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D927F0D25C7E9C9004F19B8 /* History.swift */; };
2D927F1425C7EDD9004F19B8 /* Emoji.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D927F1325C7EDD9004F19B8 /* Emoji.swift */; };
2D9BB87B25C3FEF200678AB6 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D9BB87A25C3FEF200678AB6 /* String.swift */; };
2DF123A725C3B0210020F248 /* ActiveLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DF123A625C3B0210020F248 /* ActiveLabel.swift */; };
3533495136D843E85211E3E2 /* Pods_Mastodon_MastodonUITests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1B4523A7981F1044DE89C21 /* Pods_Mastodon_MastodonUITests.framework */; };
5D526FE225BE9AC400460CB9 /* MastodonSDK in Frameworks */ = {isa = PBXBuildFile; productRef = 5D526FE125BE9AC400460CB9 /* MastodonSDK */; };
@ -124,6 +128,10 @@
2D04F42425C255B9003F936F /* APIService+PublicTimeline.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+PublicTimeline.swift"; sourceTree = "<group>"; };
2D152A8B25C295CC009AA50C /* TimelinePostView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelinePostView.swift; sourceTree = "<group>"; };
2D152A9125C2980C009AA50C /* UIFont.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIFont.swift; sourceTree = "<group>"; };
2D42FF6A25C817D2004A627A /* MastodonContent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MastodonContent.swift; sourceTree = "<group>"; };
2D42FF7D25C82218004A627A /* ActionToolBarContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionToolBarContainer.swift; sourceTree = "<group>"; };
2D42FF8425C8224F004A627A /* HitTestExpandedButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HitTestExpandedButton.swift; sourceTree = "<group>"; };
2D42FF8E25C8228A004A627A /* UIButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIButton.swift; sourceTree = "<group>"; };
2D46975D25C2A54100CF4AA9 /* NSLayoutConstraint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSLayoutConstraint.swift; sourceTree = "<group>"; };
2D46976325C2A71500CF4AA9 /* UIIamge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIIamge.swift; sourceTree = "<group>"; };
2D61335725C188A000CAE157 /* APIService+Persist+Timeline.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+Persist+Timeline.swift"; sourceTree = "<group>"; };
@ -139,7 +147,6 @@
2D927F0725C7E9A8004F19B8 /* Tag.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tag.swift; sourceTree = "<group>"; };
2D927F0D25C7E9C9004F19B8 /* History.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = History.swift; sourceTree = "<group>"; };
2D927F1325C7EDD9004F19B8 /* Emoji.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Emoji.swift; sourceTree = "<group>"; };
2D9BB87A25C3FEF200678AB6 /* String.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = String.swift; sourceTree = "<group>"; };
2DF123A625C3B0210020F248 /* ActiveLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActiveLabel.swift; sourceTree = "<group>"; };
2E1F6A67FDF9771D3E064FDC /* Pods-Mastodon.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon.debug.xcconfig"; path = "Target Support Files/Pods-Mastodon/Pods-Mastodon.debug.xcconfig"; sourceTree = "<group>"; };
459EA4F43058CAB47719E963 /* Pods-Mastodon-MastodonUITests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon-MastodonUITests.debug.xcconfig"; path = "Target Support Files/Pods-Mastodon-MastodonUITests/Pods-Mastodon-MastodonUITests.debug.xcconfig"; sourceTree = "<group>"; };
@ -202,6 +209,7 @@
buildActionMask = 2147483647;
files = (
DB89BA0325C10FD0008580ED /* CoreDataStack.framework in Frameworks */,
2D42FF6125C8177C004A627A /* ActiveLabel in Frameworks */,
5D526FE225BE9AC400460CB9 /* MastodonSDK in Frameworks */,
2D61336925C18A4F00CAE157 /* AlamofireNetworkActivityIndicator in Frameworks */,
7A9135D4559750AF07CA9BE4 /* Pods_Mastodon.framework in Frameworks */,
@ -264,6 +272,22 @@
path = Content;
sourceTree = "<group>";
};
2D42FF7C25C82207004A627A /* ToolBar */ = {
isa = PBXGroup;
children = (
2D42FF7D25C82218004A627A /* ActionToolBarContainer.swift */,
);
path = ToolBar;
sourceTree = "<group>";
};
2D42FF8325C82245004A627A /* Button */ = {
isa = PBXGroup;
children = (
2D42FF8425C8224F004A627A /* HitTestExpandedButton.swift */,
);
path = Button;
sourceTree = "<group>";
};
2D61335525C1886800CAE157 /* Service */ = {
isa = PBXGroup;
children = (
@ -321,6 +345,8 @@
2D7631A525C1532D00929FB9 /* View */ = {
isa = PBXGroup;
children = (
2D42FF8325C82245004A627A /* Button */,
2D42FF7C25C82207004A627A /* ToolBar */,
2D152A8A25C295B8009AA50C /* Content */,
2D7631A625C1533800929FB9 /* TableviewCell */,
);
@ -549,7 +575,8 @@
2D46975D25C2A54100CF4AA9 /* NSLayoutConstraint.swift */,
2D46976325C2A71500CF4AA9 /* UIIamge.swift */,
2DF123A625C3B0210020F248 /* ActiveLabel.swift */,
2D9BB87A25C3FEF200678AB6 /* String.swift */,
2D42FF6A25C817D2004A627A /* MastodonContent.swift */,
2D42FF8E25C8228A004A627A /* UIButton.swift */,
);
path = Extension;
sourceTree = "<group>";
@ -590,6 +617,7 @@
DB3D0FF225BAA61700EAA174 /* AlamofireImage */,
5D526FE125BE9AC400460CB9 /* MastodonSDK */,
2D61336825C18A4F00CAE157 /* AlamofireNetworkActivityIndicator */,
2D42FF6025C8177C004A627A /* ActiveLabel */,
);
productName = Mastodon;
productReference = DB427DD225BAA00100D1B89D /* Mastodon.app */;
@ -714,6 +742,7 @@
packageReferences = (
DB3D0FF125BAA61700EAA174 /* XCRemoteSwiftPackageReference "AlamofireImage" */,
2D61336725C18A4F00CAE157 /* XCRemoteSwiftPackageReference "AlamofireNetworkActivityIndicator" */,
2D42FF5F25C8177C004A627A /* XCRemoteSwiftPackageReference "ActiveLabel" */,
);
productRefGroup = DB427DD325BAA00100D1B89D /* Products */;
projectDirPath = "";
@ -898,8 +927,9 @@
2D7631B325C159F700929FB9 /* Item.swift in Sources */,
2D61335E25C1894B00CAE157 /* APIService.swift in Sources */,
DB8AF53025C13561002E6C99 /* AppContext.swift in Sources */,
2D9BB87B25C3FEF200678AB6 /* String.swift in Sources */,
2D152A8C25C295CC009AA50C /* TimelinePostView.swift in Sources */,
2D42FF8525C8224F004A627A /* HitTestExpandedButton.swift in Sources */,
2D42FF8F25C8228A004A627A /* UIButton.swift in Sources */,
2D61335825C188A000CAE157 /* APIService+Persist+Timeline.swift in Sources */,
DB8AF52F25C13561002E6C99 /* DocumentStore.swift in Sources */,
2DF123A725C3B0210020F248 /* ActiveLabel.swift in Sources */,
@ -907,6 +937,7 @@
2D46975E25C2A54100CF4AA9 /* NSLayoutConstraint.swift in Sources */,
2D46976425C2A71500CF4AA9 /* UIIamge.swift in Sources */,
DB8AF55D25C138B7002E6C99 /* UIViewController.swift in Sources */,
2D42FF7E25C82218004A627A /* ActionToolBarContainer.swift in Sources */,
DB8AF55025C13703002E6C99 /* MainTabBarController.swift in Sources */,
DB8AF54525C13647002E6C99 /* NeedsDependency.swift in Sources */,
2D76319F25C1521200929FB9 /* TimelineSection.swift in Sources */,
@ -914,6 +945,7 @@
DB8AF54425C13647002E6C99 /* SceneCoordinator.swift in Sources */,
2D04F42525C255B9003F936F /* APIService+PublicTimeline.swift in Sources */,
2D76317D25C14DF500929FB9 /* PublicTimelineViewController+StatusProvider.swift in Sources */,
2D42FF6B25C817D2004A627A /* MastodonContent.swift in Sources */,
DB8AF52E25C13561002E6C99 /* ViewStateStore.swift in Sources */,
DB8AF55725C137A8002E6C99 /* HomeViewController.swift in Sources */,
2D76318325C14E8F00929FB9 /* PublicTimelineViewModel+Diffable.swift in Sources */,
@ -1431,6 +1463,14 @@
/* End XCConfigurationList section */
/* Begin XCRemoteSwiftPackageReference section */
2D42FF5F25C8177C004A627A /* XCRemoteSwiftPackageReference "ActiveLabel" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/TwidereProject/ActiveLabel.swift";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 3.0.0;
};
};
2D61336725C18A4F00CAE157 /* XCRemoteSwiftPackageReference "AlamofireNetworkActivityIndicator" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/Alamofire/AlamofireNetworkActivityIndicator";
@ -1450,6 +1490,11 @@
/* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
2D42FF6025C8177C004A627A /* ActiveLabel */ = {
isa = XCSwiftPackageProductDependency;
package = 2D42FF5F25C8177C004A627A /* XCRemoteSwiftPackageReference "ActiveLabel" */;
productName = ActiveLabel;
};
2D61336825C18A4F00CAE157 /* AlamofireNetworkActivityIndicator */ = {
isa = XCSwiftPackageProductDependency;
package = 2D61336725C18A4F00CAE157 /* XCRemoteSwiftPackageReference "AlamofireNetworkActivityIndicator" */;

View File

@ -1,6 +1,15 @@
{
"object": {
"pins": [
{
"package": "ActiveLabel",
"repositoryURL": "https://github.com/TwidereProject/ActiveLabel.swift",
"state": {
"branch": null,
"revision": "3d8115c992c44358eabbb21ffc4616f4d56028b1",
"version": "3.0.0"
}
},
{
"package": "Alamofire",
"repositoryURL": "https://github.com/Alamofire/Alamofire.git",

View File

@ -45,10 +45,19 @@ extension TimelineSection {
cell: TimelinePostTableViewCell,
toot: Toot
) {
// set name username avatar
cell.timelinePostView.nameLabel.text = toot.author.displayName
cell.timelinePostView.usernameLabel.text = toot.author.username
cell.timelinePostView.avatarImageView.af.setImage(withURL: URL(string: toot.author.avatar)!)
cell.timelinePostView.usernameLabel.text = "@" + toot.author.username
cell.timelinePostView.avatarImageView.af.setImage(
withURL: URL(string: toot.author.avatar)!,
placeholderImage: UIImage.placeholder(color: .systemFill),
imageTransition: .crossDissolve(0.2)
)
// set text
cell.timelinePostView.activeTextLabel.config(content: toot.content)
// set date
let createdAt = toot.createdAt
cell.timelinePostView.dateLabel.text = createdAt.shortTimeAgoSinceNow
}
}

View File

@ -8,7 +8,7 @@
import UIKit
import Foundation
import ActiveLabel
import os.log
extension ActiveLabel {
@ -24,7 +24,7 @@ extension ActiveLabel {
case .default:
// urlMaximumLength = 30
font = .preferredFont(forTextStyle: .body)
textColor = UIColor.label.withAlphaComponent(0.8)
textColor = .white
case .timelineHeaderView:
font = .preferredFont(forTextStyle: .footnote)
textColor = .secondaryLabel
@ -40,9 +40,18 @@ extension ActiveLabel {
}
extension ActiveLabel {
func config(content:String) {
let html = content.replacingOccurrences(of: "</p><p>", with: "<br /><br />").replacingOccurrences(of: "<p>", with: "").replacingOccurrences(of: "</p>", with: "")
text = html.toPlainText()
func config(content: String) {
if let parseResult = try? TootContent.parse(toot: content) {
activeEntities.removeAll()
numberOfLines = 0
font = UIFont(name: "SFProText-Regular", size: 16)
textColor = .white
URLColor = .systemRed
mentionColor = .systemGreen
hashtagColor = .systemBlue
text = parseResult.trimmed
activeEntities = parseResult.activeEntities
}
}
}

View File

@ -0,0 +1,302 @@
//
// MastodonContent.swift
// Mastodon
//
// Created by MainasuK Cirno on 2021/2/1.
//
import Foundation
import Kanna
import ActiveLabel
enum TootContent {
static func parse(toot: String) throws -> TootContent.ParseResult {
let toot = toot.replacingOccurrences(of: "<br/>", with: "\n")
let rootNode = try Node.parse(document: toot)
let text = String(rootNode.text)
var activeEntities: [ActiveEntity] = []
let entities = TootContent.Node.entities(in: rootNode)
for entity in entities {
let range = NSRange(entity.text.startIndex..<entity.text.endIndex, in: text)
switch entity.type {
case .url:
guard let href = entity.href else { continue }
activeEntities.append(ActiveEntity(range: range, type: .url(original: href, trimmed: entity.hrefEllipsis ?? href)))
case .hashtag:
var userInfo: [AnyHashable: Any] = [:]
entity.href.flatMap { href in
userInfo["href"] = href
}
let hashtag = String(entity.text).deletingPrefix("#")
activeEntities.append(ActiveEntity(range: range, type: .hashtag(hashtag, userInfo: userInfo)))
case .mention:
var userInfo: [AnyHashable: Any] = [:]
entity.href.flatMap { href in
userInfo["href"] = href
}
let mention = String(entity.text).deletingPrefix("@")
activeEntities.append(ActiveEntity(range: range, type: .mention(mention, userInfo: userInfo)))
default:
continue
}
}
var trimmed = text
for activeEntity in activeEntities {
guard case .url = activeEntity.type else { continue }
TootContent.trimEntity(toot: &trimmed, activeEntity: activeEntity, activeEntities: activeEntities)
}
return ParseResult(
document: toot,
original: text,
trimmed: trimmed,
activeEntities: activeEntities
)
}
static func trimEntity(toot: inout String, activeEntity: ActiveEntity, activeEntities: [ActiveEntity]) {
guard case let .url(original, trimmed, _) = activeEntity.type else { return }
guard let index = activeEntities.firstIndex(where: { $0.range == activeEntity.range }) else { return }
guard let range = Range(activeEntity.range, in: toot) else { return }
toot.replaceSubrange(range, with: trimmed)
let offset = trimmed.count - original.count
activeEntity.range.length += offset
let moveActiveEntities = Array(activeEntities[index...].dropFirst())
for moveActiveEntity in moveActiveEntities {
moveActiveEntity.range.location += offset
}
}
}
extension String {
// ref: https://www.hackingwithswift.com/example-code/strings/how-to-remove-a-prefix-from-a-string
func deletingPrefix(_ prefix: String) -> String {
guard self.hasPrefix(prefix) else { return self }
return String(self.dropFirst(prefix.count))
}
}
extension TootContent {
struct ParseResult {
let document: String
let original: String
let trimmed: String
let activeEntities: [ActiveEntity]
}
}
extension TootContent {
class Node {
let level: Int
let type: Type?
// substring text
let text: Substring
// range in parent String
var range: Range<String.Index> {
return text.startIndex..<text.endIndex
}
let tagName: String?
let classNames: Set<String>
let href: String?
let hrefEllipsis: String?
let children: [Node]
init(
level: Int,
text: Substring,
tagName: String?,
className: String?,
href: String?,
hrefEllipsis: String?,
children: [Node]
) {
let _classNames: Set<String> = {
guard let className = className else { return Set() }
return Set(className.components(separatedBy: " "))
}()
let _type: Type? = {
if tagName == "a" && !_classNames.contains("mention") {
return .url
}
if _classNames.contains("mention") {
if _classNames.contains("u-url") {
return .mention
} else if _classNames.contains("hashtag") {
return .hashtag
}
}
return nil
}()
self.level = level
self.type = _type
self.text = text
self.tagName = tagName
self.classNames = _classNames
self.href = href
self.hrefEllipsis = hrefEllipsis
self.children = children
}
static func parse(document: String) throws -> TootContent.Node {
let html = try HTML(html: document, encoding: .utf8)
let body = html.body ?? nil
let text = body?.text ?? ""
let level = 0
let children: [TootContent.Node] = body.flatMap { body in
return Node.parse(element: body, parentText: text[...], parentLevel: level + 1)
} ?? []
let node = Node(
level: level,
text: text[...],
tagName: body?.tagName,
className: body?.className,
href: nil,
hrefEllipsis: nil,
children: children
)
return node
}
static func parse(element: XMLElement, parentText: Substring, parentLevel: Int) -> [Node] {
let parent = element
let scanner = Scanner(string: String(parentText))
scanner.charactersToBeSkipped = .none
var element = parent.at_css(":first-child")
var children: [Node] = []
while let _element = element {
let _text = _element.text ?? ""
// scan element text
_ = scanner.scanUpToString(_text)
let startIndexOffset = scanner.currentIndex.utf16Offset(in: scanner.string)
guard scanner.scanString(_text) != nil else {
assertionFailure()
continue
}
let endIndexOffset = scanner.currentIndex.utf16Offset(in: scanner.string)
// locate substring
let startIndex = parentText.utf16.index(parentText.utf16.startIndex, offsetBy: startIndexOffset)
let endIndex = parentText.utf16.index(parentText.utf16.startIndex, offsetBy: endIndexOffset)
let text = Substring(parentText.utf16[startIndex..<endIndex])
let href = _element["href"]
let hrefEllipsis = href.flatMap { _ in _element.at_css(".ellipsis")?.text }
let level = parentLevel + 1
let node = Node(
level: level,
text: text,
tagName: _element.tagName,
className: _element.className,
href: href,
hrefEllipsis: hrefEllipsis,
children: Node.parse(element: _element, parentText: text, parentLevel: level + 1)
)
children.append(node)
element = _element.nextSibling
}
return children
}
static func collect(
node: Node,
where predicate: (Node) -> Bool
) -> [Node] {
var nodes: [Node] = []
if predicate(node) {
nodes.append(node)
}
for child in node.children {
nodes.append(contentsOf: Node.collect(node: child, where: predicate))
}
return nodes
}
}
}
extension TootContent.Node {
enum `Type` {
case url
case mention
case hashtag
}
static func entities(in node: TootContent.Node) -> [TootContent.Node] {
return TootContent.Node.collect(node: node) { node in node.type != nil }
}
static func hashtags(in node: TootContent.Node) -> [TootContent.Node] {
return TootContent.Node.collect(node: node) { node in node.type == .hashtag }
}
static func mentions(in node: TootContent.Node) -> [TootContent.Node] {
return TootContent.Node.collect(node: node) { node in node.type == .mention }
}
static func urls(in node: TootContent.Node) -> [TootContent.Node] {
return TootContent.Node.collect(node: node) { node in node.type == .url }
}
}
extension TootContent.Node: CustomDebugStringConvertible {
var debugDescription: String {
let linkInfo: String = {
switch (href, hrefEllipsis) {
case (nil, nil):
return ""
case (let href, let hrefEllipsis):
return "(\(href ?? "nil") - \(hrefEllipsis ?? "nil"))"
}
}()
let classNamesInfo: String = {
guard !classNames.isEmpty else { return "" }
let names = Array(classNames)
.sorted()
.joined(separator: ", ")
return "@[\(names)]"
}()
let nodeDescription = String(
format: "<%@>%@%@: %@",
tagName ?? "",
classNamesInfo,
linkInfo,
String(text)
)
guard !children.isEmpty else {
return nodeDescription
}
let indent = Array(repeating: " ", count: level).joined()
let childrenDescription = children
.map { indent + $0.debugDescription }
.joined(separator: "\n")
return nodeDescription + "\n" + childrenDescription
}
}

View File

@ -1,39 +0,0 @@
//
// String.swift
// Mastodon
//
// Created by sxiaojian on 2021/1/29.
//
import Foundation
extension String {
public func pregReplace(pattern: String, with: String, options: NSRegularExpression.Options = []) -> String {
// swiftlint:disable force_try
let regex = try! NSRegularExpression(pattern: pattern, options: options)
return regex.stringByReplacingMatches(in: self, options: [], range: NSRange(location: 0, length: nsLength), withTemplate: with)
}
}
extension String {
public var nsLength: Int {
let string_NS = self as NSString
return string_NS.length
}
}
extension String {
func toPlainText() -> String {
return self.pregReplace(pattern: "<br.+?>", with: "\n")
.replacingOccurrences(of: "</p><p>", with: "\n\n")
.pregReplace(pattern: "<.+?>", with: "")
.replacingOccurrences(of: "&lt;", with: "<")
.replacingOccurrences(of: "&gt;", with: ">")
.replacingOccurrences(of: "&apos;", with: "'")
.replacingOccurrences(of: "&quot;", with: "\"")
.replacingOccurrences(of: "&amp;", with: "&")
}
}
extension String {
func string(in nsrange: NSRange) -> String? {
guard let range = Range(nsrange, in: self) else { return nil }
return String(self[range])
}
}

View File

@ -0,0 +1,45 @@
//
// UIButton.swift
// Mastodon
//
// Created by sxiaojian on 2021/2/1.
//
import UIKit
extension UIButton {
func setInsets(
forContentPadding contentPadding: UIEdgeInsets,
imageTitlePadding: CGFloat
) {
switch UIApplication.shared.userInterfaceLayoutDirection {
case .rightToLeft:
self.contentEdgeInsets = UIEdgeInsets(
top: contentPadding.top,
left: contentPadding.left + imageTitlePadding,
bottom: contentPadding.bottom,
right: contentPadding.right
)
self.titleEdgeInsets = UIEdgeInsets(
top: 0,
left: -imageTitlePadding,
bottom: 0,
right: imageTitlePadding
)
default:
self.contentEdgeInsets = UIEdgeInsets(
top: contentPadding.top,
left: contentPadding.left,
bottom: contentPadding.bottom,
right: contentPadding.right + imageTitlePadding
)
self.titleEdgeInsets = UIEdgeInsets(
top: 0,
left: imageTitlePadding,
bottom: 0,
right: -imageTitlePadding
)
}
}
}

View File

@ -12,6 +12,8 @@
// Deprecated typealiases
@available(*, deprecated, renamed: "ColorAsset.Color", message: "This typealias will be removed in SwiftGen 7.0")
internal typealias AssetColorTypeAlias = ColorAsset.Color
@available(*, deprecated, renamed: "ImageAsset.Image", message: "This typealias will be removed in SwiftGen 7.0")
internal typealias AssetImageTypeAlias = ImageAsset.Image
// swiftlint:disable superfluous_disable_command file_length implicit_return
@ -20,6 +22,27 @@ internal typealias AssetColorTypeAlias = ColorAsset.Color
// swiftlint:disable identifier_name line_length nesting type_body_length type_name
internal enum Asset {
internal static let accentColor = ColorAsset(name: "AccentColor")
internal enum Colors {
internal static let likeOrange = ColorAsset(name: "Colors/like.orange")
internal static let tootDark = ColorAsset(name: "Colors/toot.dark")
internal static let tootGray = ColorAsset(name: "Colors/toot.gray")
internal static let tootWhite = ColorAsset(name: "Colors/toot.white")
}
internal enum ToolBar {
internal static let bookmark = ImageAsset(name: "ToolBar/bookmark")
internal static let lock = ImageAsset(name: "ToolBar/lock")
internal static let more = ImageAsset(name: "ToolBar/more")
internal static let reply = ImageAsset(name: "ToolBar/reply")
internal static let retoot = ImageAsset(name: "ToolBar/retoot")
internal static let star = ImageAsset(name: "ToolBar/star")
}
internal enum TootTimeline {
internal static let email = ImageAsset(name: "TootTimeline/email")
internal static let global = ImageAsset(name: "TootTimeline/global")
internal static let lock = ImageAsset(name: "TootTimeline/lock")
internal static let textlock = ImageAsset(name: "TootTimeline/textlock")
internal static let unlock = ImageAsset(name: "TootTimeline/unlock")
}
}
// swiftlint:enable identifier_name line_length nesting type_body_length type_name
@ -61,6 +84,47 @@ internal extension ColorAsset.Color {
}
}
internal struct ImageAsset {
internal fileprivate(set) var name: String
#if os(macOS)
internal typealias Image = NSImage
#elseif os(iOS) || os(tvOS) || os(watchOS)
internal typealias Image = UIImage
#endif
internal var image: Image {
let bundle = BundleToken.bundle
#if os(iOS) || os(tvOS)
let image = Image(named: name, in: bundle, compatibleWith: nil)
#elseif os(macOS)
let name = NSImage.Name(self.name)
let image = (bundle == .main) ? NSImage(named: name) : bundle.image(forResource: name)
#elseif os(watchOS)
let image = Image(named: name)
#endif
guard let result = image else {
fatalError("Unable to load image asset named \(name).")
}
return result
}
}
internal extension ImageAsset.Image {
@available(macOS, deprecated,
message: "This initializer is unsafe on macOS, please use the ImageAsset.image property")
convenience init?(asset: ImageAsset) {
#if os(iOS) || os(tvOS)
let bundle = BundleToken.bundle
self.init(named: asset.name, in: bundle, compatibleWith: nil)
#elseif os(macOS)
self.init(named: NSImage.Name(asset.name))
#elseif os(watchOS)
self.init(named: asset.name)
#endif
}
}
// swiftlint:disable convenience_type
private final class BundleToken {
static let bundle: Bundle = {

View File

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

View File

@ -0,0 +1,38 @@
{
"colors" : [
{
"color" : {
"color-space" : "extended-srgb",
"components" : {
"alpha" : "1.000",
"blue" : "55",
"green" : "45",
"red" : "41"
}
},
"idiom" : "universal"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "55",
"green" : "45",
"red" : "41"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,38 @@
{
"colors" : [
{
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "132",
"green" : "105",
"red" : "96"
}
},
"idiom" : "universal"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "132",
"green" : "105",
"red" : "96"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,41 @@
{
"colors" : [
{
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "1.000",
"green" : "1.000",
"red" : "1.000"
}
},
"idiom" : "universal"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "1.000",
"green" : "1.000",
"red" : "1.000"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"localizable" : true
}
}

View File

@ -0,0 +1,38 @@
{
"colors" : [
{
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "10",
"green" : "159",
"red" : "255"
}
},
"idiom" : "universal"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "10",
"green" : "159",
"red" : "255"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

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

View File

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

View File

@ -0,0 +1,170 @@
%PDF-1.7
1 0 obj
<< /Length 2 0 R >>
stream
1.063477 0 0.180664 -0.195801 0.882812 1.271484 d1
endstream
endobj
2 0 obj
51
endobj
3 0 obj
[ 1.063477 ]
endobj
4 0 obj
<< /Length 5 0 R >>
stream
/CIDInit /ProcSet findresource begin
12 dict begin
begincmap
/CIDSystemInfo
<< /Registry (FigmaPDF)
/Ordering (FigmaPDF)
/Supplement 0
>> def
/CMapName /A-B-C def
/CMapType 2 def
1 begincodespacerange
<00> <FF>
endcodespacerange
1 beginbfchar
<00> <DBC0DE5E>
endbfchar
endcmap
CMapName currentdict /CMap defineresource pop
end
end
endstream
endobj
5 0 obj
336
endobj
6 0 obj
<< /Subtype /Type3
/CharProcs << /C0 1 0 R >>
/Encoding << /Type /Encoding
/Differences [ 0 /C0 ]
>>
/Widths 3 0 R
/FontBBox [ 0.000000 0.000000 0.000000 0.000000 ]
/FontMatrix [ 1.000000 0.000000 0.000000 1.000000 0.000000 0.000000 ]
/Type /Font
/ToUnicode 4 0 R
/FirstChar 0
/LastChar 0
/Resources << >>
>>
endobj
7 0 obj
<< /Font << /F1 6 0 R >> >>
endobj
8 0 obj
<< /Length 9 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 -6.382812 0.679688 cm
0.376471 0.411765 0.517647 scn
3.492188 2.453125 m
h
7.554688 -0.679688 m
8.007812 -0.679688 8.312500 -0.453125 8.945312 0.171875 c
11.937500 3.140625 l
11.968750 3.171875 12.031250 3.171875 12.070312 3.140625 c
15.054688 0.164062 l
15.695312 -0.453125 15.992188 -0.679688 16.453125 -0.679688 c
17.164062 -0.679688 17.617188 -0.179688 17.617188 0.601562 c
17.617188 14.289062 l
17.617188 15.898438 16.750000 16.773438 15.156250 16.773438 c
8.843750 16.773438 l
7.250000 16.773438 6.382812 15.898438 6.382812 14.289062 c
6.382812 0.601562 l
6.382812 -0.179688 6.835938 -0.679688 7.554688 -0.679688 c
h
8.382812 2.257812 m
8.281250 2.156250 8.164062 2.187500 8.164062 2.335938 c
8.164062 14.140625 l
8.164062 14.718750 8.437500 14.992188 9.023438 14.992188 c
14.976562 14.992188 l
15.562500 14.992188 15.843750 14.718750 15.843750 14.140625 c
15.843750 2.335938 l
15.843750 2.187500 15.726562 2.156250 15.617188 2.257812 c
12.601562 5.179688 l
12.203125 5.562500 11.796875 5.562500 11.398438 5.179688 c
8.382812 2.257812 l
h
f
n
Q
q
1.000000 0.000000 -0.000000 1.000000 -6.382812 0.679688 cm
BT
16.000000 0.000000 0.000000 16.000000 3.492188 2.453125 Tm
/F1 1.000000 Tf
[ (\000) ] TJ
ET
Q
endstream
endobj
9 0 obj
1276
endobj
10 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 11.234375 17.453125 ]
/Resources 7 0 R
/Contents 8 0 R
/Parent 11 0 R
>>
endobj
11 0 obj
<< /Kids [ 10 0 R ]
/Count 1
/Type /Pages
>>
endobj
12 0 obj
<< /Type /Catalog
/Pages 11 0 R
>>
endobj
xref
0 13
0000000000 65535 f
0000000010 00000 n
0000000117 00000 n
0000000138 00000 n
0000000169 00000 n
0000000561 00000 n
0000000583 00000 n
0000000995 00000 n
0000001041 00000 n
0000002373 00000 n
0000002396 00000 n
0000002571 00000 n
0000002647 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 12 0 R
/Size 13
>>
startxref
2708
%%EOF

View File

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

View File

@ -0,0 +1,174 @@
%PDF-1.7
1 0 obj
<< /Length 2 0 R >>
stream
1.093750 0 0.197266 -0.131348 0.896484 1.184082 d1
endstream
endobj
2 0 obj
51
endobj
3 0 obj
[ 1.093750 ]
endobj
4 0 obj
<< /Length 5 0 R >>
stream
/CIDInit /ProcSet findresource begin
12 dict begin
begincmap
/CIDSystemInfo
<< /Registry (FigmaPDF)
/Ordering (FigmaPDF)
/Supplement 0
>> def
/CMapName /A-B-C def
/CMapType 2 def
1 begincodespacerange
<00> <FF>
endcodespacerange
1 beginbfchar
<00> <DBC0DFA0>
endbfchar
endcmap
CMapName currentdict /CMap defineresource pop
end
end
endstream
endobj
5 0 obj
336
endobj
6 0 obj
<< /Subtype /Type3
/CharProcs << /C0 1 0 R >>
/Encoding << /Type /Encoding
/Differences [ 0 /C0 ]
>>
/Widths 3 0 R
/FontBBox [ 0.000000 0.000000 0.000000 0.000000 ]
/FontMatrix [ 1.000000 0.000000 0.000000 1.000000 0.000000 0.000000 ]
/Type /Font
/ToUnicode 4 0 R
/FirstChar 0
/LastChar 0
/Resources << >>
>>
endobj
7 0 obj
<< /Font << /F1 6 0 R >> >>
endobj
8 0 obj
<< /Length 9 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 -6.406250 1.312500 cm
0.266667 0.294118 0.364706 scn
3.250000 0.789062 m
h
8.257812 -1.312500 m
15.742188 -1.312500 l
16.984375 -1.312500 17.593750 -0.695312 17.593750 0.648438 c
17.593750 6.343750 l
17.593750 7.531250 17.101562 8.156250 16.117188 8.273438 c
16.117188 10.039062 l
16.117188 13.023438 14.101562 14.476562 12.000000 14.476562 c
9.898438 14.476562 7.882812 13.023438 7.882812 10.039062 c
7.882812 8.273438 l
6.890625 8.156250 6.406250 7.531250 6.406250 6.343750 c
6.406250 0.648438 l
6.406250 -0.695312 7.015625 -1.312500 8.257812 -1.312500 c
h
9.570312 10.171875 m
9.570312 11.882812 10.656250 12.843750 12.000000 12.843750 c
13.343750 12.843750 14.429688 11.882812 14.429688 10.171875 c
14.429688 8.296875 l
9.570312 8.296875 l
9.570312 10.171875 l
h
8.656250 0.289062 m
8.328125 0.289062 8.164062 0.445312 8.164062 0.843750 c
8.164062 6.148438 l
8.164062 6.546875 8.328125 6.687500 8.656250 6.687500 c
15.343750 6.687500 l
15.679688 6.687500 15.835938 6.546875 15.835938 6.148438 c
15.835938 0.843750 l
15.835938 0.445312 15.679688 0.289062 15.343750 0.289062 c
8.656250 0.289062 l
h
f
n
Q
q
1.000000 0.000000 -0.000000 1.000000 -6.406250 1.312500 cm
BT
16.000000 0.000000 0.000000 16.000000 3.250000 0.789062 Tm
/F1 1.000000 Tf
[ (\000) ] TJ
ET
Q
endstream
endobj
9 0 obj
1332
endobj
10 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 11.187500 15.789062 ]
/Resources 7 0 R
/Contents 8 0 R
/Parent 11 0 R
>>
endobj
11 0 obj
<< /Kids [ 10 0 R ]
/Count 1
/Type /Pages
>>
endobj
12 0 obj
<< /Type /Catalog
/Pages 11 0 R
>>
endobj
xref
0 13
0000000000 65535 f
0000000010 00000 n
0000000117 00000 n
0000000138 00000 n
0000000169 00000 n
0000000561 00000 n
0000000583 00000 n
0000000995 00000 n
0000001041 00000 n
0000002429 00000 n
0000002452 00000 n
0000002627 00000 n
0000002703 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 12 0 R
/Size 13
>>
startxref
2764
%%EOF

View File

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

View File

@ -0,0 +1,162 @@
%PDF-1.7
1 0 obj
<< /Length 2 0 R >>
stream
1.124512 0 0.087402 0.243652 1.037109 0.304199 d1
endstream
endobj
2 0 obj
50
endobj
3 0 obj
[ 1.124512 ]
endobj
4 0 obj
<< /Length 5 0 R >>
stream
/CIDInit /ProcSet findresource begin
12 dict begin
begincmap
/CIDSystemInfo
<< /Registry (FigmaPDF)
/Ordering (FigmaPDF)
/Supplement 0
>> def
/CMapName /A-B-C def
/CMapType 2 def
1 begincodespacerange
<00> <FF>
endcodespacerange
1 beginbfchar
<00> <DBC0DF60>
endbfchar
endcmap
CMapName currentdict /CMap defineresource pop
end
end
endstream
endobj
5 0 obj
336
endobj
6 0 obj
<< /Subtype /Type3
/CharProcs << /C0 1 0 R >>
/Encoding << /Type /Encoding
/Differences [ 0 /C0 ]
>>
/Widths 3 0 R
/FontBBox [ 0.000000 0.000000 0.000000 0.000000 ]
/FontMatrix [ 1.000000 0.000000 0.000000 1.000000 0.000000 0.000000 ]
/Type /Font
/ToUnicode 4 0 R
/FirstChar 0
/LastChar 0
/Resources << >>
>>
endobj
7 0 obj
<< /Font << /F1 6 0 R >> >>
endobj
8 0 obj
<< /Length 9 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 -4.398438 7.632812 cm
0.376471 0.411765 0.517647 scn
3.000000 -11.531250 m
h
7.875000 -5.898438 m
7.875000 -4.921875 7.117188 -4.164062 6.132812 -4.164062 c
5.179688 -4.164062 4.398438 -4.937500 4.398438 -5.898438 c
4.398438 -6.835938 5.179688 -7.632812 6.132812 -7.632812 c
7.078125 -7.632812 7.875000 -6.835938 7.875000 -5.898438 c
h
13.726562 -5.898438 m
13.726562 -4.921875 12.968750 -4.164062 11.992188 -4.164062 c
11.039062 -4.164062 10.265625 -4.937500 10.265625 -5.898438 c
10.265625 -6.835938 11.039062 -7.632812 11.992188 -7.632812 c
12.937500 -7.632812 13.726562 -6.835938 13.726562 -5.898438 c
h
19.593750 -5.898438 m
19.593750 -4.921875 18.835938 -4.164062 17.859375 -4.164062 c
16.898438 -4.164062 16.117188 -4.937500 16.117188 -5.898438 c
16.117188 -6.835938 16.898438 -7.632812 17.859375 -7.632812 c
18.796875 -7.632812 19.593750 -6.835938 19.593750 -5.898438 c
h
f
n
Q
q
1.000000 0.000000 -0.000000 1.000000 -4.398438 7.632812 cm
BT
16.000000 0.000000 0.000000 16.000000 3.000000 -11.531250 Tm
/F1 1.000000 Tf
[ (\000) ] TJ
ET
Q
endstream
endobj
9 0 obj
1113
endobj
10 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 15.195312 3.468750 ]
/Resources 7 0 R
/Contents 8 0 R
/Parent 11 0 R
>>
endobj
11 0 obj
<< /Kids [ 10 0 R ]
/Count 1
/Type /Pages
>>
endobj
12 0 obj
<< /Type /Catalog
/Pages 11 0 R
>>
endobj
xref
0 13
0000000000 65535 f
0000000010 00000 n
0000000116 00000 n
0000000137 00000 n
0000000168 00000 n
0000000560 00000 n
0000000582 00000 n
0000000994 00000 n
0000001040 00000 n
0000002209 00000 n
0000002232 00000 n
0000002406 00000 n
0000002482 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 12 0 R
/Size 13
>>
startxref
2543
%%EOF

View File

@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "reply all.pdf",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,206 @@
%PDF-1.7
1 0 obj
<< /Length 2 0 R >>
stream
1.523438 0 0.076172 -0.107910 1.409668 0.996582 d1
endstream
endobj
2 0 obj
51
endobj
3 0 obj
[ 1.523438 ]
endobj
4 0 obj
<< /Length 5 0 R >>
stream
/CIDInit /ProcSet findresource begin
12 dict begin
begincmap
/CIDSystemInfo
<< /Registry (FigmaPDF)
/Ordering (FigmaPDF)
/Supplement 0
>> def
/CMapName /A-B-C def
/CMapType 2 def
1 begincodespacerange
<00> <FF>
endcodespacerange
1 beginbfchar
<00> <DBC0DE54>
endbfchar
endcmap
CMapName currentdict /CMap defineresource pop
end
end
endstream
endobj
5 0 obj
336
endobj
6 0 obj
<< /Subtype /Type3
/CharProcs << /C0 1 0 R >>
/Encoding << /Type /Encoding
/Differences [ 0 /C0 ]
>>
/Widths 3 0 R
/FontBBox [ 0.000000 0.000000 0.000000 0.000000 ]
/FontMatrix [ 1.000000 0.000000 0.000000 1.000000 0.000000 0.000000 ]
/Type /Font
/ToUnicode 4 0 R
/FirstChar 0
/LastChar 0
/Resources << >>
>>
endobj
7 0 obj
<< /Font << /F1 6 0 R >> >>
endobj
8 0 obj
<< /Length 9 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 -1.031250 2.000000 cm
0.376471 0.411765 0.517647 scn
-0.187500 -0.273438 m
h
8.937500 -2.000000 m
9.601562 -2.000000 10.101562 -1.492188 10.101562 -0.828125 c
10.101562 0.390625 l
12.023438 -1.406250 l
12.460938 -1.812500 12.820312 -2.000000 13.281250 -2.000000 c
13.945312 -2.000000 14.445312 -1.492188 14.445312 -0.828125 c
14.445312 1.828125 l
14.617188 1.828125 l
17.335938 1.828125 18.953125 0.929688 20.062500 -1.140625 c
20.406250 -1.757812 20.804688 -1.929688 21.273438 -1.929688 c
21.921875 -1.929688 22.367188 -1.304688 22.367188 -0.078125 c
22.367188 5.515625 19.828125 8.867188 14.617188 8.867188 c
14.445312 8.867188 l
14.445312 11.531250 l
14.445312 12.195312 13.945312 12.726562 13.265625 12.726562 c
12.828125 12.726562 12.507812 12.546875 12.023438 12.101562 c
10.101562 10.320312 l
10.101562 11.531250 l
10.101562 12.195312 9.601562 12.726562 8.921875 12.726562 c
8.476562 12.726562 8.164062 12.546875 7.679688 12.101562 c
1.468750 6.335938 l
1.156250 6.039062 1.031250 5.687500 1.031250 5.367188 c
1.031250 5.054688 1.164062 4.687500 1.476562 4.390625 c
7.679688 -1.406250 l
8.109375 -1.812500 8.476562 -2.000000 8.937500 -2.000000 c
h
8.273438 0.343750 m
3.109375 5.218750 l
3.046875 5.281250 3.031250 5.320312 3.031250 5.367188 c
3.031250 5.414062 3.046875 5.453125 3.109375 5.507812 c
8.273438 10.429688 l
8.312500 10.460938 8.351562 10.484375 8.406250 10.484375 c
8.476562 10.484375 8.523438 10.437500 8.523438 10.359375 c
8.523438 8.851562 l
5.820312 6.335938 l
5.507812 6.039062 5.375000 5.687500 5.375000 5.367188 c
5.375000 5.054688 5.507812 4.687500 5.820312 4.390625 c
8.523438 1.867188 l
8.523438 0.414062 l
8.523438 0.335938 8.476562 0.281250 8.406250 0.281250 c
8.359375 0.281250 8.320312 0.296875 8.273438 0.343750 c
h
12.750000 0.281250 m
12.703125 0.281250 12.664062 0.296875 12.617188 0.343750 c
7.453125 5.218750 l
7.390625 5.281250 7.375000 5.320312 7.375000 5.367188 c
7.375000 5.414062 7.398438 5.453125 7.453125 5.507812 c
12.617188 10.429688 l
12.656250 10.460938 12.703125 10.484375 12.750000 10.484375 c
12.820312 10.484375 12.867188 10.437500 12.867188 10.359375 c
12.867188 7.523438 l
12.867188 7.351562 12.945312 7.273438 13.125000 7.273438 c
14.078125 7.273438 l
18.867188 7.273438 20.757812 4.257812 20.859375 0.492188 c
20.859375 0.445312 20.835938 0.421875 20.804688 0.421875 c
20.773438 0.421875 20.757812 0.445312 20.734375 0.492188 c
19.796875 2.437500 17.570312 3.453125 14.078125 3.453125 c
13.125000 3.453125 l
12.945312 3.453125 12.867188 3.375000 12.867188 3.195312 c
12.867188 0.414062 l
12.867188 0.335938 12.820312 0.281250 12.750000 0.281250 c
h
f
n
Q
q
1.000000 0.000000 -0.000000 1.000000 -1.031250 2.000000 cm
BT
16.000000 0.000000 0.000000 16.000000 -0.187500 -0.273438 Tm
/F1 1.000000 Tf
[ (\000) ] TJ
ET
Q
endstream
endobj
9 0 obj
2842
endobj
10 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 21.335938 14.726562 ]
/Resources 7 0 R
/Contents 8 0 R
/Parent 11 0 R
>>
endobj
11 0 obj
<< /Kids [ 10 0 R ]
/Count 1
/Type /Pages
>>
endobj
12 0 obj
<< /Type /Catalog
/Pages 11 0 R
>>
endobj
xref
0 13
0000000000 65535 f
0000000010 00000 n
0000000117 00000 n
0000000138 00000 n
0000000169 00000 n
0000000561 00000 n
0000000583 00000 n
0000000995 00000 n
0000001041 00000 n
0000003939 00000 n
0000003962 00000 n
0000004137 00000 n
0000004213 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 12 0 R
/Size 13
>>
startxref
4274
%%EOF

View File

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

View File

@ -0,0 +1,186 @@
%PDF-1.7
1 0 obj
<< /Length 2 0 R >>
stream
1.503418 0 0.119141 -0.109863 1.384277 1.042480 d1
endstream
endobj
2 0 obj
51
endobj
3 0 obj
[ 1.503418 ]
endobj
4 0 obj
<< /Length 5 0 R >>
stream
/CIDInit /ProcSet findresource begin
12 dict begin
begincmap
/CIDSystemInfo
<< /Registry (FigmaPDF)
/Ordering (FigmaPDF)
/Supplement 0
>> def
/CMapName /A-B-C def
/CMapType 2 def
1 begincodespacerange
<00> <FF>
endcodespacerange
1 beginbfchar
<00> <DBC0DD4C>
endbfchar
endcmap
CMapName currentdict /CMap defineresource pop
end
end
endstream
endobj
5 0 obj
336
endobj
6 0 obj
<< /Subtype /Type3
/CharProcs << /C0 1 0 R >>
/Encoding << /Type /Encoding
/Differences [ 0 /C0 ]
>>
/Widths 3 0 R
/FontBBox [ 0.000000 0.000000 0.000000 0.000000 ]
/FontMatrix [ 1.000000 0.000000 0.000000 1.000000 0.000000 0.000000 ]
/Type /Font
/ToUnicode 4 0 R
/FirstChar 0
/LastChar 0
/Resources << >>
>>
endobj
7 0 obj
<< /Font << /F1 6 0 R >> >>
endobj
8 0 obj
<< /Length 9 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 -1.967758 1.984375 cm
0.376471 0.411765 0.517647 scn
-0.031250 -0.226562 m
h
16.234375 12.789062 m
10.367188 12.789062 l
9.789062 12.789062 9.414062 12.437500 9.414062 11.898438 c
9.421875 11.351562 9.789062 11.000000 10.367188 11.000000 c
16.070312 11.000000 l
16.750000 11.000000 17.109375 10.664062 17.109375 9.953125 c
17.109375 2.109375 l
16.062500 3.281250 l
15.531250 3.804688 l
15.156250 4.179688 14.625000 4.195312 14.257812 3.820312 c
13.882812 3.445312 13.890625 2.914062 14.265625 2.539062 c
16.968750 -0.156250 l
17.625000 -0.804688 18.382812 -0.804688 19.039062 -0.156250 c
21.742188 2.539062 l
22.117188 2.914062 22.117188 3.445312 21.750000 3.820312 c
21.382812 4.195312 20.851562 4.179688 20.476562 3.804688 c
19.945312 3.281250 l
18.898438 2.117188 l
18.898438 10.148438 l
18.898438 11.867188 17.968750 12.789062 16.234375 12.789062 c
h
2.242188 6.984375 m
2.609375 6.617188 3.140625 6.625000 3.515625 7.000000 c
4.046875 7.523438 l
5.093750 8.687500 l
5.093750 0.664062 l
5.093750 -1.062500 6.023438 -1.984375 7.757812 -1.984375 c
13.625000 -1.984375 l
14.203125 -1.984375 14.578125 -1.625000 14.578125 -1.085938 c
14.570312 -0.546875 14.203125 -0.195312 13.625000 -0.195312 c
7.921875 -0.195312 l
7.242188 -0.195312 6.882812 0.148438 6.882812 0.859375 c
6.882812 8.695312 l
7.929688 7.523438 l
8.460938 7.000000 l
8.835938 6.632812 9.367188 6.609375 9.734375 6.984375 c
10.109375 7.359375 10.101562 7.890625 9.726562 8.265625 c
7.023438 10.960938 l
6.367188 11.617188 5.609375 11.609375 4.953125 10.960938 c
2.250000 8.265625 l
1.875000 7.890625 1.875000 7.359375 2.242188 6.984375 c
h
f
n
Q
q
1.000000 0.000000 -0.000000 1.000000 -1.967758 1.984375 cm
BT
16.000000 0.000000 0.000000 16.000000 -0.031250 -0.226562 Tm
/F1 1.000000 Tf
[ (\000) ] TJ
ET
Q
endstream
endobj
9 0 obj
1839
endobj
10 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 20.056656 14.773438 ]
/Resources 7 0 R
/Contents 8 0 R
/Parent 11 0 R
>>
endobj
11 0 obj
<< /Kids [ 10 0 R ]
/Count 1
/Type /Pages
>>
endobj
12 0 obj
<< /Type /Catalog
/Pages 11 0 R
>>
endobj
xref
0 13
0000000000 65535 f
0000000010 00000 n
0000000117 00000 n
0000000138 00000 n
0000000169 00000 n
0000000561 00000 n
0000000583 00000 n
0000000995 00000 n
0000001041 00000 n
0000002936 00000 n
0000002959 00000 n
0000003134 00000 n
0000003210 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 12 0 R
/Size 13
>>
startxref
3271
%%EOF

View File

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

View File

@ -0,0 +1,193 @@
%PDF-1.7
1 0 obj
<< /Length 2 0 R >>
stream
1.311523 0 0.092285 -0.149414 1.218750 1.164551 d1
endstream
endobj
2 0 obj
51
endobj
3 0 obj
[ 1.311523 ]
endobj
4 0 obj
<< /Length 5 0 R >>
stream
/CIDInit /ProcSet findresource begin
12 dict begin
begincmap
/CIDSystemInfo
<< /Registry (FigmaPDF)
/Ordering (FigmaPDF)
/Supplement 0
>> def
/CMapName /A-B-C def
/CMapType 2 def
1 begincodespacerange
<00> <FF>
endcodespacerange
1 beginbfchar
<00> <DBC0DEC2>
endbfchar
endcmap
CMapName currentdict /CMap defineresource pop
end
end
endstream
endobj
5 0 obj
336
endobj
6 0 obj
<< /Subtype /Type3
/CharProcs << /C0 1 0 R >>
/Encoding << /Type /Encoding
/Differences [ 0 /C0 ]
>>
/Widths 3 0 R
/FontBBox [ 0.000000 0.000000 0.000000 0.000000 ]
/FontMatrix [ 1.000000 0.000000 0.000000 1.000000 0.000000 0.000000 ]
/Type /Font
/ToUnicode 4 0 R
/FirstChar 0
/LastChar 0
/Resources << >>
>>
endobj
7 0 obj
<< /Font << /F1 6 0 R >> >>
endobj
8 0 obj
<< /Length 9 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 -3.102768 0.104736 cm
0.376471 0.411765 0.517647 scn
1.507812 2.156250 m
h
6.515625 0.078125 m
6.929688 -0.234375 7.429688 -0.132812 8.000000 0.281250 c
12.000000 3.218750 l
16.000000 0.281250 l
16.570312 -0.132812 17.070312 -0.234375 17.484375 0.078125 c
17.890625 0.382812 17.968750 0.890625 17.750000 1.546875 c
16.164062 6.242188 l
20.203125 9.140625 l
20.765625 9.539062 21.007812 10.000000 20.843750 10.484375 c
20.679688 10.968750 20.226562 11.203125 19.531250 11.195312 c
14.585938 11.156250 l
13.078125 15.882812 l
12.867188 16.554688 12.507812 16.921875 12.000000 16.921875 c
11.492188 16.921875 11.140625 16.554688 10.921875 15.882812 c
9.414062 11.156250 l
4.468750 11.195312 l
3.773438 11.203125 3.320312 10.968750 3.156250 10.492188 c
2.984375 10.000000 3.234375 9.539062 3.796875 9.140625 c
7.835938 6.242188 l
6.250000 1.546875 l
6.031250 0.890625 6.109375 0.382812 6.515625 0.078125 c
h
8.117188 2.281250 m
8.109375 2.296875 8.109375 2.304688 8.117188 2.343750 c
9.531250 6.281250 l
9.695312 6.726562 9.664062 6.968750 9.234375 7.250000 c
5.773438 9.601562 l
5.742188 9.617188 5.726562 9.632812 5.734375 9.656250 c
5.742188 9.671875 5.757812 9.671875 5.796875 9.671875 c
9.976562 9.554688 l
10.453125 9.539062 10.671875 9.664062 10.804688 10.132812 c
11.960938 14.148438 l
11.968750 14.187500 11.984375 14.203125 12.000000 14.203125 c
12.015625 14.203125 12.031250 14.187500 12.039062 14.148438 c
13.203125 10.132812 l
13.328125 9.664062 13.546875 9.539062 14.023438 9.554688 c
18.203125 9.671875 l
18.242188 9.671875 18.265625 9.671875 18.273438 9.656250 c
18.273438 9.632812 18.265625 9.625000 18.234375 9.601562 c
14.765625 7.242188 l
14.343750 6.960938 14.304688 6.726562 14.468750 6.281250 c
15.882812 2.343750 l
15.890625 2.304688 15.890625 2.296875 15.882812 2.281250 c
15.867188 2.257812 15.851562 2.273438 15.820312 2.289062 c
12.515625 4.859375 l
12.132812 5.164062 11.867188 5.164062 11.484375 4.859375 c
8.179688 2.289062 l
8.148438 2.273438 8.132812 2.257812 8.117188 2.281250 c
h
f
n
Q
q
1.000000 0.000000 -0.000000 1.000000 -3.102768 0.104736 cm
BT
16.000000 0.000000 0.000000 16.000000 1.507812 2.156250 Tm
/F1 1.000000 Tf
[ (\000) ] TJ
ET
Q
endstream
endobj
9 0 obj
2242
endobj
10 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 17.791397 17.026611 ]
/Resources 7 0 R
/Contents 8 0 R
/Parent 11 0 R
>>
endobj
11 0 obj
<< /Kids [ 10 0 R ]
/Count 1
/Type /Pages
>>
endobj
12 0 obj
<< /Type /Catalog
/Pages 11 0 R
>>
endobj
xref
0 13
0000000000 65535 f
0000000010 00000 n
0000000117 00000 n
0000000138 00000 n
0000000169 00000 n
0000000561 00000 n
0000000583 00000 n
0000000995 00000 n
0000001041 00000 n
0000003339 00000 n
0000003362 00000 n
0000003537 00000 n
0000003613 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 12 0 R
/Size 13
>>
startxref
3674
%%EOF

View File

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

View File

@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "globe-americas.pdf",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,140 @@
%PDF-1.7
1 0 obj
<< >>
endobj
2 0 obj
<< /Length 3 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 1.333252 1.333252 cm
0.376471 0.411765 0.517647 scn
6.666667 13.333374 m
2.984678 13.333374 0.000000 10.348697 0.000000 6.666707 c
0.000000 2.984718 2.984678 0.000040 6.666667 0.000040 c
10.348656 0.000040 13.333334 2.984718 13.333334 6.666707 c
13.333334 10.348697 10.348656 13.333374 6.666667 13.333374 c
h
8.878764 3.720470 m
8.773925 3.616169 8.663979 3.506761 8.574732 3.417245 c
8.494355 3.336599 8.437634 3.237138 8.408871 3.129342 c
8.368279 2.977191 8.335485 2.823428 8.280645 2.675847 c
7.813172 1.416438 l
7.443280 1.335793 7.060484 1.290363 6.666667 1.290363 c
6.666667 2.026384 l
6.712097 2.365632 6.461290 3.001116 6.058333 3.404073 c
5.897043 3.565363 5.806452 3.784181 5.806452 4.012406 c
5.806452 4.872890 l
5.806452 5.185793 5.637903 5.473427 5.363978 5.624772 c
4.977688 5.838481 4.428226 6.137137 4.051882 6.326653 c
3.743279 6.482030 3.457796 6.679880 3.201075 6.911331 c
3.179570 6.930686 l
2.995985 7.096402 2.832988 7.283587 2.694086 7.488213 c
2.441936 7.858374 2.031183 8.467245 1.764247 8.862944 c
2.314516 10.086061 3.306183 11.068320 4.538441 11.601922 c
5.183871 11.279073 l
5.469893 11.136063 5.806452 11.343858 5.806452 11.663751 c
5.806452 11.967514 l
6.021236 12.002192 6.239785 12.024234 6.462097 12.032568 c
7.222850 11.271814 l
7.390861 11.103804 7.390861 10.831492 7.222850 10.663482 c
7.096774 10.537675 l
6.818818 10.259718 l
6.734946 10.175847 6.734946 10.039557 6.818818 9.955686 c
6.944893 9.829611 l
7.028764 9.745740 7.028764 9.609449 6.944893 9.525578 c
6.729839 9.310524 l
6.689461 9.270225 6.634737 9.247601 6.577688 9.247622 c
6.336021 9.247622 l
6.280107 9.247622 6.226344 9.225847 6.186021 9.186600 c
5.919355 8.927191 l
5.886667 8.895360 5.864938 8.853966 5.857304 8.808983 c
5.849670 8.764001 5.856525 8.717755 5.876882 8.676922 c
6.295968 7.838481 l
6.367474 7.695471 6.263441 7.527191 6.103764 7.527191 c
5.952151 7.527191 l
5.900269 7.527191 5.850269 7.546009 5.811290 7.579879 c
5.561828 7.796546 l
5.505376 7.845519 5.437150 7.878955 5.363858 7.893567 c
5.290566 7.908178 5.214734 7.903461 5.143817 7.879879 c
4.305914 7.600578 l
4.241943 7.579248 4.186307 7.538327 4.146889 7.483615 c
4.107471 7.428902 4.086270 7.363173 4.086290 7.295739 c
4.086290 7.173965 4.155107 7.062944 4.263978 7.008374 c
4.561828 6.859449 l
4.814785 6.732836 5.093817 6.666976 5.376613 6.666976 c
5.659409 6.666976 5.983871 5.933374 6.236828 5.806761 c
8.031183 5.806761 l
8.259409 5.806761 8.477958 5.716170 8.639517 5.554880 c
9.007526 5.186869 l
9.161268 5.033069 9.247619 4.824495 9.247581 4.607030 c
9.247526 4.442246 9.214915 4.279098 9.151622 4.126954 c
9.088329 3.974811 8.995601 3.836672 8.878764 3.720470 c
8.878764 3.720470 l
h
11.209678 6.176116 m
11.054032 6.215095 10.918280 6.310524 10.829302 6.444127 c
10.345968 7.169127 l
10.275246 7.275051 10.237501 7.399558 10.237501 7.526922 c
10.237501 7.654286 10.275246 7.778794 10.345968 7.884718 c
10.872581 8.674503 l
10.934946 8.767782 11.020431 8.843589 11.120968 8.893589 c
11.469893 9.068051 l
11.833333 8.344396 12.043011 7.530417 12.043011 6.666707 c
12.043011 6.433643 12.023118 6.205417 11.994086 5.980148 c
11.209678 6.176116 l
h
f
n
Q
endstream
endobj
3 0 obj
3208
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
<< /Type /Catalog
/Pages 5 0 R
>>
endobj
xref
0 7
0000000000 65535 f
0000000010 00000 n
0000000034 00000 n
0000003298 00000 n
0000003321 00000 n
0000003494 00000 n
0000003568 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
3627
%%EOF

View File

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

View File

@ -0,0 +1,174 @@
%PDF-1.7
1 0 obj
<< /Length 2 0 R >>
stream
1.093750 0 0.197266 -0.131348 0.896484 1.184082 d1
endstream
endobj
2 0 obj
51
endobj
3 0 obj
[ 1.093750 ]
endobj
4 0 obj
<< /Length 5 0 R >>
stream
/CIDInit /ProcSet findresource begin
12 dict begin
begincmap
/CIDSystemInfo
<< /Registry (FigmaPDF)
/Ordering (FigmaPDF)
/Supplement 0
>> def
/CMapName /A-B-C def
/CMapType 2 def
1 begincodespacerange
<00> <FF>
endcodespacerange
1 beginbfchar
<00> <DBC0DFA0>
endbfchar
endcmap
CMapName currentdict /CMap defineresource pop
end
end
endstream
endobj
5 0 obj
336
endobj
6 0 obj
<< /Subtype /Type3
/CharProcs << /C0 1 0 R >>
/Encoding << /Type /Encoding
/Differences [ 0 /C0 ]
>>
/Widths 3 0 R
/FontBBox [ 0.000000 0.000000 0.000000 0.000000 ]
/FontMatrix [ 1.000000 0.000000 0.000000 1.000000 0.000000 0.000000 ]
/Type /Font
/ToUnicode 4 0 R
/FirstChar 0
/LastChar 0
/Resources << >>
>>
endobj
7 0 obj
<< /Font << /F1 6 0 R >> >>
endobj
8 0 obj
<< /Length 9 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 -3.755859 1.167969 cm
0.376471 0.411765 0.517647 scn
0.796875 0.802246 m
h
5.491699 -1.167969 m
12.508301 -1.167969 l
13.672852 -1.167969 14.244141 -0.589355 14.244141 0.670410 c
14.244141 6.009766 l
14.244141 7.123047 13.782715 7.708984 12.859863 7.818848 c
12.859863 9.474121 l
12.859863 12.271973 10.970215 13.634277 9.000000 13.634277 c
7.029785 13.634277 5.140137 12.271973 5.140137 9.474121 c
5.140137 7.818848 l
4.209961 7.708984 3.755859 7.123047 3.755859 6.009766 c
3.755859 0.670410 l
3.755859 -0.589355 4.327148 -1.167969 5.491699 -1.167969 c
h
6.722168 9.598633 m
6.722168 11.202637 7.740234 12.103516 9.000000 12.103516 c
10.259766 12.103516 11.277832 11.202637 11.277832 9.598633 c
11.277832 7.840820 l
6.722168 7.840820 l
6.722168 9.598633 l
h
5.865234 0.333496 m
5.557617 0.333496 5.403809 0.479980 5.403809 0.853516 c
5.403809 5.826660 l
5.403809 6.200195 5.557617 6.332031 5.865234 6.332031 c
12.134766 6.332031 l
12.449707 6.332031 12.596191 6.200195 12.596191 5.826660 c
12.596191 0.853516 l
12.596191 0.479980 12.449707 0.333496 12.134766 0.333496 c
5.865234 0.333496 l
h
f
n
Q
q
1.000000 0.000000 -0.000000 1.000000 -3.755859 1.167969 cm
BT
15.000000 0.000000 0.000000 15.000000 0.796875 0.802246 Tm
/F1 1.000000 Tf
[ (\000) ] TJ
ET
Q
endstream
endobj
9 0 obj
1324
endobj
10 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 10.488281 14.802246 ]
/Resources 7 0 R
/Contents 8 0 R
/Parent 11 0 R
>>
endobj
11 0 obj
<< /Kids [ 10 0 R ]
/Count 1
/Type /Pages
>>
endobj
12 0 obj
<< /Type /Catalog
/Pages 11 0 R
>>
endobj
xref
0 13
0000000000 65535 f
0000000010 00000 n
0000000117 00000 n
0000000138 00000 n
0000000169 00000 n
0000000561 00000 n
0000000583 00000 n
0000000995 00000 n
0000001041 00000 n
0000002421 00000 n
0000002444 00000 n
0000002619 00000 n
0000002695 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 12 0 R
/Size 13
>>
startxref
2756
%%EOF

View File

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

View File

@ -0,0 +1,83 @@
%PDF-1.7
1 0 obj
<< >>
endobj
2 0 obj
<< /Length 3 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 1.333252 2.666626 cm
0.376471 0.411765 0.517647 scn
12.000000 10.666687 m
1.333333 10.666687 l
0.600000 10.666687 0.006667 10.066687 0.006667 9.333354 c
0.000000 1.333354 l
0.000000 0.600021 0.600000 0.000021 1.333333 0.000021 c
12.000000 0.000021 l
12.733334 0.000021 13.333334 0.600021 13.333334 1.333354 c
13.333334 9.333354 l
13.333334 10.066687 12.733334 10.666687 12.000000 10.666687 c
h
12.000000 8.000021 m
6.666667 4.666687 l
1.333333 8.000021 l
1.333333 9.333354 l
6.666667 6.000021 l
12.000000 9.333354 l
12.000000 8.000021 l
h
f
n
Q
endstream
endobj
3 0 obj
612
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
<< /Type /Catalog
/Pages 5 0 R
>>
endobj
xref
0 7
0000000000 65535 f
0000000010 00000 n
0000000034 00000 n
0000000702 00000 n
0000000724 00000 n
0000000897 00000 n
0000000971 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
1030
%%EOF

View File

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

View File

@ -0,0 +1,87 @@
%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 2.000000 1.333252 cm
0.376471 0.411765 0.517647 scn
10.119047 7.500041 m
9.511904 7.500041 l
9.511904 9.375040 l
9.511904 11.557332 7.786607 13.333374 5.666667 13.333374 c
3.546726 13.333374 1.821428 11.557332 1.821428 9.375040 c
1.821428 7.500041 l
1.214286 7.500041 l
0.543899 7.500041 0.000000 6.940145 0.000000 6.250041 c
0.000000 1.250040 l
0.000000 0.559936 0.543899 0.000040 1.214286 0.000040 c
10.119047 0.000040 l
10.789433 0.000040 11.333333 0.559936 11.333333 1.250040 c
11.333333 6.250041 l
11.333333 6.940145 10.789433 7.500041 10.119047 7.500041 c
h
7.488095 7.500041 m
3.845238 7.500041 l
3.845238 9.375040 l
3.845238 10.408895 4.662351 11.250040 5.666667 11.250040 c
6.670982 11.250040 7.488095 10.408895 7.488095 9.375040 c
7.488095 7.500041 l
h
f
n
Q
endstream
endobj
3 0 obj
836
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
<< /Type /Catalog
/Pages 5 0 R
>>
endobj
xref
0 7
0000000000 65535 f
0000000010 00000 n
0000000034 00000 n
0000000926 00000 n
0000000948 00000 n
0000001121 00000 n
0000001195 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
1254
%%EOF

View File

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

View File

@ -0,0 +1,87 @@
%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 2.000000 1.325439 cm
0.376471 0.411765 0.517647 scn
10.416220 6.674232 m
3.958164 6.674232 l
3.958164 9.359012 l
3.958164 10.390217 4.783649 11.246952 5.814855 11.257368 c
6.856477 11.267784 7.708003 10.421466 7.708003 9.382448 c
7.708003 8.965799 l
7.708003 8.619460 7.986637 8.340826 8.332976 8.340826 c
9.166274 8.340826 l
9.512613 8.340826 9.791247 8.619460 9.791247 8.965799 c
9.791247 9.382448 l
9.791247 11.569854 8.007469 13.348424 5.820063 13.340611 c
3.632657 13.332799 1.874920 11.530793 1.874920 9.343388 c
1.874920 6.674232 l
1.249946 6.674232 l
0.559872 6.674232 0.000000 6.114359 0.000000 5.424285 c
0.000000 1.257797 l
0.000000 0.567722 0.559872 0.007851 1.249946 0.007851 c
10.416220 0.007851 l
11.106295 0.007851 11.666166 0.567722 11.666166 1.257797 c
11.666166 5.424285 l
11.666166 6.114359 11.106295 6.674232 10.416220 6.674232 c
h
f
n
Q
endstream
endobj
3 0 obj
926
endobj
4 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 15.999268 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
<< /Type /Catalog
/Pages 5 0 R
>>
endobj
xref
0 7
0000000000 65535 f
0000000010 00000 n
0000000034 00000 n
0000001016 00000 n
0000001038 00000 n
0000001211 00000 n
0000001285 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
1344
%%EOF

View File

@ -42,7 +42,7 @@ extension PublicTimelineViewController {
tableView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(tableView)
tableView.backgroundColor = .systemBackground
tableView.backgroundColor = Asset.Colors.tootDark.color
NSLayoutConstraint.activate([
tableView.topAnchor.constraint(equalTo: view.topAnchor),
tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
@ -71,7 +71,7 @@ extension PublicTimelineViewController {
}
} receiveValue: { response in
let tootsIDs = response.value.map { $0.id }
self.viewModel.tweetIDs.value = tootsIDs
self.viewModel.tootIDs.value = tootsIDs
}
.store(in: &viewModel.disposeBag)
}

View File

@ -36,7 +36,7 @@ extension PublicTimelineViewModel: NSFetchedResultsControllerDelegate {
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChangeContentWith snapshot: NSDiffableDataSourceSnapshotReference) {
os_log("%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function)
let indexes = tweetIDs.value
let indexes = tootIDs.value
let toots = fetchedResultsController.fetchedObjects ?? []
guard toots.count == indexes.count else { return }

View File

@ -27,7 +27,7 @@ class PublicTimelineViewModel: NSObject {
// output
var diffableDataSource: UITableViewDiffableDataSource<TimelineSection, Item>?
let tweetIDs = CurrentValueSubject<[String], Never>([])
let tootIDs = CurrentValueSubject<[String], Never>([])
let items = CurrentValueSubject<[Item], Never>([])
var cellFrameCache = NSCache<NSNumber, NSValue>()
@ -67,7 +67,7 @@ class PublicTimelineViewModel: NSObject {
}
.store(in: &disposeBag)
tweetIDs
tootIDs
.receive(on: DispatchQueue.main)
.sink { [weak self] ids in
guard let self = self else { return }

View File

@ -0,0 +1,18 @@
//
// HitTestExpandedButton.swift
// Mastodon
//
// Created by sxiaojian on 2021/2/1.
//
import UIKit
final class HitTestExpandedButton: UIButton {
var expandEdgeInsets = UIEdgeInsets(top: -10, left: -10, bottom: -10, right: -10)
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
return bounds.inset(by: expandEdgeInsets).contains(point)
}
}

View File

@ -13,33 +13,60 @@ final class TimelinePostView: UIView {
static let avatarImageViewSize = CGSize(width: 44, height: 44)
let avatarImageView = UIImageView()
let avatarImageView: UIImageView = {
let imageView = UIImageView()
imageView.layer.masksToBounds = true
imageView.layer.cornerRadius = avatarImageViewSize.width/2
imageView.layer.cornerCurve = .continuous
imageView.contentMode = .scaleAspectFill
return imageView
}()
let visibilityImageView: UIImageView = {
let imageView = UIImageView(image: Asset.TootTimeline.global.image.withRenderingMode(.alwaysTemplate))
imageView.tintColor = Asset.Colors.tootGray.color
return imageView
}()
let lockImageView: UIImageView = {
let imageview = UIImageView(image: Asset.TootTimeline.textlock.image.withRenderingMode(.alwaysTemplate))
imageview.tintColor = Asset.Colors.tootGray.color
imageview.isHidden = true
return imageview
}()
let nameLabel: UILabel = {
let label = UILabel()
label.font = .preferredFont(forTextStyle: .headline)
label.textColor = .label
label.font = UIFont(name: "Roboto-Medium", size: 14)
label.textColor = Asset.Colors.tootWhite.color
label.text = "Alice"
return label
}()
let usernameLabel: UILabel = {
let label = UILabel()
label.font = .preferredFont(forTextStyle: .subheadline)
label.textColor = .secondaryLabel
label.textColor = Asset.Colors.tootGray.color
label.font = UIFont(name: "Roboto-Regular", size: 14)
label.text = "@alice"
return label
}()
let dateLabel: UILabel = {
let label = UILabel()
label.font = UIFont.preferredMonospacedFont(withTextStyle: .callout)
label.font = UIFont(name: "Roboto-Regular", size: 14)
label.textAlignment = UIApplication.shared.userInterfaceLayoutDirection == .rightToLeft ? .left : .right
label.textColor = .secondaryLabel
label.textColor = Asset.Colors.tootGray.color
label.text = "1d"
return label
}()
let actionToolbarContainer: ActionToolbarContainer = {
let actionToolbarContainer = ActionToolbarContainer()
actionToolbarContainer.configure(for: .inline)
return actionToolbarContainer
}()
let mainContainerStackView = UIStackView()
let activeTextLabel = ActiveLabel(style: .default)
@ -59,7 +86,7 @@ final class TimelinePostView: UIView {
extension TimelinePostView {
func _init() {
// container: [retweet | post]
// container: [retoot | post]
let containerStackView = UIStackView()
containerStackView.axis = .vertical
containerStackView.spacing = 8
@ -73,7 +100,7 @@ extension TimelinePostView {
bottomAnchor.constraint(equalTo: containerStackView.bottomAnchor),
])
// post container: [user avatar | tweet container]
// post container: [user avatar | toot container]
let postContainerStackView = UIStackView()
containerStackView.addArrangedSubview(postContainerStackView)
postContainerStackView.axis = .horizontal
@ -88,36 +115,47 @@ extension TimelinePostView {
avatarImageView.heightAnchor.constraint(equalToConstant: TimelinePostView.avatarImageViewSize.height).priority(.required - 1),
])
// tweet container: [user meta container | main container | action toolbar]
let tweetContainerStackView = UIStackView()
postContainerStackView.addArrangedSubview(tweetContainerStackView)
tweetContainerStackView.axis = .vertical
tweetContainerStackView.spacing = 2
// toot container: [user meta container | main container | action toolbar]
let tootContainerStackView = UIStackView()
postContainerStackView.addArrangedSubview(tootContainerStackView)
tootContainerStackView.axis = .vertical
tootContainerStackView.spacing = 2
// user meta container: [name | lock | username | date | menu]
// user meta container: [name | lock | username | visiablity | date ]
let userMetaContainerStackView = UIStackView()
tweetContainerStackView.addArrangedSubview(userMetaContainerStackView)
tootContainerStackView.addArrangedSubview(userMetaContainerStackView)
userMetaContainerStackView.axis = .horizontal
userMetaContainerStackView.alignment = .center
userMetaContainerStackView.spacing = 6
userMetaContainerStackView.addArrangedSubview(nameLabel)
userMetaContainerStackView.addArrangedSubview(lockImageView)
userMetaContainerStackView.addArrangedSubview(usernameLabel)
userMetaContainerStackView.addArrangedSubview(visibilityImageView)
userMetaContainerStackView.addArrangedSubview(dateLabel)
nameLabel.setContentHuggingPriority(.defaultHigh + 10, for: .horizontal)
nameLabel.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
usernameLabel.setContentHuggingPriority(.defaultHigh + 3, for: .horizontal)
lockImageView.setContentCompressionResistancePriority(.defaultHigh + 1, for: .horizontal)
lockImageView.setContentHuggingPriority(.defaultHigh + 1, for: .horizontal)
usernameLabel.setContentHuggingPriority(.defaultHigh - 3, for: .horizontal)
usernameLabel.setContentCompressionResistancePriority(.defaultHigh - 1, for: .horizontal)
dateLabel.setContentHuggingPriority(.defaultLow, for: .horizontal)
visibilityImageView.setContentCompressionResistancePriority(.defaultHigh + 1, for: .horizontal)
visibilityImageView.setContentHuggingPriority(.defaultHigh + 1, for: .horizontal)
dateLabel.setContentHuggingPriority(.defaultHigh, for: .horizontal)
dateLabel.setContentCompressionResistancePriority(.required - 2, for: .horizontal)
// main container: [text | image / video | quote | geo]
tweetContainerStackView.addArrangedSubview(mainContainerStackView)
tootContainerStackView.addArrangedSubview(mainContainerStackView)
mainContainerStackView.axis = .vertical
mainContainerStackView.spacing = 8
activeTextLabel.translatesAutoresizingMaskIntoConstraints = false
mainContainerStackView.addArrangedSubview(activeTextLabel)
activeTextLabel.setContentCompressionResistancePriority(.required - 2, for: .vertical)
// action toolbar
actionToolbarContainer.translatesAutoresizingMaskIntoConstraints = false
tootContainerStackView.addArrangedSubview(actionToolbarContainer)
actionToolbarContainer.setContentCompressionResistancePriority(.defaultLow, for: .vertical)
}

View File

@ -17,8 +17,8 @@ protocol TimelinePostTableViewCellDelegate: class {
final class TimelinePostTableViewCell: UITableViewCell {
static let verticalMargin: CGFloat = 16 // without retweet indicator
static let verticalMarginAlt: CGFloat = 8 // with retweet indicator
static let verticalMargin: CGFloat = 16 // without retoot indicator
static let verticalMarginAlt: CGFloat = 8 // with retoot indicator
weak var delegate: TimelinePostTableViewCellDelegate?
@ -50,6 +50,8 @@ final class TimelinePostTableViewCell: UITableViewCell {
extension TimelinePostTableViewCell {
private func _init() {
self.backgroundColor = Asset.Colors.tootDark.color
self.selectionStyle = .none
timelinePostView.translatesAutoresizingMaskIntoConstraints = false
timelinePostViewTopLayoutConstraint = timelinePostView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: TimelinePostTableViewCell.verticalMargin)
contentView.addSubview(timelinePostView)

View File

@ -0,0 +1,201 @@
//
// ActionToolBarContainer.swift
// Mastodon
//
// Created by sxiaojian on 2021/2/1.
//
import os.log
import UIKit
protocol ActionToolbarContainerDelegate: class {
func actionToolbarContainer(_ actionToolbarContainer: ActionToolbarContainer, replayButtonDidPressed sender: UIButton)
func actionToolbarContainer(_ actionToolbarContainer: ActionToolbarContainer, retootButtonDidPressed sender: UIButton)
func actionToolbarContainer(_ actionToolbarContainer: ActionToolbarContainer, starButtonDidPressed sender: UIButton)
func actionToolbarContainer(_ actionToolbarContainer: ActionToolbarContainer, bookmarkButtonDidPressed sender: UIButton)
func actionToolbarContainer(_ actionToolbarContainer: ActionToolbarContainer, moreButtonDidPressed sender: UIButton)
}
final class ActionToolbarContainer: UIView {
let replyButton = HitTestExpandedButton()
let retootButton = HitTestExpandedButton()
let starButton = HitTestExpandedButton()
let bookmartButton = HitTestExpandedButton()
let moreButton = HitTestExpandedButton()
var isstarButtonHighlight: Bool = false {
didSet { isstarButtonHighlightStateDidChange(to: isstarButtonHighlight) }
}
weak var delegate: ActionToolbarContainerDelegate?
private let container = UIStackView()
private var style: Style?
override init(frame: CGRect) {
super.init(frame: frame)
_init()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
_init()
}
}
extension ActionToolbarContainer {
private func _init() {
container.translatesAutoresizingMaskIntoConstraints = false
addSubview(container)
NSLayoutConstraint.activate([
container.topAnchor.constraint(equalTo: topAnchor),
container.leadingAnchor.constraint(equalTo: leadingAnchor),
trailingAnchor.constraint(equalTo: container.trailingAnchor),
bottomAnchor.constraint(equalTo: container.bottomAnchor),
])
replyButton.addTarget(self, action: #selector(ActionToolbarContainer.replyButtonDidPressed(_:)), for: .touchUpInside)
retootButton.addTarget(self, action: #selector(ActionToolbarContainer.retootButtonDidPressed(_:)), for: .touchUpInside)
starButton.addTarget(self, action: #selector(ActionToolbarContainer.starButtonDidPressed(_:)), for: .touchUpInside)
bookmartButton.addTarget(self, action: #selector(ActionToolbarContainer.bookmarkButtonDidPressed(_:)), for: .touchUpInside)
moreButton.addTarget(self, action: #selector(ActionToolbarContainer.moreButtonDidPressed(_:)), for: .touchUpInside)
}
}
extension ActionToolbarContainer {
enum Style {
case inline
case plain
var buttonTitleImagePadding: CGFloat {
switch self {
case .inline: return 4.0
case .plain: return 0
}
}
}
func configure(for style: Style) {
guard needsConfigure(for: style) else {
return
}
self.style = style
container.arrangedSubviews.forEach { subview in
container.removeArrangedSubview(subview)
subview.removeFromSuperview()
}
let buttons = [replyButton, retootButton, starButton,bookmartButton, moreButton]
buttons.forEach { button in
button.tintColor = Asset.Colors.tootGray.color
button.titleLabel?.font = .monospacedDigitSystemFont(ofSize: 12, weight: .regular)
button.setTitle("", for: .normal)
button.setTitleColor(.secondaryLabel, for: .normal)
button.setInsets(forContentPadding: .zero, imageTitlePadding: style.buttonTitleImagePadding)
}
switch style {
case .inline:
buttons.forEach { button in
button.contentHorizontalAlignment = .leading
}
replyButton.setImage(Asset.ToolBar.reply.image.withRenderingMode(.alwaysTemplate), for: .normal)
retootButton.setImage(Asset.ToolBar.retoot.image.withRenderingMode(.alwaysTemplate), for: .normal)
starButton.setImage(Asset.ToolBar.star.image.withRenderingMode(.alwaysTemplate), for: .normal)
bookmartButton.setImage(Asset.ToolBar.bookmark.image.withRenderingMode(.alwaysTemplate), for: .normal)
moreButton.setImage(Asset.ToolBar.more.image.withRenderingMode(.alwaysTemplate), for: .normal)
container.axis = .horizontal
container.distribution = .fill
replyButton.translatesAutoresizingMaskIntoConstraints = false
retootButton.translatesAutoresizingMaskIntoConstraints = false
starButton.translatesAutoresizingMaskIntoConstraints = false
bookmartButton.translatesAutoresizingMaskIntoConstraints = false
moreButton.translatesAutoresizingMaskIntoConstraints = false
container.addArrangedSubview(replyButton)
container.addArrangedSubview(retootButton)
container.addArrangedSubview(starButton)
container.addArrangedSubview(bookmartButton)
container.addArrangedSubview(moreButton)
NSLayoutConstraint.activate([
replyButton.heightAnchor.constraint(equalToConstant: 40).priority(.defaultHigh),
replyButton.heightAnchor.constraint(equalTo: retootButton.heightAnchor).priority(.defaultHigh),
replyButton.heightAnchor.constraint(equalTo: starButton.heightAnchor).priority(.defaultHigh),
replyButton.heightAnchor.constraint(equalTo: moreButton.heightAnchor).priority(.defaultHigh),
replyButton.heightAnchor.constraint(equalTo: bookmartButton.heightAnchor).priority(.defaultHigh),
replyButton.widthAnchor.constraint(equalTo: retootButton.widthAnchor).priority(.defaultHigh),
replyButton.widthAnchor.constraint(equalTo: starButton.widthAnchor).priority(.defaultHigh),
replyButton.widthAnchor.constraint(equalTo: bookmartButton.widthAnchor).priority(.defaultHigh),
])
moreButton.setContentHuggingPriority(.defaultHigh, for: .horizontal)
moreButton.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
case .plain:
buttons.forEach { button in
button.contentHorizontalAlignment = .center
}
replyButton.setImage(Asset.ToolBar.reply.image.withRenderingMode(.alwaysTemplate), for: .normal)
retootButton.setImage(Asset.ToolBar.retoot.image.withRenderingMode(.alwaysTemplate), for: .normal)
starButton.setImage(Asset.ToolBar.bookmark.image.withRenderingMode(.alwaysTemplate), for: .normal)
bookmartButton.setImage(Asset.ToolBar.bookmark.image.withRenderingMode(.alwaysTemplate), for: .normal)
container.axis = .horizontal
container.spacing = 8
container.distribution = .fillEqually
container.addArrangedSubview(replyButton)
container.addArrangedSubview(retootButton)
container.addArrangedSubview(starButton)
container.addArrangedSubview(bookmartButton)
}
}
private func needsConfigure(for style: Style) -> Bool {
guard let oldStyle = self.style else { return true }
return oldStyle != style
}
private func isstarButtonHighlightStateDidChange(to isHighlight: Bool) {
let tintColor = isHighlight ? Asset.Colors.likeOrange.color : Asset.Colors.tootGray.color
starButton.tintColor = tintColor
starButton.setTitleColor(tintColor, for: .normal)
starButton.setTitleColor(tintColor, for: .highlighted)
}
}
extension ActionToolbarContainer {
@objc private func replyButtonDidPressed(_ sender: UIButton) {
os_log("%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function)
delegate?.actionToolbarContainer(self, replayButtonDidPressed: sender)
}
@objc private func retootButtonDidPressed(_ sender: UIButton) {
os_log("%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function)
delegate?.actionToolbarContainer(self, retootButtonDidPressed: sender)
}
@objc private func starButtonDidPressed(_ sender: UIButton) {
os_log("%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function)
delegate?.actionToolbarContainer(self, starButtonDidPressed: sender)
}
@objc private func moreButtonDidPressed(_ sender: UIButton) {
os_log("%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function)
delegate?.actionToolbarContainer(self, moreButtonDidPressed: sender)
}
@objc private func bookmarkButtonDidPressed(_ sender: UIButton) {
os_log("%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function)
delegate?.actionToolbarContainer(self, bookmarkButtonDidPressed: sender)
}
}

View File

@ -16,10 +16,6 @@ extension APIService {
static let publicTimelineRequestWindowInSec: TimeInterval = 15 * 60
// incoming tweet - retweet relationship could be:
// A1. incoming tweet NOT in local timeline, retweet NOT in local (never see tweet and retweet)
// A2. incoming tweet NOT in local timeline, retweet in local (never see tweet but saw retweet before)
// A3. incoming tweet in local timeline, retweet MUST in local (saw tweet before)
func publicTimeline(
count: Int = 20,
domain: String

View File

@ -23,11 +23,45 @@ extension APIService.Persist {
persistType: PersistTimelineType
) -> AnyPublisher<Result<Void, Error>, Never> {
return managedObjectContext.performChanges {
let toots = response.value
let _ = toots.map {
let toot = response.value
let _ = toot.map {
let userProperty = MastodonUser.Property(id: $0.account.id, domain: domain, acct: $0.account.acct, username: $0.account.username, displayName: $0.account.displayName,avatar: $0.account.avatar,avatarStatic: $0.account.avatarStatic, createdAt: $0.createdAt, networkDate: $0.createdAt)
let author = MastodonUser.insert(into: managedObjectContext, property: userProperty)
let tootProperty = Toot.Property(id: $0.id, domain: domain, content: $0.content, createdAt: $0.createdAt, networkDate: $0.createdAt)
let metions = $0.mentions?.compactMap({ (mention) -> Mention in
Mention.insert(into: managedObjectContext, property: Mention.Property(id: mention.id, username: mention.username, acct: mention.acct, url: mention.url))
})
let emojis = $0.emojis?.compactMap({ (emoji) -> Emoji in
Emoji.insert(into: managedObjectContext, property: Emoji.Property(shortcode: emoji.shortcode, url: emoji.url, staticURL: emoji.staticURL, visibleInPicker: emoji.visibleInPicker))
})
let tootProperty = Toot.Property(
domain: domain,
id: $0.id,
uri: $0.uri,
createdAt: $0.createdAt,
content: $0.content,
visibility: $0.visibility,
sensitive: $0.sensitive ?? false,
spoilerText: $0.spoilerText,
mentions: metions,
emojis: emojis,
reblogsCount: $0.reblogsCount,
favouritesCount: $0.favouritesCount,
repliesCount: $0.repliesCount ?? 0,
url: $0.uri,
inReplyToID: $0.inReplyToID,
inReplyToAccountID: $0.inReplyToAccountID,
reblog: nil, //TODO
language: $0.language,
text: $0.text,
favourited: $0.favourited ?? false,
reblogged: $0.reblogged ?? false,
muted: $0.muted ?? false,
bookmarked: $0.bookmarked ?? false,
pinned: $0.pinned ?? false,
updatedAt: response.networkDate,
deletedAt: nil,
author: author,
homeTimelineIndexes: nil)
Toot.insert(into: managedObjectContext, property: tootProperty, author: author)
}
}.eraseToAnyPublisher()

View File

@ -9,7 +9,7 @@ target 'Mastodon' do
# misc
pod 'SwiftGen', '~> 6.4.0'
pod 'DateToolsSwift', '~> 5.0.0'
pod 'ActiveLabel', git: 'https://github.com/ReticentJohn/ActiveLabel.swift.git', branch: 'master'
pod 'Kanna', '~> 5.2.2'
target 'MastodonTests' do
inherit! :search_paths
# Pods for testing

View File

@ -1,33 +1,24 @@
PODS:
- ActiveLabel (1.1.0)
- DateToolsSwift (5.0.0)
- Kanna (5.2.4)
- SwiftGen (6.4.0)
DEPENDENCIES:
- ActiveLabel (from `https://github.com/ReticentJohn/ActiveLabel.swift.git`, branch `master`)
- DateToolsSwift (~> 5.0.0)
- Kanna (~> 5.2.2)
- SwiftGen (~> 6.4.0)
SPEC REPOS:
trunk:
- DateToolsSwift
- Kanna
- SwiftGen
EXTERNAL SOURCES:
ActiveLabel:
:branch: master
:git: https://github.com/ReticentJohn/ActiveLabel.swift.git
CHECKOUT OPTIONS:
ActiveLabel:
:commit: 01dd31cbbd1b3fec33b0c024b011e6b932794eff
:git: https://github.com/ReticentJohn/ActiveLabel.swift.git
SPEC CHECKSUMS:
ActiveLabel: 5e3f4de79a1952d4604b845a0610d4776e4b82b3
DateToolsSwift: 4207ada6ad615d8dc076323d27037c94916dbfa6
Kanna: b9d00d7c11428308c7f95e1f1f84b8205f567a8f
SwiftGen: 67860cc7c3cfc2ed25b9b74cfd55495fc89f9108
PODFILE CHECKSUM: 7fd5233d3180e2f7f67c96a28abbc20c6eddac93
PODFILE CHECKSUM: 8b24099ae9ac02698d464cc508af9550352c85cb
COCOAPODS: 1.10.1