Compare commits

..

3 Commits

5 changed files with 73 additions and 16 deletions

View File

@ -12,19 +12,49 @@ public class Instance: Decodable {
public let uri: String
public let title: String
public let description: String
public let email: String
public let email: String?
public let version: String
public let urls: [String: URL]
// pleroma doesn't currently implement these
public let thumbnail: URL?
public let languages: [String]?
public let stats: Stats?
// pleroma doesn't currently implement these
public let contactAccount: Account?
// MARK: Unofficial additions to the Mastodon API.
public let stats: Stats?
public let thumbnail: URL?
public let maxStatusCharacters: Int?
// we need a custom decoder, because all API-compatible implementations don't return some data in the same format
public required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.uri = try container.decode(String.self, forKey: .uri)
self.title = try container.decode(String.self, forKey: .title)
self.description = try container.decode(String.self, forKey: .description)
self.email = try container.decodeIfPresent(String.self, forKey: .email)
self.version = try container.decode(String.self, forKey: .version)
if let urls = try? container.decodeIfPresent([String: URL].self, forKey: .urls) {
self.urls = urls
} else {
self.urls = [:]
}
self.languages = try? container.decodeIfPresent([String].self, forKey: .languages)
self.contactAccount = try? container.decodeIfPresent(Account.self, forKey: .contactAccount)
self.stats = try? container.decodeIfPresent(Stats.self, forKey: .stats)
self.thumbnail = try? container.decodeIfPresent(URL.self, forKey: .thumbnail)
if let maxStatusCharacters = try? container.decodeIfPresent(Int.self, forKey: .maxStatusCharacters) {
self.maxStatusCharacters = maxStatusCharacters
} else if let str = try? container.decodeIfPresent(String.self, forKey: .maxStatusCharacters),
let maxStatusCharacters = Int(str, radix: 10) {
self.maxStatusCharacters = maxStatusCharacters
} else {
self.maxStatusCharacters = nil
}
}
private enum CodingKeys: String, CodingKey {
case uri
case title
@ -32,11 +62,12 @@ public class Instance: Decodable {
case email
case version
case urls
case thumbnail
case languages
case stats
case contactAccount = "contact_account"
case stats
case thumbnail
case maxStatusCharacters = "max_toot_chars"
}
}

View File

@ -118,6 +118,7 @@
D667E5F12134D5050057A976 /* UIViewController+Delegates.swift in Sources */ = {isa = PBXBuildFile; fileRef = D667E5F02134D5050057A976 /* UIViewController+Delegates.swift */; };
D667E5F52135BCD50057A976 /* ConversationTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D667E5F42135BCD50057A976 /* ConversationTableViewController.swift */; };
D667E5F82135C3040057A976 /* Mastodon+Equatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D667E5F72135C3040057A976 /* Mastodon+Equatable.swift */; };
D66A77BB233838DC0058F1EC /* UIFont+Traits.swift in Sources */ = {isa = PBXBuildFile; fileRef = D66A77BA233838DC0058F1EC /* UIFont+Traits.swift */; };
D6757A7C2157E01900721E32 /* XCBManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6757A7B2157E01900721E32 /* XCBManager.swift */; };
D6757A7E2157E02600721E32 /* XCBRequestSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6757A7D2157E02600721E32 /* XCBRequestSpec.swift */; };
D6757A822157E8FA00721E32 /* XCBSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6757A812157E8FA00721E32 /* XCBSession.swift */; };
@ -376,6 +377,7 @@
D667E5F02134D5050057A976 /* UIViewController+Delegates.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+Delegates.swift"; sourceTree = "<group>"; };
D667E5F42135BCD50057A976 /* ConversationTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationTableViewController.swift; sourceTree = "<group>"; };
D667E5F72135C3040057A976 /* Mastodon+Equatable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Mastodon+Equatable.swift"; sourceTree = "<group>"; };
D66A77BA233838DC0058F1EC /* UIFont+Traits.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIFont+Traits.swift"; sourceTree = "<group>"; };
D6757A7B2157E01900721E32 /* XCBManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCBManager.swift; sourceTree = "<group>"; };
D6757A7D2157E02600721E32 /* XCBRequestSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCBRequestSpec.swift; sourceTree = "<group>"; };
D6757A812157E8FA00721E32 /* XCBSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCBSession.swift; sourceTree = "<group>"; };
@ -893,6 +895,7 @@
D6333B782139AEFD00CE884A /* Date+TimeAgo.swift */,
D67C57AE21E28EAD00C3118B /* Array+Uniques.swift */,
0450531E22B0097E00100BA2 /* Timline+UI.swift */,
D66A77BA233838DC0058F1EC /* UIFont+Traits.swift */,
);
path = Extensions;
sourceTree = "<group>";
@ -1559,6 +1562,7 @@
D6D58DF922074B74009C8DD9 /* LinkLabel.swift in Sources */,
0454DDAF22B462EF00B8BB8E /* GalleryExpandAnimationController.swift in Sources */,
D6A3BC8A2321F79B00FD64D5 /* AccountTableViewCell.swift in Sources */,
D66A77BB233838DC0058F1EC /* UIFont+Traits.swift in Sources */,
D68FEC4F232C5BC300C84F23 /* SegmentedPageViewController.swift in Sources */,
0450531F22B0097E00100BA2 /* Timline+UI.swift in Sources */,
D667E5F52135BCD50057A976 /* ConversationTableViewController.swift in Sources */,

View File

@ -0,0 +1,21 @@
//
// UIFont+Traits.swift
// Tusker
//
// Created by Shadowfacts on 9/22/19.
// Copyright © 2019 Shadowfacts. All rights reserved.
//
import UIKit
extension UIFont {
func addingTraits(_ traits: UIFontDescriptor.SymbolicTraits, size: CGFloat? = nil) -> UIFont? {
let descriptor = self.fontDescriptor
guard let newDescriptor = descriptor.withSymbolicTraits([descriptor.symbolicTraits, traits]) else {
return nil
}
return UIFont(descriptor: newDescriptor, size: size ?? self.pointSize)
}
}

View File

@ -1,11 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14810.11" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14868" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait" appearance="light"/>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14766.13"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14824"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
<capability name="iOS 13.0 system colors" minToolsVersion="11.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
@ -14,7 +13,7 @@
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="u7I-sx-kUe">
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="u7I-sx-kUe">
<rect key="frame" x="8" y="293.5" width="80" height="80"/>
<constraints>
<constraint firstAttribute="height" constant="80" id="CgF-eC-We6"/>
@ -34,7 +33,7 @@
</button>
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" scrollEnabled="NO" textAlignment="natural" translatesAutoresizingMaskIntoConstraints="NO" id="O6b-Zs-u8r">
<rect key="frame" x="96" y="0.0" width="241" height="667"/>
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<constraints>
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="80" id="GsE-uM-fhe"/>
</constraints>
@ -49,13 +48,13 @@
</label>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="0h4-wv-2R8">
<rect key="frame" x="0.0" y="0.0" width="375" height="1"/>
<color key="backgroundColor" cocoaTouchSystemColor="separatorColor"/>
<color key="backgroundColor" systemColor="separatorColor" red="0.23529411764705882" green="0.23529411764705882" blue="0.2627450980392157" alpha="0.28999999999999998" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="height" constant="1" id="aQa-2T-uYY"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<constraints>
<constraint firstItem="vUN-kp-3ea" firstAttribute="bottom" secondItem="O6b-Zs-u8r" secondAttribute="bottom" id="3sv-wo-gxe"/>
<constraint firstItem="u7I-sx-kUe" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="centerY" id="5Qs-i7-glv"/>

View File

@ -128,9 +128,11 @@ class ContentLabel: LinkLabel {
case "p":
attributed.append(NSAttributedString(string: "\n\n"))
case "em", "i":
attributed.addAttribute(.font, value: UIFont.italicSystemFont(ofSize: font!.pointSize), range: attributed.fullRange)
let currentFont: UIFont = attributed.attribute(.font, at: 0, effectiveRange: nil) as? UIFont ?? self.font
attributed.addAttribute(.font, value: currentFont.addingTraits(.traitItalic), range: attributed.fullRange)
case "strong", "b":
attributed.addAttribute(.font, value: UIFont.boldSystemFont(ofSize: font!.pointSize), range: attributed.fullRange)
let currentFont: UIFont = attributed.attribute(.font, at: 0, effectiveRange: nil) as? UIFont ?? self.font
attributed.addAttribute(.font, value: currentFont.addingTraits(.traitBold), range: attributed.fullRange)
case "del":
attributed.addAttribute(.strikethroughStyle, value: NSUnderlineStyle.single.rawValue, range: attributed.fullRange)
case "code":