mirror of
https://github.com/metabolist/metatext.git
synced 2024-11-22 00:01:00 +00:00
wip
This commit is contained in:
parent
2ca92ed098
commit
9b59e2fbea
110 changed files with 770 additions and 896 deletions
|
@ -3,12 +3,13 @@
|
||||||
import Foundation
|
import Foundation
|
||||||
import Combine
|
import Combine
|
||||||
import GRDB
|
import GRDB
|
||||||
|
import Mastodon
|
||||||
|
|
||||||
// swiftlint:disable file_length
|
// swiftlint:disable file_length
|
||||||
struct ContentDatabase {
|
struct ContentDatabase {
|
||||||
private let databaseQueue: DatabaseQueue
|
private let databaseQueue: DatabaseQueue
|
||||||
|
|
||||||
init(identityID: UUID, environment: AppEnvironment) throws {
|
init(identityID: UUID, inMemory: Bool) throws {
|
||||||
guard
|
guard
|
||||||
let documentsDirectory = NSSearchPathForDirectoriesInDomains(
|
let documentsDirectory = NSSearchPathForDirectoriesInDomains(
|
||||||
.documentDirectory,
|
.documentDirectory,
|
||||||
|
@ -16,7 +17,7 @@ struct ContentDatabase {
|
||||||
.first
|
.first
|
||||||
else { throw DatabaseError.documentsDirectoryNotFound }
|
else { throw DatabaseError.documentsDirectoryNotFound }
|
||||||
|
|
||||||
if environment.inMemoryContent {
|
if inMemory {
|
||||||
databaseQueue = DatabaseQueue()
|
databaseQueue = DatabaseQueue()
|
||||||
} else {
|
} else {
|
||||||
databaseQueue = try DatabaseQueue(path: "\(documentsDirectory)/\(identityID.uuidString).sqlite3")
|
databaseQueue = try DatabaseQueue(path: "\(documentsDirectory)/\(identityID.uuidString).sqlite3")
|
||||||
|
@ -24,7 +25,6 @@ struct ContentDatabase {
|
||||||
|
|
||||||
try Self.migrate(databaseQueue)
|
try Self.migrate(databaseQueue)
|
||||||
try Self.createTemporaryTables(databaseQueue)
|
try Self.createTemporaryTables(databaseQueue)
|
||||||
Self.attributedStringCache = environment.attributedStringCache
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,8 +131,6 @@ extension ContentDatabase {
|
||||||
}
|
}
|
||||||
|
|
||||||
private extension ContentDatabase {
|
private extension ContentDatabase {
|
||||||
static var attributedStringCache: AttributedStringCache?
|
|
||||||
|
|
||||||
// swiftlint:disable function_body_length
|
// swiftlint:disable function_body_length
|
||||||
static func migrate(_ writer: DatabaseWriter) throws {
|
static func migrate(_ writer: DatabaseWriter) throws {
|
||||||
var migrator = DatabaseMigrator()
|
var migrator = DatabaseMigrator()
|
||||||
|
@ -244,21 +242,11 @@ private extension ContentDatabase {
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Account: TableRecord, FetchableRecord, PersistableRecord {
|
extension Account: TableRecord, FetchableRecord, PersistableRecord {
|
||||||
static var databaseDecodingUserInfo: [CodingUserInfoKey: Any] {
|
public static func databaseJSONDecoder(for column: String) -> JSONDecoder {
|
||||||
var userInfo = [CodingUserInfoKey: Any]()
|
|
||||||
|
|
||||||
if let attributedStringCache = ContentDatabase.attributedStringCache {
|
|
||||||
userInfo[.attributedStringCache] = attributedStringCache
|
|
||||||
}
|
|
||||||
|
|
||||||
return userInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
static func databaseJSONDecoder(for column: String) -> JSONDecoder {
|
|
||||||
MastodonDecoder()
|
MastodonDecoder()
|
||||||
}
|
}
|
||||||
|
|
||||||
static func databaseJSONEncoder(for column: String) -> JSONEncoder {
|
public static func databaseJSONEncoder(for column: String) -> JSONEncoder {
|
||||||
MastodonEncoder()
|
MastodonEncoder()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -282,7 +270,7 @@ extension Timeline: StatusCollection {
|
||||||
case id, listTitle
|
case id, listTitle
|
||||||
}
|
}
|
||||||
|
|
||||||
init(row: Row) {
|
public init(row: Row) {
|
||||||
switch (row[Columns.id] as String, row[Columns.listTitle] as String?) {
|
switch (row[Columns.id] as String, row[Columns.listTitle] as String?) {
|
||||||
case (Timeline.home.id, _):
|
case (Timeline.home.id, _):
|
||||||
self = .home
|
self = .home
|
||||||
|
@ -297,7 +285,7 @@ extension Timeline: StatusCollection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func encode(to container: inout PersistenceContainer) {
|
public func encode(to container: inout PersistenceContainer) {
|
||||||
container[Columns.id] = id
|
container[Columns.id] = id
|
||||||
|
|
||||||
if case let .list(list) = self {
|
if case let .list(list) = self {
|
||||||
|
@ -336,11 +324,11 @@ private extension Timeline {
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Filter: TableRecord, FetchableRecord, PersistableRecord {
|
extension Filter: TableRecord, FetchableRecord, PersistableRecord {
|
||||||
static func databaseJSONDecoder(for column: String) -> JSONDecoder {
|
public static func databaseJSONDecoder(for column: String) -> JSONDecoder {
|
||||||
MastodonDecoder()
|
MastodonDecoder()
|
||||||
}
|
}
|
||||||
|
|
||||||
static func databaseJSONEncoder(for column: String) -> JSONEncoder {
|
public static func databaseJSONEncoder(for column: String) -> JSONEncoder {
|
||||||
MastodonEncoder()
|
MastodonEncoder()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -464,16 +452,6 @@ private extension StoredStatus {
|
||||||
}
|
}
|
||||||
|
|
||||||
extension StoredStatus: TableRecord, FetchableRecord, PersistableRecord {
|
extension StoredStatus: TableRecord, FetchableRecord, PersistableRecord {
|
||||||
static var databaseDecodingUserInfo: [CodingUserInfoKey: Any] {
|
|
||||||
var userInfo = [CodingUserInfoKey: Any]()
|
|
||||||
|
|
||||||
if let attributedStringCache = ContentDatabase.attributedStringCache {
|
|
||||||
userInfo[.attributedStringCache] = attributedStringCache
|
|
||||||
}
|
|
||||||
|
|
||||||
return userInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
static func databaseJSONDecoder(for column: String) -> JSONDecoder {
|
static func databaseJSONDecoder(for column: String) -> JSONDecoder {
|
||||||
MastodonDecoder()
|
MastodonDecoder()
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
import Foundation
|
import Foundation
|
||||||
import Combine
|
import Combine
|
||||||
import GRDB
|
import GRDB
|
||||||
|
import Mastodon
|
||||||
|
|
||||||
enum IdentityDatabaseError: Error {
|
enum IdentityDatabaseError: Error {
|
||||||
case identityNotFound
|
case identityNotFound
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
import Combine
|
import Combine
|
||||||
|
import Mastodon
|
||||||
|
|
||||||
// swiftlint:disable force_try
|
// swiftlint:disable force_try
|
||||||
private let decoder = MastodonDecoder()
|
private let decoder = MastodonDecoder()
|
||||||
|
@ -119,7 +120,7 @@ extension FiltersViewModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
extension EditFilterViewModel {
|
extension EditFilterViewModel {
|
||||||
static let development = EditFilterViewModel(filter: .new, identityService: .development)
|
static let development = EditFilterViewModel(filter: Filter.new, identityService: .development)
|
||||||
}
|
}
|
||||||
|
|
||||||
extension StatusListViewModel {
|
extension StatusListViewModel {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright © 2020 Metabolist. All rights reserved.
|
// Copyright © 2020 Metabolist. All rights reserved.
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
import Mastodon
|
||||||
|
|
||||||
struct HTTPStubs {
|
struct HTTPStubs {
|
||||||
static func stub(
|
static func stub(
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright © 2020 Metabolist. All rights reserved.
|
// Copyright © 2020 Metabolist. All rights reserved.
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
import Mastodon
|
||||||
|
|
||||||
extension AccessTokenEndpoint: Stubbing {
|
extension AccessTokenEndpoint: Stubbing {
|
||||||
func dataString(url: URL) -> String? {
|
func dataString(url: URL) -> String? {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright © 2020 Metabolist. All rights reserved.
|
// Copyright © 2020 Metabolist. All rights reserved.
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
import Mastodon
|
||||||
|
|
||||||
// swiftlint:disable line_length
|
// swiftlint:disable line_length
|
||||||
let officialAccountJSON = #"""
|
let officialAccountJSON = #"""
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright © 2020 Metabolist. All rights reserved.
|
// Copyright © 2020 Metabolist. All rights reserved.
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
import Mastodon
|
||||||
|
|
||||||
extension AppAuthorizationEndpoint: Stubbing {
|
extension AppAuthorizationEndpoint: Stubbing {
|
||||||
func dataString(url: URL) -> String? {
|
func dataString(url: URL) -> String? {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright © 2020 Metabolist. All rights reserved.
|
// Copyright © 2020 Metabolist. All rights reserved.
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
import Mastodon
|
||||||
|
|
||||||
extension ContextEndpoint: Stubbing {
|
extension ContextEndpoint: Stubbing {
|
||||||
func dataString(url: URL) -> String? {
|
func dataString(url: URL) -> String? {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright © 2020 Metabolist. All rights reserved.
|
// Copyright © 2020 Metabolist. All rights reserved.
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
import Mastodon
|
||||||
|
|
||||||
// swiftlint:disable line_length
|
// swiftlint:disable line_length
|
||||||
let officialInstanceJSON = #"""
|
let officialInstanceJSON = #"""
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright © 2020 Metabolist. All rights reserved.
|
// Copyright © 2020 Metabolist. All rights reserved.
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
import Mastodon
|
||||||
|
|
||||||
extension MastodonTarget: Stubbing {
|
extension MastodonTarget: Stubbing {
|
||||||
func stub(url: URL) -> HTTPStub? {
|
func stub(url: URL) -> HTTPStub? {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright © 2020 Metabolist. All rights reserved.
|
// Copyright © 2020 Metabolist. All rights reserved.
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
import Mastodon
|
||||||
|
|
||||||
extension PreferencesEndpoint: Stubbing {
|
extension PreferencesEndpoint: Stubbing {
|
||||||
func dataString(url: URL) -> String? {
|
func dataString(url: URL) -> String? {
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
import UIKit
|
import UIKit
|
||||||
|
import Mastodon
|
||||||
|
|
||||||
extension TimelinesEndpoint: Stubbing {
|
extension TimelinesEndpoint: Stubbing {
|
||||||
func data(url: URL) -> Data? {
|
func data(url: URL) -> Data? {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright © 2020 Metabolist. All rights reserved.
|
// Copyright © 2020 Metabolist. All rights reserved.
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
import Mastodon
|
||||||
|
|
||||||
class StubbingURLProtocol: URLProtocol {
|
class StubbingURLProtocol: URLProtocol {
|
||||||
private static var targetsForURLs = [URL: HTTPTarget]()
|
private static var targetsForURLs = [URL: HTTPTarget]()
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
// Copyright © 2020 Metabolist. All rights reserved.
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
typealias AttributedStringCache = NSCache<NSString, NSAttributedString>
|
|
||||||
|
|
||||||
extension CodingUserInfoKey {
|
|
||||||
static let attributedStringCache = CodingUserInfoKey(rawValue: "com.metabolist.metatext.attributed-string-cache")!
|
|
||||||
}
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
import UIKit
|
import UIKit
|
||||||
import Kingfisher
|
import Kingfisher
|
||||||
|
import Mastodon
|
||||||
|
|
||||||
extension NSMutableAttributedString {
|
extension NSMutableAttributedString {
|
||||||
func insert(emoji: [Emoji], view: UIView) {
|
func insert(emoji: [Emoji], view: UIView) {
|
||||||
|
|
5
Mastodon/.gitignore
vendored
Normal file
5
Mastodon/.gitignore
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
.DS_Store
|
||||||
|
/.build
|
||||||
|
/Packages
|
||||||
|
/*.xcodeproj
|
||||||
|
xcuserdata/
|
29
Mastodon/Package.swift
Normal file
29
Mastodon/Package.swift
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
// swift-tools-version:5.3
|
||||||
|
// The swift-tools-version declares the minimum version of Swift required to build this package.
|
||||||
|
|
||||||
|
import PackageDescription
|
||||||
|
|
||||||
|
let package = Package(
|
||||||
|
name: "Mastodon",
|
||||||
|
platforms: [.iOS(.v14), .macOS(.v11)],
|
||||||
|
products: [
|
||||||
|
// Products define the executables and libraries a package produces, and make them visible to other packages.
|
||||||
|
.library(
|
||||||
|
name: "Mastodon",
|
||||||
|
targets: ["Mastodon"])
|
||||||
|
],
|
||||||
|
dependencies: [
|
||||||
|
// Dependencies declare other packages that this package depends on.
|
||||||
|
.package(url: "https://github.com/Alamofire/Alamofire.git", .upToNextMajor(from: "5.2.2"))
|
||||||
|
],
|
||||||
|
targets: [
|
||||||
|
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
|
||||||
|
// Targets can depend on other targets in this package, and on products in packages this package depends on.
|
||||||
|
.target(
|
||||||
|
name: "Mastodon",
|
||||||
|
dependencies: ["Alamofire"]),
|
||||||
|
.testTarget(
|
||||||
|
name: "MastodonTests",
|
||||||
|
dependencies: ["Mastodon"])
|
||||||
|
]
|
||||||
|
)
|
3
Mastodon/README.md
Normal file
3
Mastodon/README.md
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# Mastodon
|
||||||
|
|
||||||
|
A description of this package.
|
5
Mastodon/Sources/Mastodon/Constants.swift
Normal file
5
Mastodon/Sources/Mastodon/Constants.swift
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
public enum Constants {
|
||||||
|
public static let dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
|
||||||
|
}
|
9
Mastodon/Sources/Mastodon/Entities/AccessToken.swift
Normal file
9
Mastodon/Sources/Mastodon/Entities/AccessToken.swift
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
// Copyright © 2020 Metabolist. All rights reserved.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
public struct AccessToken: Codable {
|
||||||
|
public let scope: String
|
||||||
|
public let tokenType: String
|
||||||
|
public let accessToken: String
|
||||||
|
}
|
32
Mastodon/Sources/Mastodon/Entities/Account.swift
Normal file
32
Mastodon/Sources/Mastodon/Entities/Account.swift
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
// Copyright © 2020 Metabolist. All rights reserved.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
public struct Account: Codable, Hashable {
|
||||||
|
public struct Field: Codable, Hashable {
|
||||||
|
public let name: String
|
||||||
|
public let value: HTML
|
||||||
|
public let verifiedAt: Date?
|
||||||
|
}
|
||||||
|
|
||||||
|
public let id: String
|
||||||
|
public let username: String
|
||||||
|
public let acct: String
|
||||||
|
public let displayName: String
|
||||||
|
public let locked: Bool
|
||||||
|
public let createdAt: Date
|
||||||
|
public let followersCount: Int
|
||||||
|
public let followingCount: Int
|
||||||
|
public let statusesCount: Int
|
||||||
|
public let note: HTML
|
||||||
|
public let url: URL
|
||||||
|
public let avatar: URL
|
||||||
|
public let avatarStatic: URL
|
||||||
|
public let header: URL
|
||||||
|
public let headerStatic: URL
|
||||||
|
public let fields: [Field]
|
||||||
|
public let emojis: [Emoji]
|
||||||
|
@DecodableDefault.False public private(set) var bot: Bool
|
||||||
|
@DecodableDefault.False public private(set) var moved: Bool
|
||||||
|
@DecodableDefault.False public private(set) var discoverable: Bool
|
||||||
|
}
|
13
Mastodon/Sources/Mastodon/Entities/AppAuthorization.swift
Normal file
13
Mastodon/Sources/Mastodon/Entities/AppAuthorization.swift
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
// Copyright © 2020 Metabolist. All rights reserved.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
public struct AppAuthorization: Codable {
|
||||||
|
public let id: String
|
||||||
|
public let clientId: String
|
||||||
|
public let clientSecret: String
|
||||||
|
public let name: String
|
||||||
|
public let redirectUri: String
|
||||||
|
public let website: String?
|
||||||
|
public let vapidKey: String?
|
||||||
|
}
|
8
Mastodon/Sources/Mastodon/Entities/Application.swift
Normal file
8
Mastodon/Sources/Mastodon/Entities/Application.swift
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
// Copyright © 2020 Metabolist. All rights reserved.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
public struct Application: Codable, Hashable {
|
||||||
|
public let name: String
|
||||||
|
public let website: String?
|
||||||
|
}
|
43
Mastodon/Sources/Mastodon/Entities/Attachment.swift
Normal file
43
Mastodon/Sources/Mastodon/Entities/Attachment.swift
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
// Copyright © 2020 Metabolist. All rights reserved.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
public struct Attachment: Codable, Hashable {
|
||||||
|
public enum AttachmentType: String, Codable, Hashable, Unknowable {
|
||||||
|
case image, video, gifv, audio, unknown
|
||||||
|
|
||||||
|
public static var unknownCase: Self { .unknown }
|
||||||
|
}
|
||||||
|
|
||||||
|
// swiftlint:disable nesting
|
||||||
|
public struct Meta: Codable, Hashable {
|
||||||
|
public struct Info: Codable, Hashable {
|
||||||
|
public let width: Int?
|
||||||
|
public let height: Int?
|
||||||
|
public let size: String?
|
||||||
|
public let aspect: Double?
|
||||||
|
public let frameRate: String?
|
||||||
|
public let duration: Double?
|
||||||
|
public let bitrate: Int?
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct Focus: Codable, Hashable {
|
||||||
|
public let x: Double
|
||||||
|
public let y: Double
|
||||||
|
}
|
||||||
|
|
||||||
|
public let original: Info?
|
||||||
|
public let small: Info?
|
||||||
|
public let focus: Focus?
|
||||||
|
}
|
||||||
|
// swiftlint:enable nesting
|
||||||
|
|
||||||
|
public let id: String
|
||||||
|
public let type: AttachmentType
|
||||||
|
public let url: URL
|
||||||
|
public let remoteUrl: URL?
|
||||||
|
public let previewUrl: URL
|
||||||
|
public let textUrl: URL?
|
||||||
|
public let meta: Meta?
|
||||||
|
public let description: String?
|
||||||
|
}
|
25
Mastodon/Sources/Mastodon/Entities/Card.swift
Normal file
25
Mastodon/Sources/Mastodon/Entities/Card.swift
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
// Copyright © 2020 Metabolist. All rights reserved.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
public struct Card: Codable, Hashable {
|
||||||
|
public enum CardType: String, Codable, Hashable, Unknowable {
|
||||||
|
case link, photo, video, rich, unknown
|
||||||
|
|
||||||
|
public static var unknownCase: Self { .unknown }
|
||||||
|
}
|
||||||
|
|
||||||
|
public let url: URL
|
||||||
|
public let title: String
|
||||||
|
public let description: String
|
||||||
|
public let type: CardType
|
||||||
|
public let authorName: String?
|
||||||
|
public let authorUrl: String?
|
||||||
|
public let providerName: String?
|
||||||
|
public let providerUrl: String?
|
||||||
|
public let html: String?
|
||||||
|
public let width: Int?
|
||||||
|
public let height: Int?
|
||||||
|
public let image: URL?
|
||||||
|
public let embedUrl: String?
|
||||||
|
}
|
10
Mastodon/Sources/Mastodon/Entities/Emoji.swift
Normal file
10
Mastodon/Sources/Mastodon/Entities/Emoji.swift
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
// Copyright © 2020 Metabolist. All rights reserved.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
public struct Emoji: Codable, Hashable {
|
||||||
|
public let shortcode: String
|
||||||
|
public let staticUrl: URL
|
||||||
|
public let url: URL
|
||||||
|
public let visibleInPicker: Bool
|
||||||
|
}
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
struct Filter: Codable, Hashable, Identifiable {
|
public struct Filter: Codable, Hashable, Identifiable {
|
||||||
enum Context: String, Codable, Unknowable {
|
public enum Context: String, Codable, Unknowable {
|
||||||
case home
|
case home
|
||||||
case notifications
|
case notifications
|
||||||
case `public`
|
case `public`
|
||||||
|
@ -11,18 +11,18 @@ struct Filter: Codable, Hashable, Identifiable {
|
||||||
case account
|
case account
|
||||||
case unknown
|
case unknown
|
||||||
|
|
||||||
static var unknownCase: Self { .unknown }
|
public static var unknownCase: Self { .unknown }
|
||||||
}
|
}
|
||||||
|
|
||||||
let id: String
|
public let id: String
|
||||||
var phrase: String
|
public var phrase: String
|
||||||
var context: [Context]
|
public var context: [Context]
|
||||||
var expiresAt: Date?
|
public var expiresAt: Date?
|
||||||
var irreversible: Bool
|
public var irreversible: Bool
|
||||||
var wholeWord: Bool
|
public var wholeWord: Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Filter {
|
public extension Filter {
|
||||||
static let newFilterID: String = "com.metabolist.metatext.new-filter-id"
|
static let newFilterID: String = "com.metabolist.metatext.new-filter-id"
|
||||||
static let new = Self(id: newFilterID,
|
static let new = Self(id: newFilterID,
|
||||||
phrase: "",
|
phrase: "",
|
||||||
|
@ -36,7 +36,7 @@ extension Array where Element == Filter {
|
||||||
// swiftlint:disable line_length
|
// swiftlint:disable line_length
|
||||||
// Adapted from https://github.com/tootsuite/mastodon/blob/bf477cee9f31036ebf3d164ddec1cebef5375513/app/javascript/mastodon/selectors/index.js#L43
|
// Adapted from https://github.com/tootsuite/mastodon/blob/bf477cee9f31036ebf3d164ddec1cebef5375513/app/javascript/mastodon/selectors/index.js#L43
|
||||||
// swiftlint:enable line_length
|
// swiftlint:enable line_length
|
||||||
func regularExpression() -> String? {
|
public func regularExpression() -> String? {
|
||||||
guard !isEmpty else { return nil }
|
guard !isEmpty else { return nil }
|
||||||
|
|
||||||
return map {
|
return map {
|
||||||
|
@ -59,24 +59,5 @@ extension Array where Element == Filter {
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Filter.Context: Identifiable {
|
extension Filter.Context: Identifiable {
|
||||||
var id: Self { self }
|
public var id: Self { self }
|
||||||
}
|
|
||||||
|
|
||||||
extension Filter.Context {
|
|
||||||
var localized: String {
|
|
||||||
switch self {
|
|
||||||
case .home:
|
|
||||||
return NSLocalizedString("filter.context.home", comment: "")
|
|
||||||
case .notifications:
|
|
||||||
return NSLocalizedString("filter.context.notifications", comment: "")
|
|
||||||
case .public:
|
|
||||||
return NSLocalizedString("filter.context.public", comment: "")
|
|
||||||
case .thread:
|
|
||||||
return NSLocalizedString("filter.context.thread", comment: "")
|
|
||||||
case .account:
|
|
||||||
return NSLocalizedString("filter.context.account", comment: "")
|
|
||||||
case .unknown:
|
|
||||||
return NSLocalizedString("filter.context.unknown", comment: "")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,30 +1,26 @@
|
||||||
// Copyright © 2020 Metabolist. All rights reserved.
|
// Copyright © 2020 Metabolist. All rights reserved.
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
#if !os(macOS)
|
||||||
|
import UIKit
|
||||||
|
#else
|
||||||
|
import AppKit
|
||||||
|
#endif
|
||||||
|
|
||||||
struct HTML: Hashable {
|
public struct HTML: Hashable {
|
||||||
let raw: String
|
public let raw: String
|
||||||
let attributed: NSAttributedString
|
public let attributed: NSAttributedString
|
||||||
}
|
}
|
||||||
|
|
||||||
extension HTML: Codable {
|
extension HTML: Codable {
|
||||||
init(from decoder: Decoder) throws {
|
public init(from decoder: Decoder) throws {
|
||||||
let container = try decoder.singleValueContainer()
|
let container = try decoder.singleValueContainer()
|
||||||
let attributedStringCache = decoder.userInfo[.attributedStringCache] as? AttributedStringCache
|
|
||||||
|
|
||||||
raw = try container.decode(String.self)
|
raw = try container.decode(String.self)
|
||||||
|
|
||||||
if let attributed = attributedStringCache?.object(forKey: raw as NSString) {
|
|
||||||
self.attributed = attributed
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
attributed = HTMLParser(string: raw).parse()
|
attributed = HTMLParser(string: raw).parse()
|
||||||
attributedStringCache?.setObject(attributed, forKey: raw as NSString)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func encode(to encoder: Encoder) throws {
|
public func encode(to encoder: Encoder) throws {
|
||||||
var container = encoder.singleValueContainer()
|
var container = encoder.singleValueContainer()
|
||||||
|
|
||||||
try container.encode(raw)
|
try container.encode(raw)
|
30
Mastodon/Sources/Mastodon/Entities/Instance.swift
Normal file
30
Mastodon/Sources/Mastodon/Entities/Instance.swift
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
// Copyright © 2020 Metabolist. All rights reserved.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
public struct Instance: Codable, Hashable {
|
||||||
|
public struct URLs: Codable, Hashable {
|
||||||
|
public let streamingApi: URL
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct Stats: Codable, Hashable {
|
||||||
|
public let userCount: Int
|
||||||
|
public let statusCount: Int
|
||||||
|
public let domainCount: Int
|
||||||
|
}
|
||||||
|
|
||||||
|
public let uri: String
|
||||||
|
public let title: String
|
||||||
|
public let description: String
|
||||||
|
public let shortDescription: String?
|
||||||
|
public let email: String
|
||||||
|
public let version: String
|
||||||
|
@DecodableDefault.EmptyList public private(set) var languages: [String]
|
||||||
|
@DecodableDefault.False public private(set) var registrations: Bool
|
||||||
|
@DecodableDefault.False public private(set) var approvalRequired: Bool
|
||||||
|
@DecodableDefault.False public private(set) var invitesEnabled: Bool
|
||||||
|
public let urls: URLs
|
||||||
|
public let stats: Stats
|
||||||
|
public let thumbnail: URL?
|
||||||
|
public let contactAccount: Account?
|
||||||
|
}
|
13
Mastodon/Sources/Mastodon/Entities/List.swift
Normal file
13
Mastodon/Sources/Mastodon/Entities/List.swift
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
// Copyright © 2020 Metabolist. All rights reserved.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
public struct MastodonList: Codable, Hashable, Identifiable {
|
||||||
|
public let id: String
|
||||||
|
public let title: String
|
||||||
|
|
||||||
|
public init(id: String, title: String) {
|
||||||
|
self.id = id
|
||||||
|
self.title = title
|
||||||
|
}
|
||||||
|
}
|
13
Mastodon/Sources/Mastodon/Entities/MastodonContext.swift
Normal file
13
Mastodon/Sources/Mastodon/Entities/MastodonContext.swift
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
// Copyright © 2020 Metabolist. All rights reserved.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
public struct MastodonContext: Codable, Hashable {
|
||||||
|
public let ancestors: [Status]
|
||||||
|
public let descendants: [Status]
|
||||||
|
|
||||||
|
public init(ancestors: [Status], descendants: [Status]) {
|
||||||
|
self.ancestors = ancestors
|
||||||
|
self.descendants = descendants
|
||||||
|
}
|
||||||
|
}
|
11
Mastodon/Sources/Mastodon/Entities/MastodonError.swift
Normal file
11
Mastodon/Sources/Mastodon/Entities/MastodonError.swift
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
// Copyright © 2020 Metabolist. All rights reserved.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
public struct MastodonError: Error, Codable {
|
||||||
|
public let error: String
|
||||||
|
}
|
||||||
|
|
||||||
|
extension MastodonError: LocalizedError {
|
||||||
|
public var errorDescription: String? { error }
|
||||||
|
}
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
struct MastodonPreferences: Codable {
|
public struct MastodonPreferences: Codable {
|
||||||
enum CodingKeys: String, CodingKey {
|
enum CodingKeys: String, CodingKey {
|
||||||
case postingDefaultVisibility = "posting:default:visibility"
|
case postingDefaultVisibility = "posting:default:visibility"
|
||||||
case postingDefaultSensitive = "posting:default:sensitive"
|
case postingDefaultSensitive = "posting:default:sensitive"
|
||||||
|
@ -11,20 +11,20 @@ struct MastodonPreferences: Codable {
|
||||||
case readingExpandSpoilers = "reading:expand:spoilers"
|
case readingExpandSpoilers = "reading:expand:spoilers"
|
||||||
}
|
}
|
||||||
|
|
||||||
let postingDefaultVisibility: Status.Visibility
|
public let postingDefaultVisibility: Status.Visibility
|
||||||
let postingDefaultSensitive: Bool
|
public let postingDefaultSensitive: Bool
|
||||||
let postingDefaultLanguage: String?
|
public let postingDefaultLanguage: String?
|
||||||
let readingExpandMedia: ExpandMedia
|
public let readingExpandMedia: ExpandMedia
|
||||||
let readingExpandSpoilers: Bool
|
public let readingExpandSpoilers: Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
extension MastodonPreferences {
|
public extension MastodonPreferences {
|
||||||
enum ExpandMedia: String, Codable, Unknowable {
|
enum ExpandMedia: String, Codable, Unknowable {
|
||||||
case `default`
|
case `default`
|
||||||
case showAll
|
case showAll
|
||||||
case hideAll
|
case hideAll
|
||||||
case unknown
|
case unknown
|
||||||
|
|
||||||
static var unknownCase: Self { .unknown }
|
public static var unknownCase: Self { .unknown }
|
||||||
}
|
}
|
||||||
}
|
}
|
10
Mastodon/Sources/Mastodon/Entities/Mention.swift
Normal file
10
Mastodon/Sources/Mastodon/Entities/Mention.swift
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
// Copyright © 2020 Metabolist. All rights reserved.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
public struct Mention: Codable, Hashable {
|
||||||
|
public let url: URL
|
||||||
|
public let username: String
|
||||||
|
public let acct: String
|
||||||
|
public let id: String
|
||||||
|
}
|
21
Mastodon/Sources/Mastodon/Entities/Poll.swift
Normal file
21
Mastodon/Sources/Mastodon/Entities/Poll.swift
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
// Copyright © 2020 Metabolist. All rights reserved.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
public struct Poll: Codable, Hashable {
|
||||||
|
public struct Option: Codable, Hashable {
|
||||||
|
public var title: String
|
||||||
|
public var votesCount: Int
|
||||||
|
}
|
||||||
|
|
||||||
|
public let id: String
|
||||||
|
public let expiresAt: Date
|
||||||
|
public let expired: Bool
|
||||||
|
public let multiple: Bool
|
||||||
|
public let votesCount: Int
|
||||||
|
public let votersCount: Int?
|
||||||
|
@DecodableDefault.False public private(set) var voted: Bool
|
||||||
|
@DecodableDefault.EmptyList public private(set) var ownVotes: [Int]
|
||||||
|
public let options: [Option]
|
||||||
|
public let emojis: [Emoji]
|
||||||
|
}
|
23
Mastodon/Sources/Mastodon/Entities/PushNotification.swift
Normal file
23
Mastodon/Sources/Mastodon/Entities/PushNotification.swift
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
// Copyright © 2020 Metabolist. All rights reserved.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
public struct PushNotification: Codable {
|
||||||
|
public enum NotificationType: String, Codable, Unknowable {
|
||||||
|
case mention
|
||||||
|
case reblog
|
||||||
|
case favourite
|
||||||
|
case follow
|
||||||
|
case unknown
|
||||||
|
|
||||||
|
public static var unknownCase: Self { .unknown }
|
||||||
|
}
|
||||||
|
|
||||||
|
public let accessToken: String
|
||||||
|
public let body: String
|
||||||
|
public let title: String
|
||||||
|
public let icon: URL
|
||||||
|
public let notificationId: Int
|
||||||
|
public let notificationType: NotificationType
|
||||||
|
public let preferredLocale: String
|
||||||
|
}
|
26
Mastodon/Sources/Mastodon/Entities/PushSubscription.swift
Normal file
26
Mastodon/Sources/Mastodon/Entities/PushSubscription.swift
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
// Copyright © 2020 Metabolist. All rights reserved.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
public struct PushSubscription: Codable {
|
||||||
|
public struct Alerts: Codable, Hashable {
|
||||||
|
public var follow: Bool
|
||||||
|
public var favourite: Bool
|
||||||
|
public var reblog: Bool
|
||||||
|
public var mention: Bool
|
||||||
|
@DecodableDefault.True public var poll: Bool
|
||||||
|
}
|
||||||
|
|
||||||
|
public let endpoint: URL
|
||||||
|
public let alerts: Alerts
|
||||||
|
public let serverKey: String
|
||||||
|
}
|
||||||
|
|
||||||
|
public extension PushSubscription.Alerts {
|
||||||
|
static let initial: Self = Self(
|
||||||
|
follow: true,
|
||||||
|
favourite: true,
|
||||||
|
reblog: true,
|
||||||
|
mention: true,
|
||||||
|
poll: DecodableDefault.True())
|
||||||
|
}
|
|
@ -2,49 +2,49 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
class Status: Codable, Identifiable {
|
public class Status: Codable, Identifiable {
|
||||||
enum Visibility: String, Codable, Unknowable {
|
public enum Visibility: String, Codable, Unknowable {
|
||||||
case `public`
|
case `public`
|
||||||
case unlisted
|
case unlisted
|
||||||
case `private`
|
case `private`
|
||||||
case direct
|
case direct
|
||||||
case unknown
|
case unknown
|
||||||
|
|
||||||
static var unknownCase: Self { .unknown }
|
public static var unknownCase: Self { .unknown }
|
||||||
}
|
}
|
||||||
|
|
||||||
let id: String
|
public let id: String
|
||||||
let uri: String
|
public let uri: String
|
||||||
let createdAt: Date
|
public let createdAt: Date
|
||||||
let account: Account
|
public let account: Account
|
||||||
let content: HTML
|
public let content: HTML
|
||||||
let visibility: Visibility
|
public let visibility: Visibility
|
||||||
let sensitive: Bool
|
public let sensitive: Bool
|
||||||
let spoilerText: String
|
public let spoilerText: String
|
||||||
let mediaAttachments: [Attachment]
|
public let mediaAttachments: [Attachment]
|
||||||
let mentions: [Mention]
|
public let mentions: [Mention]
|
||||||
let tags: [Tag]
|
public let tags: [Tag]
|
||||||
let emojis: [Emoji]
|
public let emojis: [Emoji]
|
||||||
let reblogsCount: Int
|
public let reblogsCount: Int
|
||||||
let favouritesCount: Int
|
public let favouritesCount: Int
|
||||||
@DecodableDefault.Zero private(set) var repliesCount: Int
|
@DecodableDefault.Zero public private(set) var repliesCount: Int
|
||||||
let application: Application?
|
public let application: Application?
|
||||||
let url: URL?
|
public let url: URL?
|
||||||
let inReplyToId: String?
|
public let inReplyToId: String?
|
||||||
let inReplyToAccountId: String?
|
public let inReplyToAccountId: String?
|
||||||
let reblog: Status?
|
public let reblog: Status?
|
||||||
let poll: Poll?
|
public let poll: Poll?
|
||||||
let card: Card?
|
public let card: Card?
|
||||||
let language: String?
|
public let language: String?
|
||||||
let text: String?
|
public let text: String?
|
||||||
@DecodableDefault.False private(set) var favourited: Bool
|
@DecodableDefault.False public private(set) var favourited: Bool
|
||||||
@DecodableDefault.False private(set) var reblogged: Bool
|
@DecodableDefault.False public private(set) var reblogged: Bool
|
||||||
@DecodableDefault.False private(set) var muted: Bool
|
@DecodableDefault.False public private(set) var muted: Bool
|
||||||
@DecodableDefault.False private(set) var bookmarked: Bool
|
@DecodableDefault.False public private(set) var bookmarked: Bool
|
||||||
let pinned: Bool?
|
public let pinned: Bool?
|
||||||
|
|
||||||
// Xcode-generated memberwise initializer
|
// Xcode-generated memberwise initializer
|
||||||
init(
|
public init(
|
||||||
id: String,
|
id: String,
|
||||||
uri: String,
|
uri: String,
|
||||||
createdAt: Date,
|
createdAt: Date,
|
||||||
|
@ -88,7 +88,6 @@ class Status: Codable, Identifiable {
|
||||||
self.emojis = emojis
|
self.emojis = emojis
|
||||||
self.reblogsCount = reblogsCount
|
self.reblogsCount = reblogsCount
|
||||||
self.favouritesCount = favouritesCount
|
self.favouritesCount = favouritesCount
|
||||||
self.repliesCount = repliesCount
|
|
||||||
self.application = application
|
self.application = application
|
||||||
self.url = url
|
self.url = url
|
||||||
self.inReplyToId = inReplyToId
|
self.inReplyToId = inReplyToId
|
||||||
|
@ -98,15 +97,16 @@ class Status: Codable, Identifiable {
|
||||||
self.card = card
|
self.card = card
|
||||||
self.language = language
|
self.language = language
|
||||||
self.text = text
|
self.text = text
|
||||||
|
self.pinned = pinned
|
||||||
|
self.repliesCount = repliesCount
|
||||||
self.favourited = favourited
|
self.favourited = favourited
|
||||||
self.reblogged = reblogged
|
self.reblogged = reblogged
|
||||||
self.muted = muted
|
self.muted = muted
|
||||||
self.bookmarked = bookmarked
|
self.bookmarked = bookmarked
|
||||||
self.pinned = pinned
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Status {
|
public extension Status {
|
||||||
var displayStatus: Status {
|
var displayStatus: Status {
|
||||||
reblog ?? self
|
reblog ?? self
|
||||||
}
|
}
|
||||||
|
@ -121,7 +121,7 @@ extension Status {
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Status: Hashable {
|
extension Status: Hashable {
|
||||||
static func == (lhs: Status, rhs: Status) -> Bool {
|
public static func == (lhs: Status, rhs: Status) -> Bool {
|
||||||
lhs.id == rhs.id
|
lhs.id == rhs.id
|
||||||
&& lhs.uri == rhs.uri
|
&& lhs.uri == rhs.uri
|
||||||
&& lhs.createdAt == rhs.createdAt
|
&& lhs.createdAt == rhs.createdAt
|
||||||
|
@ -153,7 +153,7 @@ extension Status: Hashable {
|
||||||
&& lhs.pinned == rhs.pinned
|
&& lhs.pinned == rhs.pinned
|
||||||
}
|
}
|
||||||
|
|
||||||
func hash(into hasher: inout Hasher) {
|
public func hash(into hasher: inout Hasher) {
|
||||||
hasher.combine(id)
|
hasher.combine(id)
|
||||||
hasher.combine(uri)
|
hasher.combine(uri)
|
||||||
hasher.combine(createdAt)
|
hasher.combine(createdAt)
|
8
Mastodon/Sources/Mastodon/Entities/Tag.swift
Normal file
8
Mastodon/Sources/Mastodon/Entities/Tag.swift
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
// Copyright © 2020 Metabolist. All rights reserved.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
public struct Tag: Codable, Hashable {
|
||||||
|
public let name: String
|
||||||
|
public let url: URL
|
||||||
|
}
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
enum Timeline: Hashable {
|
public enum Timeline: Hashable {
|
||||||
case home
|
case home
|
||||||
case local
|
case local
|
||||||
case federated
|
case federated
|
||||||
|
@ -10,7 +10,7 @@ enum Timeline: Hashable {
|
||||||
case tag(String)
|
case tag(String)
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Timeline {
|
public extension Timeline {
|
||||||
static let nonLists: [Timeline] = [.home, .local, .federated]
|
static let nonLists: [Timeline] = [.home, .local, .federated]
|
||||||
|
|
||||||
var endpoint: TimelinesEndpoint {
|
var endpoint: TimelinesEndpoint {
|
||||||
|
@ -30,7 +30,7 @@ extension Timeline {
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Timeline: Identifiable {
|
extension Timeline: Identifiable {
|
||||||
var id: String {
|
public var id: String {
|
||||||
switch self {
|
switch self {
|
||||||
case .home:
|
case .home:
|
||||||
return "home"
|
return "home"
|
|
@ -4,22 +4,22 @@ import Foundation
|
||||||
import Combine
|
import Combine
|
||||||
import Alamofire
|
import Alamofire
|
||||||
|
|
||||||
typealias Session = Alamofire.Session
|
public typealias Session = Alamofire.Session
|
||||||
|
|
||||||
class HTTPClient {
|
public class HTTPClient {
|
||||||
private let session: Session
|
private let session: Session
|
||||||
private let decoder: DataDecoder
|
private let decoder: DataDecoder
|
||||||
|
|
||||||
init(session: Session, decoder: DataDecoder) {
|
public init(session: Session, decoder: DataDecoder) {
|
||||||
self.session = session
|
self.session = session
|
||||||
self.decoder = decoder
|
self.decoder = decoder
|
||||||
}
|
}
|
||||||
|
|
||||||
func request<T: DecodableTarget>(_ target: T) -> AnyPublisher<T.ResultType, Error> {
|
public func request<T: DecodableTarget>(_ target: T) -> AnyPublisher<T.ResultType, Error> {
|
||||||
requestPublisher(target).value().mapError { $0 as Error }.eraseToAnyPublisher()
|
requestPublisher(target).value().mapError { $0 as Error }.eraseToAnyPublisher()
|
||||||
}
|
}
|
||||||
|
|
||||||
func request<T: DecodableTarget, E: Error & Decodable>(
|
public func request<T: DecodableTarget, E: Error & Decodable>(
|
||||||
_ target: T,
|
_ target: T,
|
||||||
decodeErrorsAs errorType: E.Type) -> AnyPublisher<T.ResultType, Error> {
|
decodeErrorsAs errorType: E.Type) -> AnyPublisher<T.ResultType, Error> {
|
||||||
let decoder = self.decoder
|
let decoder = self.decoder
|
||||||
|
@ -43,12 +43,12 @@ class HTTPClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
private extension HTTPClient {
|
private extension HTTPClient {
|
||||||
private func requestPublisher<T: DecodableTarget>(_ target: T) -> DataResponsePublisher<T.ResultType> {
|
func requestPublisher<T: DecodableTarget>(_ target: T) -> DataResponsePublisher<T.ResultType> {
|
||||||
#if DEBUG
|
// #if DEBUG
|
||||||
if let url = try? target.asURLRequest().url {
|
// if let url = try? target.asURLRequest().url {
|
||||||
StubbingURLProtocol.setTarget(target, forURL: url)
|
// StubbingURLProtocol.setTarget(target, forURL: url)
|
||||||
}
|
// }
|
||||||
#endif
|
// #endif
|
||||||
|
|
||||||
return session.request(target)
|
return session.request(target)
|
||||||
.validate()
|
.validate()
|
|
@ -3,13 +3,13 @@
|
||||||
import Foundation
|
import Foundation
|
||||||
import Alamofire
|
import Alamofire
|
||||||
|
|
||||||
typealias HTTPMethod = Alamofire.HTTPMethod
|
public typealias HTTPMethod = Alamofire.HTTPMethod
|
||||||
typealias HTTPHeaders = Alamofire.HTTPHeaders
|
public typealias HTTPHeaders = Alamofire.HTTPHeaders
|
||||||
typealias ParameterEncoding = Alamofire.ParameterEncoding
|
public typealias ParameterEncoding = Alamofire.ParameterEncoding
|
||||||
typealias URLEncoding = Alamofire.URLEncoding
|
public typealias URLEncoding = Alamofire.URLEncoding
|
||||||
typealias JSONEncoding = Alamofire.JSONEncoding
|
public typealias JSONEncoding = Alamofire.JSONEncoding
|
||||||
|
|
||||||
protocol HTTPTarget: URLRequestConvertible {
|
public protocol HTTPTarget: URLRequestConvertible {
|
||||||
var baseURL: URL { get }
|
var baseURL: URL { get }
|
||||||
var pathComponents: [String] { get }
|
var pathComponents: [String] { get }
|
||||||
var method: HTTPMethod { get }
|
var method: HTTPMethod { get }
|
||||||
|
@ -18,7 +18,7 @@ protocol HTTPTarget: URLRequestConvertible {
|
||||||
var headers: HTTPHeaders? { get }
|
var headers: HTTPHeaders? { get }
|
||||||
}
|
}
|
||||||
|
|
||||||
extension HTTPTarget {
|
public extension HTTPTarget {
|
||||||
func asURLRequest() throws -> URLRequest {
|
func asURLRequest() throws -> URLRequest {
|
||||||
var url = baseURL
|
var url = baseURL
|
||||||
|
|
||||||
|
@ -30,6 +30,6 @@ extension HTTPTarget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protocol DecodableTarget: HTTPTarget {
|
public protocol DecodableTarget: HTTPTarget {
|
||||||
associatedtype ResultType: Decodable
|
associatedtype ResultType: Decodable
|
||||||
}
|
}
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
enum AccessTokenEndpoint {
|
public enum AccessTokenEndpoint {
|
||||||
case oauthToken(
|
case oauthToken(
|
||||||
clientID: String,
|
clientID: String,
|
||||||
clientSecret: String,
|
clientSecret: String,
|
||||||
|
@ -14,21 +14,21 @@ enum AccessTokenEndpoint {
|
||||||
}
|
}
|
||||||
|
|
||||||
extension AccessTokenEndpoint: MastodonEndpoint {
|
extension AccessTokenEndpoint: MastodonEndpoint {
|
||||||
typealias ResultType = AccessToken
|
public typealias ResultType = AccessToken
|
||||||
|
|
||||||
var context: [String] { [] }
|
public var context: [String] { [] }
|
||||||
|
|
||||||
var pathComponentsInContext: [String] {
|
public var pathComponentsInContext: [String] {
|
||||||
["oauth", "token"]
|
["oauth", "token"]
|
||||||
}
|
}
|
||||||
|
|
||||||
var method: HTTPMethod {
|
public var method: HTTPMethod {
|
||||||
switch self {
|
switch self {
|
||||||
case .oauthToken: return .post
|
case .oauthToken: return .post
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var parameters: [String: Any]? {
|
public var parameters: [String: Any]? {
|
||||||
switch self {
|
switch self {
|
||||||
case let .oauthToken(clientID, clientSecret, code, grantType, scopes, redirectURI):
|
case let .oauthToken(clientID, clientSecret, code, grantType, scopes, redirectURI):
|
||||||
return [
|
return [
|
|
@ -2,24 +2,24 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
enum AccountEndpoint {
|
public enum AccountEndpoint {
|
||||||
case verifyCredentials
|
case verifyCredentials
|
||||||
}
|
}
|
||||||
|
|
||||||
extension AccountEndpoint: MastodonEndpoint {
|
extension AccountEndpoint: MastodonEndpoint {
|
||||||
typealias ResultType = Account
|
public typealias ResultType = Account
|
||||||
|
|
||||||
var context: [String] {
|
public var context: [String] {
|
||||||
defaultContext + ["accounts"]
|
defaultContext + ["accounts"]
|
||||||
}
|
}
|
||||||
|
|
||||||
var pathComponentsInContext: [String] {
|
public var pathComponentsInContext: [String] {
|
||||||
switch self {
|
switch self {
|
||||||
case .verifyCredentials: return ["verify_credentials"]
|
case .verifyCredentials: return ["verify_credentials"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var method: HTTPMethod {
|
public var method: HTTPMethod {
|
||||||
switch self {
|
switch self {
|
||||||
case .verifyCredentials: return .get
|
case .verifyCredentials: return .get
|
||||||
}
|
}
|
|
@ -2,26 +2,26 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
enum AppAuthorizationEndpoint {
|
public enum AppAuthorizationEndpoint {
|
||||||
case apps(clientName: String, redirectURI: String, scopes: String, website: URL?)
|
case apps(clientName: String, redirectURI: String, scopes: String, website: URL?)
|
||||||
}
|
}
|
||||||
|
|
||||||
extension AppAuthorizationEndpoint: MastodonEndpoint {
|
extension AppAuthorizationEndpoint: MastodonEndpoint {
|
||||||
typealias ResultType = AppAuthorization
|
public typealias ResultType = AppAuthorization
|
||||||
|
|
||||||
var pathComponentsInContext: [String] {
|
public var pathComponentsInContext: [String] {
|
||||||
switch self {
|
switch self {
|
||||||
case .apps: return ["apps"]
|
case .apps: return ["apps"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var method: HTTPMethod {
|
public var method: HTTPMethod {
|
||||||
switch self {
|
switch self {
|
||||||
case .apps: return .post
|
case .apps: return .post
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var parameters: [String: Any]? {
|
public var parameters: [String: Any]? {
|
||||||
switch self {
|
switch self {
|
||||||
case let .apps(clientName, redirectURI, scopes, website):
|
case let .apps(clientName, redirectURI, scopes, website):
|
||||||
var params = [
|
var params = [
|
|
@ -2,23 +2,23 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
enum ContextEndpoint {
|
public enum ContextEndpoint {
|
||||||
case context(id: String)
|
case context(id: String)
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ContextEndpoint: MastodonEndpoint {
|
extension ContextEndpoint: MastodonEndpoint {
|
||||||
typealias ResultType = MastodonContext
|
public typealias ResultType = MastodonContext
|
||||||
|
|
||||||
var context: [String] {
|
public var context: [String] {
|
||||||
defaultContext + ["statuses"]
|
defaultContext + ["statuses"]
|
||||||
}
|
}
|
||||||
|
|
||||||
var pathComponentsInContext: [String] {
|
public var pathComponentsInContext: [String] {
|
||||||
switch self {
|
switch self {
|
||||||
case let .context(id):
|
case let .context(id):
|
||||||
return [id, "context"]
|
return [id, "context"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var method: HTTPMethod { .get }
|
public var method: HTTPMethod { .get }
|
||||||
}
|
}
|
|
@ -2,16 +2,16 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
enum DeletionEndpoint {
|
public enum DeletionEndpoint {
|
||||||
case oauthRevoke(token: String, clientID: String, clientSecret: String)
|
case oauthRevoke(token: String, clientID: String, clientSecret: String)
|
||||||
case list(id: String)
|
case list(id: String)
|
||||||
case filter(id: String)
|
case filter(id: String)
|
||||||
}
|
}
|
||||||
|
|
||||||
extension DeletionEndpoint: MastodonEndpoint {
|
extension DeletionEndpoint: MastodonEndpoint {
|
||||||
typealias ResultType = [String: String]
|
public typealias ResultType = [String: String]
|
||||||
|
|
||||||
var context: [String] {
|
public var context: [String] {
|
||||||
switch self {
|
switch self {
|
||||||
case .oauthRevoke:
|
case .oauthRevoke:
|
||||||
return ["oauth"]
|
return ["oauth"]
|
||||||
|
@ -22,7 +22,7 @@ extension DeletionEndpoint: MastodonEndpoint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var pathComponentsInContext: [String] {
|
public var pathComponentsInContext: [String] {
|
||||||
switch self {
|
switch self {
|
||||||
case .oauthRevoke:
|
case .oauthRevoke:
|
||||||
return ["revoke"]
|
return ["revoke"]
|
||||||
|
@ -31,7 +31,7 @@ extension DeletionEndpoint: MastodonEndpoint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var method: HTTPMethod {
|
public var method: HTTPMethod {
|
||||||
switch self {
|
switch self {
|
||||||
case .oauthRevoke:
|
case .oauthRevoke:
|
||||||
return .post
|
return .post
|
||||||
|
@ -40,7 +40,7 @@ extension DeletionEndpoint: MastodonEndpoint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var parameters: [String: Any]? {
|
public var parameters: [String: Any]? {
|
||||||
switch self {
|
switch self {
|
||||||
case let .oauthRevoke(token, clientID, clientSecret):
|
case let .oauthRevoke(token, clientID, clientSecret):
|
||||||
return ["token": token, "client_id": clientID, "client_secret": clientSecret]
|
return ["token": token, "client_id": clientID, "client_secret": clientSecret]
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
enum FilterEndpoint {
|
public enum FilterEndpoint {
|
||||||
case create(
|
case create(
|
||||||
phrase: String,
|
phrase: String,
|
||||||
context: [Filter.Context],
|
context: [Filter.Context],
|
||||||
|
@ -19,13 +19,13 @@ enum FilterEndpoint {
|
||||||
}
|
}
|
||||||
|
|
||||||
extension FilterEndpoint: MastodonEndpoint {
|
extension FilterEndpoint: MastodonEndpoint {
|
||||||
typealias ResultType = Filter
|
public typealias ResultType = Filter
|
||||||
|
|
||||||
var context: [String] {
|
public var context: [String] {
|
||||||
defaultContext + ["filters"]
|
defaultContext + ["filters"]
|
||||||
}
|
}
|
||||||
|
|
||||||
var pathComponentsInContext: [String] {
|
public var pathComponentsInContext: [String] {
|
||||||
switch self {
|
switch self {
|
||||||
case .create:
|
case .create:
|
||||||
return []
|
return []
|
||||||
|
@ -34,7 +34,7 @@ extension FilterEndpoint: MastodonEndpoint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var parameters: [String: Any]? {
|
public var parameters: [String: Any]? {
|
||||||
switch self {
|
switch self {
|
||||||
case let .create(phrase, context, irreversible, wholeWord, expiresIn):
|
case let .create(phrase, context, irreversible, wholeWord, expiresIn):
|
||||||
return params(phrase: phrase,
|
return params(phrase: phrase,
|
||||||
|
@ -55,7 +55,7 @@ extension FilterEndpoint: MastodonEndpoint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var method: HTTPMethod {
|
public var method: HTTPMethod {
|
||||||
switch self {
|
switch self {
|
||||||
case .create:
|
case .create:
|
||||||
return .post
|
return .post
|
|
@ -2,25 +2,25 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
enum FiltersEndpoint {
|
public enum FiltersEndpoint {
|
||||||
case filters
|
case filters
|
||||||
}
|
}
|
||||||
|
|
||||||
extension FiltersEndpoint: MastodonEndpoint {
|
extension FiltersEndpoint: MastodonEndpoint {
|
||||||
typealias ResultType = [Filter]
|
public typealias ResultType = [Filter]
|
||||||
|
|
||||||
var context: [String] {
|
public var context: [String] {
|
||||||
defaultContext + ["filters"]
|
defaultContext + ["filters"]
|
||||||
}
|
}
|
||||||
|
|
||||||
var pathComponentsInContext: [String] {
|
public var pathComponentsInContext: [String] {
|
||||||
switch self {
|
switch self {
|
||||||
case .filters:
|
case .filters:
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var method: HTTPMethod {
|
public var method: HTTPMethod {
|
||||||
switch self {
|
switch self {
|
||||||
case .filters:
|
case .filters:
|
||||||
return .get
|
return .get
|
|
@ -2,20 +2,20 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
enum InstanceEndpoint {
|
public enum InstanceEndpoint {
|
||||||
case instance
|
case instance
|
||||||
}
|
}
|
||||||
|
|
||||||
extension InstanceEndpoint: MastodonEndpoint {
|
extension InstanceEndpoint: MastodonEndpoint {
|
||||||
typealias ResultType = Instance
|
public typealias ResultType = Instance
|
||||||
|
|
||||||
var pathComponentsInContext: [String] {
|
public var pathComponentsInContext: [String] {
|
||||||
switch self {
|
switch self {
|
||||||
case .instance: return ["instance"]
|
case .instance: return ["instance"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var method: HTTPMethod {
|
public var method: HTTPMethod {
|
||||||
switch self {
|
switch self {
|
||||||
case .instance: return .get
|
case .instance: return .get
|
||||||
}
|
}
|
|
@ -2,32 +2,32 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
enum ListEndpoint {
|
public enum ListEndpoint {
|
||||||
case create(title: String)
|
case create(title: String)
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ListEndpoint: MastodonEndpoint {
|
extension ListEndpoint: MastodonEndpoint {
|
||||||
typealias ResultType = MastodonList
|
public typealias ResultType = MastodonList
|
||||||
|
|
||||||
var context: [String] {
|
public var context: [String] {
|
||||||
defaultContext + ["lists"]
|
defaultContext + ["lists"]
|
||||||
}
|
}
|
||||||
|
|
||||||
var pathComponentsInContext: [String] {
|
public var pathComponentsInContext: [String] {
|
||||||
switch self {
|
switch self {
|
||||||
case .create:
|
case .create:
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var parameters: [String: Any]? {
|
public var parameters: [String: Any]? {
|
||||||
switch self {
|
switch self {
|
||||||
case let .create(title):
|
case let .create(title):
|
||||||
return ["title": title]
|
return ["title": title]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var method: HTTPMethod {
|
public var method: HTTPMethod {
|
||||||
switch self {
|
switch self {
|
||||||
case .create:
|
case .create:
|
||||||
return .post
|
return .post
|
|
@ -2,18 +2,18 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
enum ListsEndpoint {
|
public enum ListsEndpoint {
|
||||||
case lists
|
case lists
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ListsEndpoint: MastodonEndpoint {
|
extension ListsEndpoint: MastodonEndpoint {
|
||||||
typealias ResultType = [MastodonList]
|
public typealias ResultType = [MastodonList]
|
||||||
|
|
||||||
var pathComponentsInContext: [String] {
|
public var pathComponentsInContext: [String] {
|
||||||
["lists"]
|
["lists"]
|
||||||
}
|
}
|
||||||
|
|
||||||
var method: HTTPMethod {
|
public var method: HTTPMethod {
|
||||||
.get
|
.get
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
// Copyright © 2020 Metabolist. All rights reserved.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
public struct Paged<T: MastodonEndpoint> {
|
||||||
|
public let endpoint: T
|
||||||
|
public let maxID: String?
|
||||||
|
public let minID: String?
|
||||||
|
public let sinceID: String?
|
||||||
|
public let limit: Int?
|
||||||
|
|
||||||
|
public init(_ endpoint: T, maxID: String? = nil, minID: String? = nil, sinceID: String? = nil, limit: Int? = nil) {
|
||||||
|
self.endpoint = endpoint
|
||||||
|
self.maxID = maxID
|
||||||
|
self.minID = minID
|
||||||
|
self.sinceID = sinceID
|
||||||
|
self.limit = limit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Paged: MastodonEndpoint {
|
||||||
|
public typealias ResultType = T.ResultType
|
||||||
|
|
||||||
|
public var APIVersion: String { endpoint.APIVersion }
|
||||||
|
|
||||||
|
public var context: [String] { endpoint.context }
|
||||||
|
|
||||||
|
public var pathComponentsInContext: [String] { endpoint.pathComponentsInContext }
|
||||||
|
|
||||||
|
public var method: HTTPMethod { endpoint.method }
|
||||||
|
|
||||||
|
public var encoding: ParameterEncoding { endpoint.encoding }
|
||||||
|
|
||||||
|
public var parameters: [String: Any]? {
|
||||||
|
var parameters = endpoint.parameters ?? [String: Any]()
|
||||||
|
|
||||||
|
parameters["max_id"] = maxID
|
||||||
|
parameters["min_id"] = minID
|
||||||
|
parameters["since_id"] = sinceID
|
||||||
|
parameters["limit"] = limit
|
||||||
|
|
||||||
|
return parameters
|
||||||
|
}
|
||||||
|
|
||||||
|
public var headers: HTTPHeaders? { endpoint.headers }
|
||||||
|
}
|
|
@ -2,20 +2,20 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
enum PreferencesEndpoint {
|
public enum PreferencesEndpoint {
|
||||||
case preferences
|
case preferences
|
||||||
}
|
}
|
||||||
|
|
||||||
extension PreferencesEndpoint: MastodonEndpoint {
|
extension PreferencesEndpoint: MastodonEndpoint {
|
||||||
typealias ResultType = MastodonPreferences
|
public typealias ResultType = MastodonPreferences
|
||||||
|
|
||||||
var pathComponentsInContext: [String] {
|
public var pathComponentsInContext: [String] {
|
||||||
switch self {
|
switch self {
|
||||||
case .preferences: return ["preferences"]
|
case .preferences: return ["preferences"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var method: HTTPMethod {
|
public var method: HTTPMethod {
|
||||||
switch self {
|
switch self {
|
||||||
case .preferences: return .get
|
case .preferences: return .get
|
||||||
}
|
}
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
enum PushSubscriptionEndpoint {
|
public enum PushSubscriptionEndpoint {
|
||||||
case create(
|
case create(
|
||||||
endpoint: URL,
|
endpoint: URL,
|
||||||
publicKey: String,
|
publicKey: String,
|
||||||
|
@ -14,15 +14,15 @@ enum PushSubscriptionEndpoint {
|
||||||
}
|
}
|
||||||
|
|
||||||
extension PushSubscriptionEndpoint: MastodonEndpoint {
|
extension PushSubscriptionEndpoint: MastodonEndpoint {
|
||||||
typealias ResultType = PushSubscription
|
public typealias ResultType = PushSubscription
|
||||||
|
|
||||||
var context: [String] {
|
public var context: [String] {
|
||||||
defaultContext + ["push", "subscription"]
|
defaultContext + ["push", "subscription"]
|
||||||
}
|
}
|
||||||
|
|
||||||
var pathComponentsInContext: [String] { [] }
|
public var pathComponentsInContext: [String] { [] }
|
||||||
|
|
||||||
var method: HTTPMethod {
|
public var method: HTTPMethod {
|
||||||
switch self {
|
switch self {
|
||||||
case .create: return .post
|
case .create: return .post
|
||||||
case .read: return .get
|
case .read: return .get
|
||||||
|
@ -31,7 +31,7 @@ extension PushSubscriptionEndpoint: MastodonEndpoint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var parameters: [String: Any]? {
|
public var parameters: [String: Any]? {
|
||||||
switch self {
|
switch self {
|
||||||
case let .create(endpoint, publicKey, auth, alerts):
|
case let .create(endpoint, publicKey, auth, alerts):
|
||||||
return ["subscription":
|
return ["subscription":
|
|
@ -2,20 +2,20 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
enum StatusEndpoint {
|
public enum StatusEndpoint {
|
||||||
case status(id: String)
|
case status(id: String)
|
||||||
case favourite(id: String)
|
case favourite(id: String)
|
||||||
case unfavourite(id: String)
|
case unfavourite(id: String)
|
||||||
}
|
}
|
||||||
|
|
||||||
extension StatusEndpoint: MastodonEndpoint {
|
extension StatusEndpoint: MastodonEndpoint {
|
||||||
typealias ResultType = Status
|
public typealias ResultType = Status
|
||||||
|
|
||||||
var context: [String] {
|
public var context: [String] {
|
||||||
defaultContext + ["statuses"]
|
defaultContext + ["statuses"]
|
||||||
}
|
}
|
||||||
|
|
||||||
var pathComponentsInContext: [String] {
|
public var pathComponentsInContext: [String] {
|
||||||
switch self {
|
switch self {
|
||||||
case let .status(id):
|
case let .status(id):
|
||||||
return [id]
|
return [id]
|
||||||
|
@ -26,7 +26,7 @@ extension StatusEndpoint: MastodonEndpoint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var method: HTTPMethod {
|
public var method: HTTPMethod {
|
||||||
switch self {
|
switch self {
|
||||||
case .status:
|
case .status:
|
||||||
return .get
|
return .get
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
enum TimelinesEndpoint {
|
public enum TimelinesEndpoint {
|
||||||
case `public`(local: Bool)
|
case `public`(local: Bool)
|
||||||
case tag(String)
|
case tag(String)
|
||||||
case home
|
case home
|
||||||
|
@ -10,13 +10,13 @@ enum TimelinesEndpoint {
|
||||||
}
|
}
|
||||||
|
|
||||||
extension TimelinesEndpoint: MastodonEndpoint {
|
extension TimelinesEndpoint: MastodonEndpoint {
|
||||||
typealias ResultType = [Status]
|
public typealias ResultType = [Status]
|
||||||
|
|
||||||
var context: [String] {
|
public var context: [String] {
|
||||||
defaultContext + ["timelines"]
|
defaultContext + ["timelines"]
|
||||||
}
|
}
|
||||||
|
|
||||||
var pathComponentsInContext: [String] {
|
public var pathComponentsInContext: [String] {
|
||||||
switch self {
|
switch self {
|
||||||
case .public:
|
case .public:
|
||||||
return ["public"]
|
return ["public"]
|
||||||
|
@ -29,7 +29,7 @@ extension TimelinesEndpoint: MastodonEndpoint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var parameters: [String: Any]? {
|
public var parameters: [String: Any]? {
|
||||||
switch self {
|
switch self {
|
||||||
case let .public(local):
|
case let .public(local):
|
||||||
return ["local": local]
|
return ["local": local]
|
||||||
|
@ -38,5 +38,5 @@ extension TimelinesEndpoint: MastodonEndpoint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var method: HTTPMethod { .get }
|
public var method: HTTPMethod { .get }
|
||||||
}
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
// Copyright © 2020 Metabolist. All rights reserved.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import Combine
|
||||||
|
|
||||||
|
public class MastodonClient: HTTPClient {
|
||||||
|
public var instanceURL: URL?
|
||||||
|
public var accessToken: String?
|
||||||
|
|
||||||
|
public required init(session: Session) {
|
||||||
|
super.init(session: session, decoder: MastodonDecoder())
|
||||||
|
}
|
||||||
|
|
||||||
|
public override func request<T: DecodableTarget>(_ target: T) -> AnyPublisher<T.ResultType, Error> {
|
||||||
|
super.request(target, decodeErrorsAs: MastodonError.self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension MastodonClient {
|
||||||
|
public func request<E: MastodonEndpoint>(_ endpoint: E) -> AnyPublisher<E.ResultType, Error> {
|
||||||
|
guard let instanceURL = instanceURL else {
|
||||||
|
return Fail(error: URLError(.badURL)).eraseToAnyPublisher()
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.request(
|
||||||
|
MastodonTarget(baseURL: instanceURL, endpoint: endpoint, accessToken: accessToken),
|
||||||
|
decodeErrorsAs: MastodonError.self)
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,13 +2,13 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
class MastodonDecoder: JSONDecoder {
|
public class MastodonDecoder: JSONDecoder {
|
||||||
override init() {
|
public override init() {
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
let dateFormatter = DateFormatter()
|
let dateFormatter = DateFormatter()
|
||||||
|
|
||||||
dateFormatter.dateFormat = MastodonAPI.dateFormat
|
dateFormatter.dateFormat = Constants.dateFormat
|
||||||
dateDecodingStrategy = .formatted(dateFormatter)
|
dateDecodingStrategy = .formatted(dateFormatter)
|
||||||
keyDecodingStrategy = .convertFromSnakeCase
|
keyDecodingStrategy = .convertFromSnakeCase
|
||||||
}
|
}
|
|
@ -2,13 +2,13 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
class MastodonEncoder: JSONEncoder {
|
public class MastodonEncoder: JSONEncoder {
|
||||||
override init() {
|
public override init() {
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
let dateFormatter = DateFormatter()
|
let dateFormatter = DateFormatter()
|
||||||
|
|
||||||
dateFormatter.dateFormat = MastodonAPI.dateFormat
|
dateFormatter.dateFormat = Constants.dateFormat
|
||||||
dateEncodingStrategy = .formatted(dateFormatter)
|
dateEncodingStrategy = .formatted(dateFormatter)
|
||||||
keyEncodingStrategy = .convertToSnakeCase
|
keyEncodingStrategy = .convertToSnakeCase
|
||||||
outputFormatting = .sortedKeys
|
outputFormatting = .sortedKeys
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
protocol MastodonEndpoint {
|
public protocol MastodonEndpoint {
|
||||||
associatedtype ResultType: Decodable
|
associatedtype ResultType: Decodable
|
||||||
var APIVersion: String { get }
|
var APIVersion: String { get }
|
||||||
var context: [String] { get }
|
var context: [String] { get }
|
||||||
|
@ -13,7 +13,7 @@ protocol MastodonEndpoint {
|
||||||
var headers: HTTPHeaders? { get }
|
var headers: HTTPHeaders? { get }
|
||||||
}
|
}
|
||||||
|
|
||||||
extension MastodonEndpoint {
|
public extension MastodonEndpoint {
|
||||||
var defaultContext: [String] {
|
var defaultContext: [String] {
|
||||||
["api", APIVersion]
|
["api", APIVersion]
|
||||||
}
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
// Copyright © 2020 Metabolist. All rights reserved.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
public struct MastodonTarget<E: MastodonEndpoint> {
|
||||||
|
public let baseURL: URL
|
||||||
|
public let endpoint: E
|
||||||
|
public let accessToken: String?
|
||||||
|
|
||||||
|
public init(baseURL: URL, endpoint: E, accessToken: String?) {
|
||||||
|
self.baseURL = baseURL
|
||||||
|
self.endpoint = endpoint
|
||||||
|
self.accessToken = accessToken
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension MastodonTarget: DecodableTarget {
|
||||||
|
public typealias ResultType = E.ResultType
|
||||||
|
|
||||||
|
public var pathComponents: [String] { endpoint.pathComponents }
|
||||||
|
|
||||||
|
public var method: HTTPMethod { endpoint.method }
|
||||||
|
|
||||||
|
public var encoding: ParameterEncoding { endpoint.encoding }
|
||||||
|
|
||||||
|
public var parameters: [String: Any]? { endpoint.parameters }
|
||||||
|
|
||||||
|
public var headers: HTTPHeaders? {
|
||||||
|
var headers = endpoint.headers
|
||||||
|
|
||||||
|
if let accessToken = accessToken {
|
||||||
|
if headers == nil {
|
||||||
|
headers = HTTPHeaders()
|
||||||
|
}
|
||||||
|
|
||||||
|
headers?.add(.authorization(bearerToken: accessToken))
|
||||||
|
}
|
||||||
|
|
||||||
|
return headers
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,64 +4,66 @@ import Foundation
|
||||||
|
|
||||||
// Thank you https://www.swiftbysundell.com/tips/default-decoding-values/
|
// Thank you https://www.swiftbysundell.com/tips/default-decoding-values/
|
||||||
|
|
||||||
protocol DecodableDefaultSource {
|
public protocol DecodableDefaultSource {
|
||||||
associatedtype Value: Decodable
|
associatedtype Value: Decodable
|
||||||
static var defaultValue: Value { get }
|
static var defaultValue: Value { get }
|
||||||
}
|
}
|
||||||
|
|
||||||
enum DecodableDefault {}
|
public enum DecodableDefault {}
|
||||||
|
|
||||||
// swiftlint:disable nesting
|
// swiftlint:disable nesting
|
||||||
extension DecodableDefault {
|
extension DecodableDefault {
|
||||||
@propertyWrapper
|
@propertyWrapper
|
||||||
struct Wrapper<Source: DecodableDefaultSource> {
|
public struct Wrapper<Source: DecodableDefaultSource> {
|
||||||
typealias Value = Source.Value
|
public typealias Value = Source.Value
|
||||||
var wrappedValue = Source.defaultValue
|
public var wrappedValue = Source.defaultValue
|
||||||
|
|
||||||
|
public init() {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension DecodableDefault {
|
public extension DecodableDefault {
|
||||||
typealias Source = DecodableDefaultSource
|
typealias Source = DecodableDefaultSource
|
||||||
typealias List = Decodable & ExpressibleByArrayLiteral
|
typealias List = Decodable & ExpressibleByArrayLiteral
|
||||||
typealias Map = Decodable & ExpressibleByDictionaryLiteral
|
typealias Map = Decodable & ExpressibleByDictionaryLiteral
|
||||||
|
|
||||||
enum Sources {
|
enum Sources {
|
||||||
enum True: Source {
|
public enum True: Source {
|
||||||
static var defaultValue: Bool { true }
|
public static var defaultValue: Bool { true }
|
||||||
}
|
}
|
||||||
|
|
||||||
enum False: Source {
|
public enum False: Source {
|
||||||
static var defaultValue: Bool { false }
|
public static var defaultValue: Bool { false }
|
||||||
}
|
}
|
||||||
|
|
||||||
enum EmptyString: Source {
|
public enum EmptyString: Source {
|
||||||
static var defaultValue: String { "" }
|
public static var defaultValue: String { "" }
|
||||||
}
|
}
|
||||||
|
|
||||||
enum EmptyList<T: List>: Source {
|
public enum EmptyList<T: List>: Source {
|
||||||
static var defaultValue: T { [] }
|
public static var defaultValue: T { [] }
|
||||||
}
|
}
|
||||||
|
|
||||||
enum EmptyMap<T: Map>: Source {
|
public enum EmptyMap<T: Map>: Source {
|
||||||
static var defaultValue: T { [:] }
|
public static var defaultValue: T { [:] }
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Zero: Source {
|
public enum Zero: Source {
|
||||||
static var defaultValue: Int { 0 }
|
public static var defaultValue: Int { 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
enum StatusVisibilityPublic: Source {
|
public enum StatusVisibilityPublic: Source {
|
||||||
static var defaultValue: Status.Visibility { .public }
|
public static var defaultValue: Status.Visibility { .public }
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ExpandMediaDefault: Source {
|
public enum ExpandMediaDefault: Source {
|
||||||
static var defaultValue: MastodonPreferences.ExpandMedia { .default }
|
public static var defaultValue: MastodonPreferences.ExpandMedia { .default }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// swiftlint:enable nesting
|
// swiftlint:enable nesting
|
||||||
|
|
||||||
extension DecodableDefault {
|
public extension DecodableDefault {
|
||||||
typealias True = Wrapper<Sources.True>
|
typealias True = Wrapper<Sources.True>
|
||||||
typealias False = Wrapper<Sources.False>
|
typealias False = Wrapper<Sources.False>
|
||||||
typealias EmptyString = Wrapper<Sources.EmptyString>
|
typealias EmptyString = Wrapper<Sources.EmptyString>
|
||||||
|
@ -73,7 +75,7 @@ extension DecodableDefault {
|
||||||
}
|
}
|
||||||
|
|
||||||
extension DecodableDefault.Wrapper: Decodable {
|
extension DecodableDefault.Wrapper: Decodable {
|
||||||
init(from decoder: Decoder) throws {
|
public init(from decoder: Decoder) throws {
|
||||||
let container = try decoder.singleValueContainer()
|
let container = try decoder.singleValueContainer()
|
||||||
wrappedValue = try container.decode(Value.self)
|
wrappedValue = try container.decode(Value.self)
|
||||||
}
|
}
|
||||||
|
@ -83,13 +85,13 @@ extension DecodableDefault.Wrapper: Equatable where Value: Equatable {}
|
||||||
extension DecodableDefault.Wrapper: Hashable where Value: Hashable {}
|
extension DecodableDefault.Wrapper: Hashable where Value: Hashable {}
|
||||||
|
|
||||||
extension DecodableDefault.Wrapper: Encodable where Value: Encodable {
|
extension DecodableDefault.Wrapper: Encodable where Value: Encodable {
|
||||||
func encode(to encoder: Encoder) throws {
|
public func encode(to encoder: Encoder) throws {
|
||||||
var container = encoder.singleValueContainer()
|
var container = encoder.singleValueContainer()
|
||||||
try container.encode(wrappedValue)
|
try container.encode(wrappedValue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension KeyedDecodingContainer {
|
public extension KeyedDecodingContainer {
|
||||||
func decode<T>(_ type: DecodableDefault.Wrapper<T>.Type,
|
func decode<T>(_ type: DecodableDefault.Wrapper<T>.Type,
|
||||||
forKey key: Key) throws -> DecodableDefault.Wrapper<T> {
|
forKey key: Key) throws -> DecodableDefault.Wrapper<T> {
|
||||||
try decodeIfPresent(type, forKey: key) ?? .init()
|
try decodeIfPresent(type, forKey: key) ?? .init()
|
|
@ -2,16 +2,14 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
protocol Unknowable: RawRepresentable, CaseIterable where RawValue: Equatable {
|
public protocol Unknowable: RawRepresentable, CaseIterable where RawValue: Equatable {
|
||||||
static var unknownCase: Self { get }
|
static var unknownCase: Self { get }
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Unknowable {
|
public extension Unknowable {
|
||||||
init(rawValue: RawValue) {
|
init(rawValue: RawValue) {
|
||||||
self = Self.allCases.first { $0.rawValue == rawValue } ?? Self.unknownCase
|
self = Self.allCases.first { $0.rawValue == rawValue } ?? Self.unknownCase
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
extension Unknowable {
|
|
||||||
static var allCasesExceptUnknown: [Self] { allCases.filter { $0 != unknownCase } }
|
static var allCasesExceptUnknown: [Self] { allCases.filter { $0 != unknownCase } }
|
||||||
}
|
}
|
7
Mastodon/Tests/LinuxMain.swift
Normal file
7
Mastodon/Tests/LinuxMain.swift
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import XCTest
|
||||||
|
|
||||||
|
import MastodonTests
|
||||||
|
|
||||||
|
var tests = [XCTestCaseEntry]()
|
||||||
|
tests += MastodonTests.allTests()
|
||||||
|
XCTMain(tests)
|
15
Mastodon/Tests/MastodonTests/MastodonTests.swift
Normal file
15
Mastodon/Tests/MastodonTests/MastodonTests.swift
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import XCTest
|
||||||
|
@testable import Mastodon
|
||||||
|
|
||||||
|
final class MastodonTests: XCTestCase {
|
||||||
|
func testExample() {
|
||||||
|
// This is an example of a functional test case.
|
||||||
|
// Use XCTAssert and related functions to verify your tests produce the correct
|
||||||
|
// results.
|
||||||
|
XCTAssertEqual(Mastodon().text, "Hello, World!")
|
||||||
|
}
|
||||||
|
|
||||||
|
static var allTests = [
|
||||||
|
("testExample", testExample)
|
||||||
|
]
|
||||||
|
}
|
9
Mastodon/Tests/MastodonTests/XCTestManifests.swift
Normal file
9
Mastodon/Tests/MastodonTests/XCTestManifests.swift
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
import XCTest
|
||||||
|
|
||||||
|
#if !canImport(ObjectiveC)
|
||||||
|
public func allTests() -> [XCTestCaseEntry] {
|
||||||
|
return [
|
||||||
|
testCase(MastodonTests.allTests)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -27,17 +27,11 @@
|
||||||
D074577A24D29366004758DB /* URLSessionConfiguration+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D074577924D29366004758DB /* URLSessionConfiguration+Extensions.swift */; };
|
D074577A24D29366004758DB /* URLSessionConfiguration+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D074577924D29366004758DB /* URLSessionConfiguration+Extensions.swift */; };
|
||||||
D0A652AD24DE3EB6002EA33F /* PreferencesEndpoint+Stubbing.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0A652AC24DE3EB6002EA33F /* PreferencesEndpoint+Stubbing.swift */; };
|
D0A652AD24DE3EB6002EA33F /* PreferencesEndpoint+Stubbing.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0A652AC24DE3EB6002EA33F /* PreferencesEndpoint+Stubbing.swift */; };
|
||||||
D0BEB1F324F8EE8C001B0F04 /* AttachmentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEB1F224F8EE8C001B0F04 /* AttachmentView.swift */; };
|
D0BEB1F324F8EE8C001B0F04 /* AttachmentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEB1F224F8EE8C001B0F04 /* AttachmentView.swift */; };
|
||||||
D0BEB1F524F9A216001B0F04 /* Paged.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEB1F424F9A216001B0F04 /* Paged.swift */; };
|
|
||||||
D0BEB1F724F9A84B001B0F04 /* LoadingTableFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEB1F624F9A84B001B0F04 /* LoadingTableFooterView.swift */; };
|
D0BEB1F724F9A84B001B0F04 /* LoadingTableFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEB1F624F9A84B001B0F04 /* LoadingTableFooterView.swift */; };
|
||||||
D0BEB1F924F9D627001B0F04 /* ListsEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEB1F824F9D627001B0F04 /* ListsEndpoint.swift */; };
|
|
||||||
D0BEB1FD24F9E4E5001B0F04 /* ListsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEB1FC24F9E4E5001B0F04 /* ListsViewModel.swift */; };
|
D0BEB1FD24F9E4E5001B0F04 /* ListsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEB1FC24F9E4E5001B0F04 /* ListsViewModel.swift */; };
|
||||||
D0BEB1FF24F9E5BB001B0F04 /* ListsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEB1FE24F9E5BB001B0F04 /* ListsView.swift */; };
|
D0BEB1FF24F9E5BB001B0F04 /* ListsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEB1FE24F9E5BB001B0F04 /* ListsView.swift */; };
|
||||||
D0BEB20124FA0220001B0F04 /* ListEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEB20024FA0220001B0F04 /* ListEndpoint.swift */; };
|
|
||||||
D0BEB20524FA1107001B0F04 /* FiltersView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEB20424FA1107001B0F04 /* FiltersView.swift */; };
|
D0BEB20524FA1107001B0F04 /* FiltersView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEB20424FA1107001B0F04 /* FiltersView.swift */; };
|
||||||
D0BEB20724FA1121001B0F04 /* FiltersViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEB20624FA1121001B0F04 /* FiltersViewModel.swift */; };
|
D0BEB20724FA1121001B0F04 /* FiltersViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEB20624FA1121001B0F04 /* FiltersViewModel.swift */; };
|
||||||
D0BEB20924FA1136001B0F04 /* Filter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEB20824FA1136001B0F04 /* Filter.swift */; };
|
|
||||||
D0BEB20B24FA12D8001B0F04 /* FiltersEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEB20A24FA12D8001B0F04 /* FiltersEndpoint.swift */; };
|
|
||||||
D0BEB20D24FA193A001B0F04 /* FilterEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEB20C24FA193A001B0F04 /* FilterEndpoint.swift */; };
|
|
||||||
D0BEB21124FA2A91001B0F04 /* EditFilterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEB21024FA2A90001B0F04 /* EditFilterView.swift */; };
|
D0BEB21124FA2A91001B0F04 /* EditFilterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEB21024FA2A90001B0F04 /* EditFilterView.swift */; };
|
||||||
D0BEB21324FA2C0A001B0F04 /* EditFilterViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEB21224FA2C0A001B0F04 /* EditFilterViewModel.swift */; };
|
D0BEB21324FA2C0A001B0F04 /* EditFilterViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEB21224FA2C0A001B0F04 /* EditFilterViewModel.swift */; };
|
||||||
D0C7D49724F7616A001EBDBB /* IdentitiesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D42224F76169001EBDBB /* IdentitiesView.swift */; };
|
D0C7D49724F7616A001EBDBB /* IdentitiesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D42224F76169001EBDBB /* IdentitiesView.swift */; };
|
||||||
|
@ -51,32 +45,10 @@
|
||||||
D0C7D4A224F7616A001EBDBB /* NotificationTypesPreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D42D24F76169001EBDBB /* NotificationTypesPreferencesView.swift */; };
|
D0C7D4A224F7616A001EBDBB /* NotificationTypesPreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D42D24F76169001EBDBB /* NotificationTypesPreferencesView.swift */; };
|
||||||
D0C7D4A324F7616A001EBDBB /* TabNavigationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D42E24F76169001EBDBB /* TabNavigationView.swift */; };
|
D0C7D4A324F7616A001EBDBB /* TabNavigationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D42E24F76169001EBDBB /* TabNavigationView.swift */; };
|
||||||
D0C7D4A524F7616A001EBDBB /* StatusListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D43124F76169001EBDBB /* StatusListViewController.swift */; };
|
D0C7D4A524F7616A001EBDBB /* StatusListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D43124F76169001EBDBB /* StatusListViewController.swift */; };
|
||||||
D0C7D4A624F7616A001EBDBB /* DecodableDefault.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D43324F76169001EBDBB /* DecodableDefault.swift */; };
|
|
||||||
D0C7D4A924F7616A001EBDBB /* Mention.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D43924F76169001EBDBB /* Mention.swift */; };
|
|
||||||
D0C7D4AA24F7616A001EBDBB /* Attachment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D43A24F76169001EBDBB /* Attachment.swift */; };
|
|
||||||
D0C7D4AB24F7616A001EBDBB /* Identity.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D43B24F76169001EBDBB /* Identity.swift */; };
|
D0C7D4AB24F7616A001EBDBB /* Identity.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D43B24F76169001EBDBB /* Identity.swift */; };
|
||||||
D0C7D4AC24F7616A001EBDBB /* Poll.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D43C24F76169001EBDBB /* Poll.swift */; };
|
|
||||||
D0C7D4AD24F7616A001EBDBB /* AccessToken.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D43D24F76169001EBDBB /* AccessToken.swift */; };
|
|
||||||
D0C7D4AE24F7616A001EBDBB /* Timeline.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D43E24F76169001EBDBB /* Timeline.swift */; };
|
|
||||||
D0C7D4AF24F7616A001EBDBB /* PushNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D43F24F76169001EBDBB /* PushNotification.swift */; };
|
|
||||||
D0C7D4B024F7616A001EBDBB /* PushSubscription.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D44024F76169001EBDBB /* PushSubscription.swift */; };
|
|
||||||
D0C7D4B124F7616A001EBDBB /* Card.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D44124F76169001EBDBB /* Card.swift */; };
|
|
||||||
D0C7D4B224F7616A001EBDBB /* HTML.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D44224F76169001EBDBB /* HTML.swift */; };
|
|
||||||
D0C7D4B324F7616A001EBDBB /* MastodonError.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D44324F76169001EBDBB /* MastodonError.swift */; };
|
|
||||||
D0C7D4B424F7616A001EBDBB /* MastodonContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D44424F76169001EBDBB /* MastodonContext.swift */; };
|
|
||||||
D0C7D4B524F7616A001EBDBB /* Instance.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D44524F76169001EBDBB /* Instance.swift */; };
|
|
||||||
D0C7D4B624F7616A001EBDBB /* ListTimeline.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D44624F76169001EBDBB /* ListTimeline.swift */; };
|
|
||||||
D0C7D4B724F7616A001EBDBB /* TransientStatusCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D44724F76169001EBDBB /* TransientStatusCollection.swift */; };
|
D0C7D4B724F7616A001EBDBB /* TransientStatusCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D44724F76169001EBDBB /* TransientStatusCollection.swift */; };
|
||||||
D0C7D4B824F7616A001EBDBB /* Application.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D44824F76169001EBDBB /* Application.swift */; };
|
|
||||||
D0C7D4B924F7616A001EBDBB /* Status.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D44924F76169001EBDBB /* Status.swift */; };
|
|
||||||
D0C7D4BA24F7616A001EBDBB /* AppAuthorization.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D44A24F76169001EBDBB /* AppAuthorization.swift */; };
|
|
||||||
D0C7D4BB24F7616A001EBDBB /* Emoji.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D44B24F76169001EBDBB /* Emoji.swift */; };
|
|
||||||
D0C7D4BC24F7616A001EBDBB /* Tag.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D44C24F76169001EBDBB /* Tag.swift */; };
|
|
||||||
D0C7D4BD24F7616A001EBDBB /* Account.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D44D24F76169001EBDBB /* Account.swift */; };
|
|
||||||
D0C7D4BE24F7616A001EBDBB /* Unknowable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D44E24F76169001EBDBB /* Unknowable.swift */; };
|
|
||||||
D0C7D4BF24F7616A001EBDBB /* AppEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D44F24F76169001EBDBB /* AppEnvironment.swift */; };
|
D0C7D4BF24F7616A001EBDBB /* AppEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D44F24F76169001EBDBB /* AppEnvironment.swift */; };
|
||||||
D0C7D4C024F7616A001EBDBB /* AlertItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D45024F76169001EBDBB /* AlertItem.swift */; };
|
D0C7D4C024F7616A001EBDBB /* AlertItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D45024F76169001EBDBB /* AlertItem.swift */; };
|
||||||
D0C7D4C124F7616A001EBDBB /* MastodonPreferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D45124F76169001EBDBB /* MastodonPreferences.swift */; };
|
|
||||||
D0C7D4C224F7616A001EBDBB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D0C7D45224F76169001EBDBB /* Assets.xcassets */; };
|
D0C7D4C224F7616A001EBDBB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D0C7D45224F76169001EBDBB /* Assets.xcassets */; };
|
||||||
D0C7D4C324F7616A001EBDBB /* MetatextApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D45424F76169001EBDBB /* MetatextApp.swift */; };
|
D0C7D4C324F7616A001EBDBB /* MetatextApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D45424F76169001EBDBB /* MetatextApp.swift */; };
|
||||||
D0C7D4C424F7616A001EBDBB /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D45524F76169001EBDBB /* AppDelegate.swift */; };
|
D0C7D4C424F7616A001EBDBB /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D45524F76169001EBDBB /* AppDelegate.swift */; };
|
||||||
|
@ -104,26 +76,7 @@
|
||||||
D0C7D4DA24F7616A001EBDBB /* View+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D46F24F76169001EBDBB /* View+Extensions.swift */; };
|
D0C7D4DA24F7616A001EBDBB /* View+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D46F24F76169001EBDBB /* View+Extensions.swift */; };
|
||||||
D0C7D4DB24F7616A001EBDBB /* Date+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D47024F76169001EBDBB /* Date+Extensions.swift */; };
|
D0C7D4DB24F7616A001EBDBB /* Date+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D47024F76169001EBDBB /* Date+Extensions.swift */; };
|
||||||
D0C7D4DC24F7616A001EBDBB /* Data+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D47124F76169001EBDBB /* Data+Extensions.swift */; };
|
D0C7D4DC24F7616A001EBDBB /* Data+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D47124F76169001EBDBB /* Data+Extensions.swift */; };
|
||||||
D0C7D4DD24F7616A001EBDBB /* CodingUserInfoKey+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D47224F76169001EBDBB /* CodingUserInfoKey+Extensions.swift */; };
|
|
||||||
D0C7D4DE24F7616A001EBDBB /* HTTPTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D47424F76169001EBDBB /* HTTPTarget.swift */; };
|
|
||||||
D0C7D4DF24F7616A001EBDBB /* HTTPClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D47524F76169001EBDBB /* HTTPClient.swift */; };
|
|
||||||
D0C7D4E024F7616A001EBDBB /* WebAuthSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D47624F76169001EBDBB /* WebAuthSession.swift */; };
|
D0C7D4E024F7616A001EBDBB /* WebAuthSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D47624F76169001EBDBB /* WebAuthSession.swift */; };
|
||||||
D0C7D4E124F7616A001EBDBB /* MastodonDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D47824F76169001EBDBB /* MastodonDecoder.swift */; };
|
|
||||||
D0C7D4E224F7616A001EBDBB /* MastodonEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D47924F76169001EBDBB /* MastodonEndpoint.swift */; };
|
|
||||||
D0C7D4E324F7616A001EBDBB /* PushSubscriptionEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D47B24F76169001EBDBB /* PushSubscriptionEndpoint.swift */; };
|
|
||||||
D0C7D4E424F7616A001EBDBB /* PreferencesEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D47C24F76169001EBDBB /* PreferencesEndpoint.swift */; };
|
|
||||||
D0C7D4E524F7616A001EBDBB /* InstanceEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D47D24F76169001EBDBB /* InstanceEndpoint.swift */; };
|
|
||||||
D0C7D4E624F7616A001EBDBB /* TimelinesEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D47E24F76169001EBDBB /* TimelinesEndpoint.swift */; };
|
|
||||||
D0C7D4E724F7616A001EBDBB /* AppAuthorizationEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D47F24F76169001EBDBB /* AppAuthorizationEndpoint.swift */; };
|
|
||||||
D0C7D4E824F7616A001EBDBB /* AccountEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D48024F76169001EBDBB /* AccountEndpoint.swift */; };
|
|
||||||
D0C7D4E924F7616A001EBDBB /* AccessTokenEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D48124F76169001EBDBB /* AccessTokenEndpoint.swift */; };
|
|
||||||
D0C7D4EA24F7616A001EBDBB /* DeletionEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D48224F76169001EBDBB /* DeletionEndpoint.swift */; };
|
|
||||||
D0C7D4EB24F7616A001EBDBB /* ContextEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D48324F76169001EBDBB /* ContextEndpoint.swift */; };
|
|
||||||
D0C7D4EC24F7616A001EBDBB /* StatusEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D48424F76169001EBDBB /* StatusEndpoint.swift */; };
|
|
||||||
D0C7D4ED24F7616A001EBDBB /* MastodonAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D48524F76169001EBDBB /* MastodonAPI.swift */; };
|
|
||||||
D0C7D4EE24F7616A001EBDBB /* MastodonEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D48624F76169001EBDBB /* MastodonEncoder.swift */; };
|
|
||||||
D0C7D4EF24F7616A001EBDBB /* MastodonClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D48724F76169001EBDBB /* MastodonClient.swift */; };
|
|
||||||
D0C7D4F024F7616A001EBDBB /* MastodonTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D48824F76169001EBDBB /* MastodonTarget.swift */; };
|
|
||||||
D0C7D4F124F7616A001EBDBB /* IdentityService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D48A24F76169001EBDBB /* IdentityService.swift */; };
|
D0C7D4F124F7616A001EBDBB /* IdentityService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D48A24F76169001EBDBB /* IdentityService.swift */; };
|
||||||
D0C7D4F224F7616A001EBDBB /* TimelineService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D48C24F76169001EBDBB /* TimelineService.swift */; };
|
D0C7D4F224F7616A001EBDBB /* TimelineService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D48C24F76169001EBDBB /* TimelineService.swift */; };
|
||||||
D0C7D4F324F7616A001EBDBB /* ContextService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D48D24F76169001EBDBB /* ContextService.swift */; };
|
D0C7D4F324F7616A001EBDBB /* ContextService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D48D24F76169001EBDBB /* ContextService.swift */; };
|
||||||
|
@ -134,13 +87,9 @@
|
||||||
D0C7D4F824F7616A001EBDBB /* SecretsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D49224F7616A001EBDBB /* SecretsService.swift */; };
|
D0C7D4F824F7616A001EBDBB /* SecretsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D49224F7616A001EBDBB /* SecretsService.swift */; };
|
||||||
D0C7D4F924F7616A001EBDBB /* UserNotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D49324F7616A001EBDBB /* UserNotificationService.swift */; };
|
D0C7D4F924F7616A001EBDBB /* UserNotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D49324F7616A001EBDBB /* UserNotificationService.swift */; };
|
||||||
D0C7D4FA24F7616A001EBDBB /* AllIdentitiesService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D49424F7616A001EBDBB /* AllIdentitiesService.swift */; };
|
D0C7D4FA24F7616A001EBDBB /* AllIdentitiesService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D49424F7616A001EBDBB /* AllIdentitiesService.swift */; };
|
||||||
D0C7D4FB24F7619F001EBDBB /* PushNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D43F24F76169001EBDBB /* PushNotification.swift */; };
|
|
||||||
D0C7D4FC24F761A8001EBDBB /* Unknowable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D44E24F76169001EBDBB /* Unknowable.swift */; };
|
|
||||||
D0C7D4FD24F761C1001EBDBB /* MastodonDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D47824F76169001EBDBB /* MastodonDecoder.swift */; };
|
|
||||||
D0C7D4FE24F761C9001EBDBB /* SecretsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D49224F7616A001EBDBB /* SecretsService.swift */; };
|
D0C7D4FE24F761C9001EBDBB /* SecretsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D49224F7616A001EBDBB /* SecretsService.swift */; };
|
||||||
D0C7D4FF24F761D0001EBDBB /* KeychainService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D49024F7616A001EBDBB /* KeychainService.swift */; };
|
D0C7D4FF24F761D0001EBDBB /* KeychainService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D49024F7616A001EBDBB /* KeychainService.swift */; };
|
||||||
D0C7D50024F761E0001EBDBB /* NSError+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D46924F76169001EBDBB /* NSError+Extensions.swift */; };
|
D0C7D50024F761E0001EBDBB /* NSError+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D46924F76169001EBDBB /* NSError+Extensions.swift */; };
|
||||||
D0C7D50124F761EC001EBDBB /* MastodonAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D48524F76169001EBDBB /* MastodonAPI.swift */; };
|
|
||||||
D0DC174624CFEC2000A75C65 /* StubbingURLProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0DC174524CFEC2000A75C65 /* StubbingURLProtocol.swift */; };
|
D0DC174624CFEC2000A75C65 /* StubbingURLProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0DC174524CFEC2000A75C65 /* StubbingURLProtocol.swift */; };
|
||||||
D0DC174A24CFF15F00A75C65 /* AppAuthorizationEndpoint+Stubbing.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0DC174924CFF15F00A75C65 /* AppAuthorizationEndpoint+Stubbing.swift */; };
|
D0DC174A24CFF15F00A75C65 /* AppAuthorizationEndpoint+Stubbing.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0DC174924CFF15F00A75C65 /* AppAuthorizationEndpoint+Stubbing.swift */; };
|
||||||
D0DC174D24CFF1F100A75C65 /* Stubbing.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0DC174C24CFF1F100A75C65 /* Stubbing.swift */; };
|
D0DC174D24CFF1F100A75C65 /* Stubbing.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0DC174C24CFF1F100A75C65 /* Stubbing.swift */; };
|
||||||
|
@ -149,6 +98,8 @@
|
||||||
D0DC175824D0130800A75C65 /* HTTPStubs.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0DC175724D0130800A75C65 /* HTTPStubs.swift */; };
|
D0DC175824D0130800A75C65 /* HTTPStubs.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0DC175724D0130800A75C65 /* HTTPStubs.swift */; };
|
||||||
D0DC175F24D016EA00A75C65 /* Alamofire in Frameworks */ = {isa = PBXBuildFile; productRef = D0DC175E24D016EA00A75C65 /* Alamofire */; };
|
D0DC175F24D016EA00A75C65 /* Alamofire in Frameworks */ = {isa = PBXBuildFile; productRef = D0DC175E24D016EA00A75C65 /* Alamofire */; };
|
||||||
D0DC177724D0CF2600A75C65 /* MockKeychainService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0DC177624D0CF2600A75C65 /* MockKeychainService.swift */; };
|
D0DC177724D0CF2600A75C65 /* MockKeychainService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0DC177624D0CF2600A75C65 /* MockKeychainService.swift */; };
|
||||||
|
D0E0F1E624FC4B76002C04BF /* Mastodon in Frameworks */ = {isa = PBXBuildFile; productRef = D0E0F1E524FC4B76002C04BF /* Mastodon */; };
|
||||||
|
D0E0F1E824FC5A61002C04BF /* Mastodon in Frameworks */ = {isa = PBXBuildFile; productRef = D0E0F1E724FC5A61002C04BF /* Mastodon */; };
|
||||||
D0E5361C24E3EB4D00FB1CE1 /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0E5361B24E3EB4D00FB1CE1 /* NotificationService.swift */; };
|
D0E5361C24E3EB4D00FB1CE1 /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0E5361B24E3EB4D00FB1CE1 /* NotificationService.swift */; };
|
||||||
D0E5362024E3EB4D00FB1CE1 /* Notification Service Extension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = D0E5361924E3EB4D00FB1CE1 /* Notification Service Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
D0E5362024E3EB4D00FB1CE1 /* Notification Service Extension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = D0E5361924E3EB4D00FB1CE1 /* Notification Service Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||||
D0EC8DD424DFE38900A08489 /* AuthenticationServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0EC8DD324DFE38900A08489 /* AuthenticationServiceTests.swift */; };
|
D0EC8DD424DFE38900A08489 /* AuthenticationServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0EC8DD324DFE38900A08489 /* AuthenticationServiceTests.swift */; };
|
||||||
|
@ -207,17 +158,11 @@
|
||||||
D074577924D29366004758DB /* URLSessionConfiguration+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URLSessionConfiguration+Extensions.swift"; sourceTree = "<group>"; };
|
D074577924D29366004758DB /* URLSessionConfiguration+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URLSessionConfiguration+Extensions.swift"; sourceTree = "<group>"; };
|
||||||
D0A652AC24DE3EB6002EA33F /* PreferencesEndpoint+Stubbing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PreferencesEndpoint+Stubbing.swift"; sourceTree = "<group>"; };
|
D0A652AC24DE3EB6002EA33F /* PreferencesEndpoint+Stubbing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PreferencesEndpoint+Stubbing.swift"; sourceTree = "<group>"; };
|
||||||
D0BEB1F224F8EE8C001B0F04 /* AttachmentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttachmentView.swift; sourceTree = "<group>"; };
|
D0BEB1F224F8EE8C001B0F04 /* AttachmentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttachmentView.swift; sourceTree = "<group>"; };
|
||||||
D0BEB1F424F9A216001B0F04 /* Paged.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Paged.swift; sourceTree = "<group>"; };
|
|
||||||
D0BEB1F624F9A84B001B0F04 /* LoadingTableFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingTableFooterView.swift; sourceTree = "<group>"; };
|
D0BEB1F624F9A84B001B0F04 /* LoadingTableFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingTableFooterView.swift; sourceTree = "<group>"; };
|
||||||
D0BEB1F824F9D627001B0F04 /* ListsEndpoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListsEndpoint.swift; sourceTree = "<group>"; };
|
|
||||||
D0BEB1FC24F9E4E5001B0F04 /* ListsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListsViewModel.swift; sourceTree = "<group>"; };
|
D0BEB1FC24F9E4E5001B0F04 /* ListsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListsViewModel.swift; sourceTree = "<group>"; };
|
||||||
D0BEB1FE24F9E5BB001B0F04 /* ListsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListsView.swift; sourceTree = "<group>"; };
|
D0BEB1FE24F9E5BB001B0F04 /* ListsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListsView.swift; sourceTree = "<group>"; };
|
||||||
D0BEB20024FA0220001B0F04 /* ListEndpoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListEndpoint.swift; sourceTree = "<group>"; };
|
|
||||||
D0BEB20424FA1107001B0F04 /* FiltersView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FiltersView.swift; sourceTree = "<group>"; };
|
D0BEB20424FA1107001B0F04 /* FiltersView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FiltersView.swift; sourceTree = "<group>"; };
|
||||||
D0BEB20624FA1121001B0F04 /* FiltersViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FiltersViewModel.swift; sourceTree = "<group>"; };
|
D0BEB20624FA1121001B0F04 /* FiltersViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FiltersViewModel.swift; sourceTree = "<group>"; };
|
||||||
D0BEB20824FA1136001B0F04 /* Filter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Filter.swift; sourceTree = "<group>"; };
|
|
||||||
D0BEB20A24FA12D8001B0F04 /* FiltersEndpoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FiltersEndpoint.swift; sourceTree = "<group>"; };
|
|
||||||
D0BEB20C24FA193A001B0F04 /* FilterEndpoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilterEndpoint.swift; sourceTree = "<group>"; };
|
|
||||||
D0BEB21024FA2A90001B0F04 /* EditFilterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditFilterView.swift; sourceTree = "<group>"; };
|
D0BEB21024FA2A90001B0F04 /* EditFilterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditFilterView.swift; sourceTree = "<group>"; };
|
||||||
D0BEB21224FA2C0A001B0F04 /* EditFilterViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditFilterViewModel.swift; sourceTree = "<group>"; };
|
D0BEB21224FA2C0A001B0F04 /* EditFilterViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditFilterViewModel.swift; sourceTree = "<group>"; };
|
||||||
D0C7D41E24F76169001EBDBB /* Metatext.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Metatext.entitlements; sourceTree = "<group>"; };
|
D0C7D41E24F76169001EBDBB /* Metatext.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Metatext.entitlements; sourceTree = "<group>"; };
|
||||||
|
@ -233,32 +178,10 @@
|
||||||
D0C7D42D24F76169001EBDBB /* NotificationTypesPreferencesView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NotificationTypesPreferencesView.swift; sourceTree = "<group>"; };
|
D0C7D42D24F76169001EBDBB /* NotificationTypesPreferencesView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NotificationTypesPreferencesView.swift; sourceTree = "<group>"; };
|
||||||
D0C7D42E24F76169001EBDBB /* TabNavigationView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TabNavigationView.swift; sourceTree = "<group>"; };
|
D0C7D42E24F76169001EBDBB /* TabNavigationView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TabNavigationView.swift; sourceTree = "<group>"; };
|
||||||
D0C7D43124F76169001EBDBB /* StatusListViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatusListViewController.swift; sourceTree = "<group>"; };
|
D0C7D43124F76169001EBDBB /* StatusListViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatusListViewController.swift; sourceTree = "<group>"; };
|
||||||
D0C7D43324F76169001EBDBB /* DecodableDefault.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DecodableDefault.swift; sourceTree = "<group>"; };
|
|
||||||
D0C7D43924F76169001EBDBB /* Mention.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Mention.swift; sourceTree = "<group>"; };
|
|
||||||
D0C7D43A24F76169001EBDBB /* Attachment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Attachment.swift; sourceTree = "<group>"; };
|
|
||||||
D0C7D43B24F76169001EBDBB /* Identity.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Identity.swift; sourceTree = "<group>"; };
|
D0C7D43B24F76169001EBDBB /* Identity.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Identity.swift; sourceTree = "<group>"; };
|
||||||
D0C7D43C24F76169001EBDBB /* Poll.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Poll.swift; sourceTree = "<group>"; };
|
|
||||||
D0C7D43D24F76169001EBDBB /* AccessToken.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccessToken.swift; sourceTree = "<group>"; };
|
|
||||||
D0C7D43E24F76169001EBDBB /* Timeline.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Timeline.swift; sourceTree = "<group>"; };
|
|
||||||
D0C7D43F24F76169001EBDBB /* PushNotification.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PushNotification.swift; sourceTree = "<group>"; };
|
|
||||||
D0C7D44024F76169001EBDBB /* PushSubscription.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PushSubscription.swift; sourceTree = "<group>"; };
|
|
||||||
D0C7D44124F76169001EBDBB /* Card.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Card.swift; sourceTree = "<group>"; };
|
|
||||||
D0C7D44224F76169001EBDBB /* HTML.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTML.swift; sourceTree = "<group>"; };
|
|
||||||
D0C7D44324F76169001EBDBB /* MastodonError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MastodonError.swift; sourceTree = "<group>"; };
|
|
||||||
D0C7D44424F76169001EBDBB /* MastodonContext.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MastodonContext.swift; sourceTree = "<group>"; };
|
|
||||||
D0C7D44524F76169001EBDBB /* Instance.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Instance.swift; sourceTree = "<group>"; };
|
|
||||||
D0C7D44624F76169001EBDBB /* ListTimeline.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListTimeline.swift; sourceTree = "<group>"; };
|
|
||||||
D0C7D44724F76169001EBDBB /* TransientStatusCollection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransientStatusCollection.swift; sourceTree = "<group>"; };
|
D0C7D44724F76169001EBDBB /* TransientStatusCollection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransientStatusCollection.swift; sourceTree = "<group>"; };
|
||||||
D0C7D44824F76169001EBDBB /* Application.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Application.swift; sourceTree = "<group>"; };
|
|
||||||
D0C7D44924F76169001EBDBB /* Status.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Status.swift; sourceTree = "<group>"; };
|
|
||||||
D0C7D44A24F76169001EBDBB /* AppAuthorization.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppAuthorization.swift; sourceTree = "<group>"; };
|
|
||||||
D0C7D44B24F76169001EBDBB /* Emoji.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Emoji.swift; sourceTree = "<group>"; };
|
|
||||||
D0C7D44C24F76169001EBDBB /* Tag.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Tag.swift; sourceTree = "<group>"; };
|
|
||||||
D0C7D44D24F76169001EBDBB /* Account.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Account.swift; sourceTree = "<group>"; };
|
|
||||||
D0C7D44E24F76169001EBDBB /* Unknowable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Unknowable.swift; sourceTree = "<group>"; };
|
|
||||||
D0C7D44F24F76169001EBDBB /* AppEnvironment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppEnvironment.swift; sourceTree = "<group>"; };
|
D0C7D44F24F76169001EBDBB /* AppEnvironment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppEnvironment.swift; sourceTree = "<group>"; };
|
||||||
D0C7D45024F76169001EBDBB /* AlertItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlertItem.swift; sourceTree = "<group>"; };
|
D0C7D45024F76169001EBDBB /* AlertItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlertItem.swift; sourceTree = "<group>"; };
|
||||||
D0C7D45124F76169001EBDBB /* MastodonPreferences.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MastodonPreferences.swift; sourceTree = "<group>"; };
|
|
||||||
D0C7D45224F76169001EBDBB /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
D0C7D45224F76169001EBDBB /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||||
D0C7D45424F76169001EBDBB /* MetatextApp.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MetatextApp.swift; sourceTree = "<group>"; };
|
D0C7D45424F76169001EBDBB /* MetatextApp.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MetatextApp.swift; sourceTree = "<group>"; };
|
||||||
D0C7D45524F76169001EBDBB /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
D0C7D45524F76169001EBDBB /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||||
|
@ -286,26 +209,7 @@
|
||||||
D0C7D46F24F76169001EBDBB /* View+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "View+Extensions.swift"; sourceTree = "<group>"; };
|
D0C7D46F24F76169001EBDBB /* View+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "View+Extensions.swift"; sourceTree = "<group>"; };
|
||||||
D0C7D47024F76169001EBDBB /* Date+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Date+Extensions.swift"; sourceTree = "<group>"; };
|
D0C7D47024F76169001EBDBB /* Date+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Date+Extensions.swift"; sourceTree = "<group>"; };
|
||||||
D0C7D47124F76169001EBDBB /* Data+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Data+Extensions.swift"; sourceTree = "<group>"; };
|
D0C7D47124F76169001EBDBB /* Data+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Data+Extensions.swift"; sourceTree = "<group>"; };
|
||||||
D0C7D47224F76169001EBDBB /* CodingUserInfoKey+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CodingUserInfoKey+Extensions.swift"; sourceTree = "<group>"; };
|
|
||||||
D0C7D47424F76169001EBDBB /* HTTPTarget.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTTPTarget.swift; sourceTree = "<group>"; };
|
|
||||||
D0C7D47524F76169001EBDBB /* HTTPClient.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTTPClient.swift; sourceTree = "<group>"; };
|
|
||||||
D0C7D47624F76169001EBDBB /* WebAuthSession.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebAuthSession.swift; sourceTree = "<group>"; };
|
D0C7D47624F76169001EBDBB /* WebAuthSession.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebAuthSession.swift; sourceTree = "<group>"; };
|
||||||
D0C7D47824F76169001EBDBB /* MastodonDecoder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MastodonDecoder.swift; sourceTree = "<group>"; };
|
|
||||||
D0C7D47924F76169001EBDBB /* MastodonEndpoint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MastodonEndpoint.swift; sourceTree = "<group>"; };
|
|
||||||
D0C7D47B24F76169001EBDBB /* PushSubscriptionEndpoint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PushSubscriptionEndpoint.swift; sourceTree = "<group>"; };
|
|
||||||
D0C7D47C24F76169001EBDBB /* PreferencesEndpoint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreferencesEndpoint.swift; sourceTree = "<group>"; };
|
|
||||||
D0C7D47D24F76169001EBDBB /* InstanceEndpoint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InstanceEndpoint.swift; sourceTree = "<group>"; };
|
|
||||||
D0C7D47E24F76169001EBDBB /* TimelinesEndpoint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TimelinesEndpoint.swift; sourceTree = "<group>"; };
|
|
||||||
D0C7D47F24F76169001EBDBB /* AppAuthorizationEndpoint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppAuthorizationEndpoint.swift; sourceTree = "<group>"; };
|
|
||||||
D0C7D48024F76169001EBDBB /* AccountEndpoint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountEndpoint.swift; sourceTree = "<group>"; };
|
|
||||||
D0C7D48124F76169001EBDBB /* AccessTokenEndpoint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccessTokenEndpoint.swift; sourceTree = "<group>"; };
|
|
||||||
D0C7D48224F76169001EBDBB /* DeletionEndpoint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeletionEndpoint.swift; sourceTree = "<group>"; };
|
|
||||||
D0C7D48324F76169001EBDBB /* ContextEndpoint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContextEndpoint.swift; sourceTree = "<group>"; };
|
|
||||||
D0C7D48424F76169001EBDBB /* StatusEndpoint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatusEndpoint.swift; sourceTree = "<group>"; };
|
|
||||||
D0C7D48524F76169001EBDBB /* MastodonAPI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MastodonAPI.swift; sourceTree = "<group>"; };
|
|
||||||
D0C7D48624F76169001EBDBB /* MastodonEncoder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MastodonEncoder.swift; sourceTree = "<group>"; };
|
|
||||||
D0C7D48724F76169001EBDBB /* MastodonClient.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MastodonClient.swift; sourceTree = "<group>"; };
|
|
||||||
D0C7D48824F76169001EBDBB /* MastodonTarget.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MastodonTarget.swift; sourceTree = "<group>"; };
|
|
||||||
D0C7D48A24F76169001EBDBB /* IdentityService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IdentityService.swift; sourceTree = "<group>"; };
|
D0C7D48A24F76169001EBDBB /* IdentityService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IdentityService.swift; sourceTree = "<group>"; };
|
||||||
D0C7D48C24F76169001EBDBB /* TimelineService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TimelineService.swift; sourceTree = "<group>"; };
|
D0C7D48C24F76169001EBDBB /* TimelineService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TimelineService.swift; sourceTree = "<group>"; };
|
||||||
D0C7D48D24F76169001EBDBB /* ContextService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContextService.swift; sourceTree = "<group>"; };
|
D0C7D48D24F76169001EBDBB /* ContextService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContextService.swift; sourceTree = "<group>"; };
|
||||||
|
@ -323,6 +227,7 @@
|
||||||
D0DC175424D00F0A00A75C65 /* AccessTokenEndpoint+Stubbing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AccessTokenEndpoint+Stubbing.swift"; sourceTree = "<group>"; };
|
D0DC175424D00F0A00A75C65 /* AccessTokenEndpoint+Stubbing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AccessTokenEndpoint+Stubbing.swift"; sourceTree = "<group>"; };
|
||||||
D0DC175724D0130800A75C65 /* HTTPStubs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HTTPStubs.swift; sourceTree = "<group>"; };
|
D0DC175724D0130800A75C65 /* HTTPStubs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HTTPStubs.swift; sourceTree = "<group>"; };
|
||||||
D0DC177624D0CF2600A75C65 /* MockKeychainService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockKeychainService.swift; sourceTree = "<group>"; };
|
D0DC177624D0CF2600A75C65 /* MockKeychainService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockKeychainService.swift; sourceTree = "<group>"; };
|
||||||
|
D0E0F1E424FC49FC002C04BF /* Mastodon */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Mastodon; sourceTree = "<group>"; };
|
||||||
D0E5361924E3EB4D00FB1CE1 /* Notification Service Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "Notification Service Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
|
D0E5361924E3EB4D00FB1CE1 /* Notification Service Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "Notification Service Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
D0E5361B24E3EB4D00FB1CE1 /* NotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationService.swift; sourceTree = "<group>"; };
|
D0E5361B24E3EB4D00FB1CE1 /* NotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationService.swift; sourceTree = "<group>"; };
|
||||||
D0E5361D24E3EB4D00FB1CE1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
D0E5361D24E3EB4D00FB1CE1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
|
@ -337,6 +242,7 @@
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
D06B492324D4611300642749 /* KingfisherSwiftUI in Frameworks */,
|
D06B492324D4611300642749 /* KingfisherSwiftUI in Frameworks */,
|
||||||
|
D0E0F1E624FC4B76002C04BF /* Mastodon in Frameworks */,
|
||||||
D0666A4924C6C1A300F3F04B /* GRDB in Frameworks */,
|
D0666A4924C6C1A300F3F04B /* GRDB in Frameworks */,
|
||||||
D0DC175F24D016EA00A75C65 /* Alamofire in Frameworks */,
|
D0DC175F24D016EA00A75C65 /* Alamofire in Frameworks */,
|
||||||
);
|
);
|
||||||
|
@ -354,6 +260,7 @@
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
D0E0F1E824FC5A61002C04BF /* Mastodon in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
@ -382,6 +289,7 @@
|
||||||
D047FA7F24C3E21000AF17C5 = {
|
D047FA7F24C3E21000AF17C5 = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
D0E0F1E424FC49FC002C04BF /* Mastodon */,
|
||||||
D0C7D45224F76169001EBDBB /* Assets.xcassets */,
|
D0C7D45224F76169001EBDBB /* Assets.xcassets */,
|
||||||
D0C7D46424F76169001EBDBB /* Databases */,
|
D0C7D46424F76169001EBDBB /* Databases */,
|
||||||
D0ED1BB224CE3A1600B4899C /* Development Assets */,
|
D0ED1BB224CE3A1600B4899C /* Development Assets */,
|
||||||
|
@ -392,7 +300,6 @@
|
||||||
D0C7D47324F76169001EBDBB /* Networking */,
|
D0C7D47324F76169001EBDBB /* Networking */,
|
||||||
D0E5361A24E3EB4D00FB1CE1 /* Notification Service Extension */,
|
D0E5361A24E3EB4D00FB1CE1 /* Notification Service Extension */,
|
||||||
D047FA8D24C3E21200AF17C5 /* Products */,
|
D047FA8D24C3E21200AF17C5 /* Products */,
|
||||||
D0C7D43224F76169001EBDBB /* Property Wrappers */,
|
|
||||||
D0C7D48924F76169001EBDBB /* Services */,
|
D0C7D48924F76169001EBDBB /* Services */,
|
||||||
D0C7D41D24F76169001EBDBB /* Supporting Files */,
|
D0C7D41D24F76169001EBDBB /* Supporting Files */,
|
||||||
D0C7D45324F76169001EBDBB /* System */,
|
D0C7D45324F76169001EBDBB /* System */,
|
||||||
|
@ -470,43 +377,13 @@
|
||||||
path = "View Controllers";
|
path = "View Controllers";
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
D0C7D43224F76169001EBDBB /* Property Wrappers */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
D0C7D43324F76169001EBDBB /* DecodableDefault.swift */,
|
|
||||||
);
|
|
||||||
path = "Property Wrappers";
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
D0C7D43824F76169001EBDBB /* Model */ = {
|
D0C7D43824F76169001EBDBB /* Model */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
D0C7D43D24F76169001EBDBB /* AccessToken.swift */,
|
|
||||||
D0C7D44D24F76169001EBDBB /* Account.swift */,
|
|
||||||
D0C7D45024F76169001EBDBB /* AlertItem.swift */,
|
D0C7D45024F76169001EBDBB /* AlertItem.swift */,
|
||||||
D0C7D44A24F76169001EBDBB /* AppAuthorization.swift */,
|
|
||||||
D0C7D44F24F76169001EBDBB /* AppEnvironment.swift */,
|
D0C7D44F24F76169001EBDBB /* AppEnvironment.swift */,
|
||||||
D0C7D44824F76169001EBDBB /* Application.swift */,
|
|
||||||
D0C7D43A24F76169001EBDBB /* Attachment.swift */,
|
|
||||||
D0C7D44124F76169001EBDBB /* Card.swift */,
|
|
||||||
D0C7D44B24F76169001EBDBB /* Emoji.swift */,
|
|
||||||
D0BEB20824FA1136001B0F04 /* Filter.swift */,
|
|
||||||
D0C7D44224F76169001EBDBB /* HTML.swift */,
|
|
||||||
D0C7D43B24F76169001EBDBB /* Identity.swift */,
|
D0C7D43B24F76169001EBDBB /* Identity.swift */,
|
||||||
D0C7D44524F76169001EBDBB /* Instance.swift */,
|
|
||||||
D0C7D44624F76169001EBDBB /* ListTimeline.swift */,
|
|
||||||
D0C7D44424F76169001EBDBB /* MastodonContext.swift */,
|
|
||||||
D0C7D44324F76169001EBDBB /* MastodonError.swift */,
|
|
||||||
D0C7D45124F76169001EBDBB /* MastodonPreferences.swift */,
|
|
||||||
D0C7D43924F76169001EBDBB /* Mention.swift */,
|
|
||||||
D0C7D43C24F76169001EBDBB /* Poll.swift */,
|
|
||||||
D0C7D43F24F76169001EBDBB /* PushNotification.swift */,
|
|
||||||
D0C7D44024F76169001EBDBB /* PushSubscription.swift */,
|
|
||||||
D0C7D44924F76169001EBDBB /* Status.swift */,
|
|
||||||
D0C7D44C24F76169001EBDBB /* Tag.swift */,
|
|
||||||
D0C7D43E24F76169001EBDBB /* Timeline.swift */,
|
|
||||||
D0C7D44724F76169001EBDBB /* TransientStatusCollection.swift */,
|
D0C7D44724F76169001EBDBB /* TransientStatusCollection.swift */,
|
||||||
D0C7D44E24F76169001EBDBB /* Unknowable.swift */,
|
|
||||||
);
|
);
|
||||||
path = Model;
|
path = Model;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -563,7 +440,6 @@
|
||||||
D0C7D46824F76169001EBDBB /* Extensions */ = {
|
D0C7D46824F76169001EBDBB /* Extensions */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
D0C7D47224F76169001EBDBB /* CodingUserInfoKey+Extensions.swift */,
|
|
||||||
D0C7D47124F76169001EBDBB /* Data+Extensions.swift */,
|
D0C7D47124F76169001EBDBB /* Data+Extensions.swift */,
|
||||||
D0C7D47024F76169001EBDBB /* Date+Extensions.swift */,
|
D0C7D47024F76169001EBDBB /* Date+Extensions.swift */,
|
||||||
D0C7D46E24F76169001EBDBB /* KingfisherOptionsInfo+Extensions.swift */,
|
D0C7D46E24F76169001EBDBB /* KingfisherOptionsInfo+Extensions.swift */,
|
||||||
|
@ -580,50 +456,11 @@
|
||||||
D0C7D47324F76169001EBDBB /* Networking */ = {
|
D0C7D47324F76169001EBDBB /* Networking */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
D0C7D47524F76169001EBDBB /* HTTPClient.swift */,
|
|
||||||
D0C7D47424F76169001EBDBB /* HTTPTarget.swift */,
|
|
||||||
D0C7D47724F76169001EBDBB /* Mastodon API */,
|
|
||||||
D0C7D47624F76169001EBDBB /* WebAuthSession.swift */,
|
D0C7D47624F76169001EBDBB /* WebAuthSession.swift */,
|
||||||
);
|
);
|
||||||
path = Networking;
|
path = Networking;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
D0C7D47724F76169001EBDBB /* Mastodon API */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
D0C7D47A24F76169001EBDBB /* Endpoints */,
|
|
||||||
D0C7D48524F76169001EBDBB /* MastodonAPI.swift */,
|
|
||||||
D0C7D48724F76169001EBDBB /* MastodonClient.swift */,
|
|
||||||
D0C7D47824F76169001EBDBB /* MastodonDecoder.swift */,
|
|
||||||
D0C7D48624F76169001EBDBB /* MastodonEncoder.swift */,
|
|
||||||
D0C7D47924F76169001EBDBB /* MastodonEndpoint.swift */,
|
|
||||||
D0C7D48824F76169001EBDBB /* MastodonTarget.swift */,
|
|
||||||
);
|
|
||||||
path = "Mastodon API";
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
D0C7D47A24F76169001EBDBB /* Endpoints */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
D0C7D48124F76169001EBDBB /* AccessTokenEndpoint.swift */,
|
|
||||||
D0C7D48024F76169001EBDBB /* AccountEndpoint.swift */,
|
|
||||||
D0C7D47F24F76169001EBDBB /* AppAuthorizationEndpoint.swift */,
|
|
||||||
D0C7D48324F76169001EBDBB /* ContextEndpoint.swift */,
|
|
||||||
D0C7D48224F76169001EBDBB /* DeletionEndpoint.swift */,
|
|
||||||
D0BEB20C24FA193A001B0F04 /* FilterEndpoint.swift */,
|
|
||||||
D0BEB20A24FA12D8001B0F04 /* FiltersEndpoint.swift */,
|
|
||||||
D0C7D47D24F76169001EBDBB /* InstanceEndpoint.swift */,
|
|
||||||
D0BEB20024FA0220001B0F04 /* ListEndpoint.swift */,
|
|
||||||
D0BEB1F824F9D627001B0F04 /* ListsEndpoint.swift */,
|
|
||||||
D0BEB1F424F9A216001B0F04 /* Paged.swift */,
|
|
||||||
D0C7D47C24F76169001EBDBB /* PreferencesEndpoint.swift */,
|
|
||||||
D0C7D47B24F76169001EBDBB /* PushSubscriptionEndpoint.swift */,
|
|
||||||
D0C7D48424F76169001EBDBB /* StatusEndpoint.swift */,
|
|
||||||
D0C7D47E24F76169001EBDBB /* TimelinesEndpoint.swift */,
|
|
||||||
);
|
|
||||||
path = Endpoints;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
D0C7D48924F76169001EBDBB /* Services */ = {
|
D0C7D48924F76169001EBDBB /* Services */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
@ -731,6 +568,7 @@
|
||||||
D0666A4824C6C1A300F3F04B /* GRDB */,
|
D0666A4824C6C1A300F3F04B /* GRDB */,
|
||||||
D0DC175E24D016EA00A75C65 /* Alamofire */,
|
D0DC175E24D016EA00A75C65 /* Alamofire */,
|
||||||
D06B492224D4611300642749 /* KingfisherSwiftUI */,
|
D06B492224D4611300642749 /* KingfisherSwiftUI */,
|
||||||
|
D0E0F1E524FC4B76002C04BF /* Mastodon */,
|
||||||
);
|
);
|
||||||
productName = "Metatext (iOS)";
|
productName = "Metatext (iOS)";
|
||||||
productReference = D047FA8C24C3E21200AF17C5 /* Metatext.app */;
|
productReference = D047FA8C24C3E21200AF17C5 /* Metatext.app */;
|
||||||
|
@ -771,6 +609,7 @@
|
||||||
);
|
);
|
||||||
name = "Notification Service Extension";
|
name = "Notification Service Extension";
|
||||||
packageProductDependencies = (
|
packageProductDependencies = (
|
||||||
|
D0E0F1E724FC5A61002C04BF /* Mastodon */,
|
||||||
);
|
);
|
||||||
productName = "Notification Service Extension";
|
productName = "Notification Service Extension";
|
||||||
productReference = D0E5361924E3EB4D00FB1CE1 /* Notification Service Extension.appex */;
|
productReference = D0E5361924E3EB4D00FB1CE1 /* Notification Service Extension.appex */;
|
||||||
|
@ -880,16 +719,9 @@
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
D0C7D4CA24F7616A001EBDBB /* NotificationTypesPreferencesViewModel.swift in Sources */,
|
D0C7D4CA24F7616A001EBDBB /* NotificationTypesPreferencesViewModel.swift in Sources */,
|
||||||
D0C7D4EE24F7616A001EBDBB /* MastodonEncoder.swift in Sources */,
|
|
||||||
D0C7D4E624F7616A001EBDBB /* TimelinesEndpoint.swift in Sources */,
|
|
||||||
D0C7D4B924F7616A001EBDBB /* Status.swift in Sources */,
|
|
||||||
D0C7D4F424F7616A001EBDBB /* StatusListService.swift in Sources */,
|
D0C7D4F424F7616A001EBDBB /* StatusListService.swift in Sources */,
|
||||||
D0C7D4B824F7616A001EBDBB /* Application.swift in Sources */,
|
|
||||||
D0C7D4E724F7616A001EBDBB /* AppAuthorizationEndpoint.swift in Sources */,
|
|
||||||
D0C7D4EA24F7616A001EBDBB /* DeletionEndpoint.swift in Sources */,
|
|
||||||
D0C7D4B724F7616A001EBDBB /* TransientStatusCollection.swift in Sources */,
|
D0C7D4B724F7616A001EBDBB /* TransientStatusCollection.swift in Sources */,
|
||||||
D01F41DF24F8868800D55A2D /* AttachmentViewModel.swift in Sources */,
|
D01F41DF24F8868800D55A2D /* AttachmentViewModel.swift in Sources */,
|
||||||
D0C7D4E824F7616A001EBDBB /* AccountEndpoint.swift in Sources */,
|
|
||||||
D0C7D4A324F7616A001EBDBB /* TabNavigationView.swift in Sources */,
|
D0C7D4A324F7616A001EBDBB /* TabNavigationView.swift in Sources */,
|
||||||
D0C7D49C24F7616A001EBDBB /* RootView.swift in Sources */,
|
D0C7D49C24F7616A001EBDBB /* RootView.swift in Sources */,
|
||||||
D0C7D4D224F7616A001EBDBB /* ContentDatabase.swift in Sources */,
|
D0C7D4D224F7616A001EBDBB /* ContentDatabase.swift in Sources */,
|
||||||
|
@ -900,55 +732,33 @@
|
||||||
D0C7D4CD24F7616A001EBDBB /* AddIdentityViewModel.swift in Sources */,
|
D0C7D4CD24F7616A001EBDBB /* AddIdentityViewModel.swift in Sources */,
|
||||||
D03658D124EDD80900AC17EC /* ContextEndpoint+Stubbing.swift in Sources */,
|
D03658D124EDD80900AC17EC /* ContextEndpoint+Stubbing.swift in Sources */,
|
||||||
D0BEB1F324F8EE8C001B0F04 /* AttachmentView.swift in Sources */,
|
D0BEB1F324F8EE8C001B0F04 /* AttachmentView.swift in Sources */,
|
||||||
D0BEB1F524F9A216001B0F04 /* Paged.swift in Sources */,
|
|
||||||
D0DC174A24CFF15F00A75C65 /* AppAuthorizationEndpoint+Stubbing.swift in Sources */,
|
D0DC174A24CFF15F00A75C65 /* AppAuthorizationEndpoint+Stubbing.swift in Sources */,
|
||||||
D0BEB20D24FA193A001B0F04 /* FilterEndpoint.swift in Sources */,
|
|
||||||
D0C7D49A24F7616A001EBDBB /* StatusListView.swift in Sources */,
|
D0C7D49A24F7616A001EBDBB /* StatusListView.swift in Sources */,
|
||||||
D01F41D924F880C400D55A2D /* TouchFallthroughTextView.swift in Sources */,
|
D01F41D924F880C400D55A2D /* TouchFallthroughTextView.swift in Sources */,
|
||||||
D0BEB20924FA1136001B0F04 /* Filter.swift in Sources */,
|
|
||||||
D0C7D4A524F7616A001EBDBB /* StatusListViewController.swift in Sources */,
|
D0C7D4A524F7616A001EBDBB /* StatusListViewController.swift in Sources */,
|
||||||
D0C7D4CC24F7616A001EBDBB /* IdentitiesViewModel.swift in Sources */,
|
D0C7D4CC24F7616A001EBDBB /* IdentitiesViewModel.swift in Sources */,
|
||||||
D0C7D4E024F7616A001EBDBB /* WebAuthSession.swift in Sources */,
|
D0C7D4E024F7616A001EBDBB /* WebAuthSession.swift in Sources */,
|
||||||
D0C7D4F024F7616A001EBDBB /* MastodonTarget.swift in Sources */,
|
|
||||||
D0C7D4A624F7616A001EBDBB /* DecodableDefault.swift in Sources */,
|
|
||||||
D0C7D4CB24F7616A001EBDBB /* RootViewModel.swift in Sources */,
|
D0C7D4CB24F7616A001EBDBB /* RootViewModel.swift in Sources */,
|
||||||
D0C7D4BC24F7616A001EBDBB /* Tag.swift in Sources */,
|
|
||||||
D0C7D4E324F7616A001EBDBB /* PushSubscriptionEndpoint.swift in Sources */,
|
|
||||||
D0C7D4CE24F7616A001EBDBB /* PreferencesViewModel.swift in Sources */,
|
D0C7D4CE24F7616A001EBDBB /* PreferencesViewModel.swift in Sources */,
|
||||||
D0C7D4D124F7616A001EBDBB /* IdentityDatabase.swift in Sources */,
|
D0C7D4D124F7616A001EBDBB /* IdentityDatabase.swift in Sources */,
|
||||||
D0C7D4ED24F7616A001EBDBB /* MastodonAPI.swift in Sources */,
|
|
||||||
D0C7D4D624F7616A001EBDBB /* NSMutableAttributedString+Extensions.swift in Sources */,
|
D0C7D4D624F7616A001EBDBB /* NSMutableAttributedString+Extensions.swift in Sources */,
|
||||||
D05494FA24EA4E5E008B00A5 /* TimelinesEndpoint+Stubbing.swift in Sources */,
|
D05494FA24EA4E5E008B00A5 /* TimelinesEndpoint+Stubbing.swift in Sources */,
|
||||||
D0A652AD24DE3EB6002EA33F /* PreferencesEndpoint+Stubbing.swift in Sources */,
|
D0A652AD24DE3EB6002EA33F /* PreferencesEndpoint+Stubbing.swift in Sources */,
|
||||||
D0C7D4A924F7616A001EBDBB /* Mention.swift in Sources */,
|
|
||||||
D0DC175524D00F0A00A75C65 /* AccessTokenEndpoint+Stubbing.swift in Sources */,
|
D0DC175524D00F0A00A75C65 /* AccessTokenEndpoint+Stubbing.swift in Sources */,
|
||||||
D0C7D4B524F7616A001EBDBB /* Instance.swift in Sources */,
|
|
||||||
D0C7D4D324F7616A001EBDBB /* DatabaseError.swift in Sources */,
|
D0C7D4D324F7616A001EBDBB /* DatabaseError.swift in Sources */,
|
||||||
D0C7D4E224F7616A001EBDBB /* MastodonEndpoint.swift in Sources */,
|
|
||||||
D0C7D4F224F7616A001EBDBB /* TimelineService.swift in Sources */,
|
D0C7D4F224F7616A001EBDBB /* TimelineService.swift in Sources */,
|
||||||
D0C7D4BF24F7616A001EBDBB /* AppEnvironment.swift in Sources */,
|
D0C7D4BF24F7616A001EBDBB /* AppEnvironment.swift in Sources */,
|
||||||
D0C7D49D24F7616A001EBDBB /* PostingReadingPreferencesView.swift in Sources */,
|
D0C7D49D24F7616A001EBDBB /* PostingReadingPreferencesView.swift in Sources */,
|
||||||
D0C7D4D024F7616A001EBDBB /* StatusListViewModel.swift in Sources */,
|
D0C7D4D024F7616A001EBDBB /* StatusListViewModel.swift in Sources */,
|
||||||
D0C7D4AC24F7616A001EBDBB /* Poll.swift in Sources */,
|
|
||||||
D0C7D4BD24F7616A001EBDBB /* Account.swift in Sources */,
|
|
||||||
D0C7D4EB24F7616A001EBDBB /* ContextEndpoint.swift in Sources */,
|
|
||||||
D0C7D49E24F7616A001EBDBB /* SecondaryNavigationView.swift in Sources */,
|
D0C7D49E24F7616A001EBDBB /* SecondaryNavigationView.swift in Sources */,
|
||||||
D0C7D4DF24F7616A001EBDBB /* HTTPClient.swift in Sources */,
|
|
||||||
D0C7D4D424F7616A001EBDBB /* NSError+Extensions.swift in Sources */,
|
D0C7D4D424F7616A001EBDBB /* NSError+Extensions.swift in Sources */,
|
||||||
D052BBCA24D74C9200A80A7A /* MockUserDefaults.swift in Sources */,
|
D052BBCA24D74C9200A80A7A /* MockUserDefaults.swift in Sources */,
|
||||||
D0C7D4DB24F7616A001EBDBB /* Date+Extensions.swift in Sources */,
|
D0C7D4DB24F7616A001EBDBB /* Date+Extensions.swift in Sources */,
|
||||||
D0C7D4DA24F7616A001EBDBB /* View+Extensions.swift in Sources */,
|
D0C7D4DA24F7616A001EBDBB /* View+Extensions.swift in Sources */,
|
||||||
D0C7D4C824F7616A001EBDBB /* SecondaryNavigationViewModel.swift in Sources */,
|
D0C7D4C824F7616A001EBDBB /* SecondaryNavigationViewModel.swift in Sources */,
|
||||||
D0C7D4EF24F7616A001EBDBB /* MastodonClient.swift in Sources */,
|
|
||||||
D0C7D4B224F7616A001EBDBB /* HTML.swift in Sources */,
|
|
||||||
D0C7D4B324F7616A001EBDBB /* MastodonError.swift in Sources */,
|
|
||||||
D0C7D4E924F7616A001EBDBB /* AccessTokenEndpoint.swift in Sources */,
|
|
||||||
D0C7D4D524F7616A001EBDBB /* String+Extensions.swift in Sources */,
|
D0C7D4D524F7616A001EBDBB /* String+Extensions.swift in Sources */,
|
||||||
D0BEB20124FA0220001B0F04 /* ListEndpoint.swift in Sources */,
|
|
||||||
D0C7D4BA24F7616A001EBDBB /* AppAuthorization.swift in Sources */,
|
|
||||||
D0C7D4AB24F7616A001EBDBB /* Identity.swift in Sources */,
|
D0C7D4AB24F7616A001EBDBB /* Identity.swift in Sources */,
|
||||||
D0C7D4C024F7616A001EBDBB /* AlertItem.swift in Sources */,
|
D0C7D4C024F7616A001EBDBB /* AlertItem.swift in Sources */,
|
||||||
D0C7D4B424F7616A001EBDBB /* MastodonContext.swift in Sources */,
|
|
||||||
D0C7D4A224F7616A001EBDBB /* NotificationTypesPreferencesView.swift in Sources */,
|
D0C7D4A224F7616A001EBDBB /* NotificationTypesPreferencesView.swift in Sources */,
|
||||||
D0C7D4CF24F7616A001EBDBB /* StatusViewModel.swift in Sources */,
|
D0C7D4CF24F7616A001EBDBB /* StatusViewModel.swift in Sources */,
|
||||||
D0C7D4C724F7616A001EBDBB /* PostingReadingPreferencesViewModel.swift in Sources */,
|
D0C7D4C724F7616A001EBDBB /* PostingReadingPreferencesViewModel.swift in Sources */,
|
||||||
|
@ -964,46 +774,28 @@
|
||||||
D0DC174624CFEC2000A75C65 /* StubbingURLProtocol.swift in Sources */,
|
D0DC174624CFEC2000A75C65 /* StubbingURLProtocol.swift in Sources */,
|
||||||
D0BEB1FF24F9E5BB001B0F04 /* ListsView.swift in Sources */,
|
D0BEB1FF24F9E5BB001B0F04 /* ListsView.swift in Sources */,
|
||||||
D0C7D4F824F7616A001EBDBB /* SecretsService.swift in Sources */,
|
D0C7D4F824F7616A001EBDBB /* SecretsService.swift in Sources */,
|
||||||
D0C7D4DE24F7616A001EBDBB /* HTTPTarget.swift in Sources */,
|
|
||||||
D0C7D4F624F7616A001EBDBB /* KeychainService.swift in Sources */,
|
D0C7D4F624F7616A001EBDBB /* KeychainService.swift in Sources */,
|
||||||
D0C7D4C124F7616A001EBDBB /* MastodonPreferences.swift in Sources */,
|
|
||||||
D0DC174D24CFF1F100A75C65 /* Stubbing.swift in Sources */,
|
D0DC174D24CFF1F100A75C65 /* Stubbing.swift in Sources */,
|
||||||
D0C7D4E524F7616A001EBDBB /* InstanceEndpoint.swift in Sources */,
|
|
||||||
D0C7D49724F7616A001EBDBB /* IdentitiesView.swift in Sources */,
|
D0C7D49724F7616A001EBDBB /* IdentitiesView.swift in Sources */,
|
||||||
D074577724D29006004758DB /* MockWebAuthSession.swift in Sources */,
|
D074577724D29006004758DB /* MockWebAuthSession.swift in Sources */,
|
||||||
D0C7D4F924F7616A001EBDBB /* UserNotificationService.swift in Sources */,
|
D0C7D4F924F7616A001EBDBB /* UserNotificationService.swift in Sources */,
|
||||||
D0C7D49824F7616A001EBDBB /* CustomEmojiText.swift in Sources */,
|
D0C7D49824F7616A001EBDBB /* CustomEmojiText.swift in Sources */,
|
||||||
D01F41E424F8889700D55A2D /* AttachmentsView.swift in Sources */,
|
D01F41E424F8889700D55A2D /* AttachmentsView.swift in Sources */,
|
||||||
D0C7D4AA24F7616A001EBDBB /* Attachment.swift in Sources */,
|
|
||||||
D0C7D4AF24F7616A001EBDBB /* PushNotification.swift in Sources */,
|
|
||||||
D0BEB20724FA1121001B0F04 /* FiltersViewModel.swift in Sources */,
|
D0BEB20724FA1121001B0F04 /* FiltersViewModel.swift in Sources */,
|
||||||
D0C7D4C924F7616A001EBDBB /* TabNavigationViewModel.swift in Sources */,
|
D0C7D4C924F7616A001EBDBB /* TabNavigationViewModel.swift in Sources */,
|
||||||
D0BEB21124FA2A91001B0F04 /* EditFilterView.swift in Sources */,
|
D0BEB21124FA2A91001B0F04 /* EditFilterView.swift in Sources */,
|
||||||
D0C7D4B624F7616A001EBDBB /* ListTimeline.swift in Sources */,
|
|
||||||
D0C7D4E124F7616A001EBDBB /* MastodonDecoder.swift in Sources */,
|
|
||||||
D0C7D4B024F7616A001EBDBB /* PushSubscription.swift in Sources */,
|
|
||||||
D0BEB20B24FA12D8001B0F04 /* FiltersEndpoint.swift in Sources */,
|
|
||||||
D0C7D4C424F7616A001EBDBB /* AppDelegate.swift in Sources */,
|
D0C7D4C424F7616A001EBDBB /* AppDelegate.swift in Sources */,
|
||||||
D074577A24D29366004758DB /* URLSessionConfiguration+Extensions.swift in Sources */,
|
D074577A24D29366004758DB /* URLSessionConfiguration+Extensions.swift in Sources */,
|
||||||
D0C7D4E424F7616A001EBDBB /* PreferencesEndpoint.swift in Sources */,
|
|
||||||
D0C7D49924F7616A001EBDBB /* AddIdentityView.swift in Sources */,
|
D0C7D49924F7616A001EBDBB /* AddIdentityView.swift in Sources */,
|
||||||
D0BEB1FD24F9E4E5001B0F04 /* ListsViewModel.swift in Sources */,
|
D0BEB1FD24F9E4E5001B0F04 /* ListsViewModel.swift in Sources */,
|
||||||
D0C7D4C324F7616A001EBDBB /* MetatextApp.swift in Sources */,
|
D0C7D4C324F7616A001EBDBB /* MetatextApp.swift in Sources */,
|
||||||
D0C7D4B124F7616A001EBDBB /* Card.swift in Sources */,
|
|
||||||
D0C7D4F324F7616A001EBDBB /* ContextService.swift in Sources */,
|
D0C7D4F324F7616A001EBDBB /* ContextService.swift in Sources */,
|
||||||
D0C7D4DD24F7616A001EBDBB /* CodingUserInfoKey+Extensions.swift in Sources */,
|
|
||||||
D0C7D4D824F7616A001EBDBB /* Publisher+Extensions.swift in Sources */,
|
D0C7D4D824F7616A001EBDBB /* Publisher+Extensions.swift in Sources */,
|
||||||
D0BEB20524FA1107001B0F04 /* FiltersView.swift in Sources */,
|
D0BEB20524FA1107001B0F04 /* FiltersView.swift in Sources */,
|
||||||
D01F41D824F880C400D55A2D /* StatusTableViewCell.swift in Sources */,
|
D01F41D824F880C400D55A2D /* StatusTableViewCell.swift in Sources */,
|
||||||
D04FD73C24D4A83A007D572D /* InstanceEndpoint+Stubbing.swift in Sources */,
|
D04FD73C24D4A83A007D572D /* InstanceEndpoint+Stubbing.swift in Sources */,
|
||||||
D0C7D4BE24F7616A001EBDBB /* Unknowable.swift in Sources */,
|
|
||||||
D0C7D4AE24F7616A001EBDBB /* Timeline.swift in Sources */,
|
|
||||||
D0C7D49B24F7616A001EBDBB /* PreferencesView.swift in Sources */,
|
D0C7D49B24F7616A001EBDBB /* PreferencesView.swift in Sources */,
|
||||||
D0C7D4EC24F7616A001EBDBB /* StatusEndpoint.swift in Sources */,
|
|
||||||
D0C7D4D724F7616A001EBDBB /* UIColor+Extensions.swift in Sources */,
|
D0C7D4D724F7616A001EBDBB /* UIColor+Extensions.swift in Sources */,
|
||||||
D0C7D4BB24F7616A001EBDBB /* Emoji.swift in Sources */,
|
|
||||||
D0BEB1F924F9D627001B0F04 /* ListsEndpoint.swift in Sources */,
|
|
||||||
D0C7D4AD24F7616A001EBDBB /* AccessToken.swift in Sources */,
|
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
@ -1021,12 +813,8 @@
|
||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
D0C7D4FC24F761A8001EBDBB /* Unknowable.swift in Sources */,
|
|
||||||
D0C7D4FB24F7619F001EBDBB /* PushNotification.swift in Sources */,
|
|
||||||
D0C7D4FE24F761C9001EBDBB /* SecretsService.swift in Sources */,
|
D0C7D4FE24F761C9001EBDBB /* SecretsService.swift in Sources */,
|
||||||
D0C7D50124F761EC001EBDBB /* MastodonAPI.swift in Sources */,
|
|
||||||
D0E5361C24E3EB4D00FB1CE1 /* NotificationService.swift in Sources */,
|
D0E5361C24E3EB4D00FB1CE1 /* NotificationService.swift in Sources */,
|
||||||
D0C7D4FD24F761C1001EBDBB /* MastodonDecoder.swift in Sources */,
|
|
||||||
D0C7D50024F761E0001EBDBB /* NSError+Extensions.swift in Sources */,
|
D0C7D50024F761E0001EBDBB /* NSError+Extensions.swift in Sources */,
|
||||||
D0C7D4FF24F761D0001EBDBB /* KeychainService.swift in Sources */,
|
D0C7D4FF24F761D0001EBDBB /* KeychainService.swift in Sources */,
|
||||||
);
|
);
|
||||||
|
@ -1404,6 +1192,14 @@
|
||||||
package = D0DC175D24D016EA00A75C65 /* XCRemoteSwiftPackageReference "Alamofire" */;
|
package = D0DC175D24D016EA00A75C65 /* XCRemoteSwiftPackageReference "Alamofire" */;
|
||||||
productName = Alamofire;
|
productName = Alamofire;
|
||||||
};
|
};
|
||||||
|
D0E0F1E524FC4B76002C04BF /* Mastodon */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
productName = Mastodon;
|
||||||
|
};
|
||||||
|
D0E0F1E724FC5A61002C04BF /* Mastodon */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
productName = Mastodon;
|
||||||
|
};
|
||||||
/* End XCSwiftPackageProductDependency section */
|
/* End XCSwiftPackageProductDependency section */
|
||||||
};
|
};
|
||||||
rootObject = D047FA8024C3E21000AF17C5 /* Project object */;
|
rootObject = D047FA8024C3E21000AF17C5 /* Project object */;
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
// Copyright © 2020 Metabolist. All rights reserved.
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
struct AccessToken: Codable {
|
|
||||||
let scope: String
|
|
||||||
let tokenType: String
|
|
||||||
let accessToken: String
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
// Copyright © 2020 Metabolist. All rights reserved.
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
struct Account: Codable, Hashable {
|
|
||||||
struct Field: Codable, Hashable {
|
|
||||||
let name: String
|
|
||||||
let value: HTML
|
|
||||||
let verifiedAt: Date?
|
|
||||||
}
|
|
||||||
|
|
||||||
let id: String
|
|
||||||
let username: String
|
|
||||||
let acct: String
|
|
||||||
let displayName: String
|
|
||||||
let locked: Bool
|
|
||||||
let createdAt: Date
|
|
||||||
let followersCount: Int
|
|
||||||
let followingCount: Int
|
|
||||||
let statusesCount: Int
|
|
||||||
let note: HTML
|
|
||||||
let url: URL
|
|
||||||
let avatar: URL
|
|
||||||
let avatarStatic: URL
|
|
||||||
let header: URL
|
|
||||||
let headerStatic: URL
|
|
||||||
let fields: [Field]
|
|
||||||
let emojis: [Emoji]
|
|
||||||
@DecodableDefault.False private(set) var bot: Bool
|
|
||||||
@DecodableDefault.False private(set) var moved: Bool
|
|
||||||
@DecodableDefault.False private(set) var discoverable: Bool
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
// Copyright © 2020 Metabolist. All rights reserved.
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
struct AppAuthorization: Codable {
|
|
||||||
let id: String
|
|
||||||
let clientId: String
|
|
||||||
let clientSecret: String
|
|
||||||
let name: String
|
|
||||||
let redirectUri: String
|
|
||||||
let website: String?
|
|
||||||
let vapidKey: String?
|
|
||||||
}
|
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright © 2020 Metabolist. All rights reserved.
|
// Copyright © 2020 Metabolist. All rights reserved.
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
import Mastodon
|
||||||
|
|
||||||
struct AppEnvironment {
|
struct AppEnvironment {
|
||||||
let session: Session
|
let session: Session
|
||||||
|
@ -8,7 +9,6 @@ struct AppEnvironment {
|
||||||
let keychainServiceType: KeychainService.Type
|
let keychainServiceType: KeychainService.Type
|
||||||
let userDefaults: UserDefaults
|
let userDefaults: UserDefaults
|
||||||
let inMemoryContent: Bool
|
let inMemoryContent: Bool
|
||||||
let attributedStringCache = AttributedStringCache()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extension AppEnvironment {
|
extension AppEnvironment {
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
// Copyright © 2020 Metabolist. All rights reserved.
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
struct Application: Codable, Hashable {
|
|
||||||
let name: String
|
|
||||||
let website: String?
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
// Copyright © 2020 Metabolist. All rights reserved.
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
struct Attachment: Codable, Hashable {
|
|
||||||
enum AttachmentType: String, Codable, Hashable, Unknowable {
|
|
||||||
case image, video, gifv, audio, unknown
|
|
||||||
|
|
||||||
static var unknownCase: Self { .unknown }
|
|
||||||
}
|
|
||||||
|
|
||||||
// swiftlint:disable nesting
|
|
||||||
struct Meta: Codable, Hashable {
|
|
||||||
struct Info: Codable, Hashable {
|
|
||||||
let width: Int?
|
|
||||||
let height: Int?
|
|
||||||
let size: String?
|
|
||||||
let aspect: Double?
|
|
||||||
let frameRate: String?
|
|
||||||
let duration: Double?
|
|
||||||
let bitrate: Int?
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Focus: Codable, Hashable {
|
|
||||||
let x: Double
|
|
||||||
let y: Double
|
|
||||||
}
|
|
||||||
|
|
||||||
let original: Info?
|
|
||||||
let small: Info?
|
|
||||||
let focus: Focus?
|
|
||||||
}
|
|
||||||
// swiftlint:enable nesting
|
|
||||||
|
|
||||||
let id: String
|
|
||||||
let type: AttachmentType
|
|
||||||
let url: URL
|
|
||||||
let remoteUrl: URL?
|
|
||||||
let previewUrl: URL
|
|
||||||
let textUrl: URL?
|
|
||||||
let meta: Meta?
|
|
||||||
let description: String?
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
// Copyright © 2020 Metabolist. All rights reserved.
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
struct Card: Codable, Hashable {
|
|
||||||
enum CardType: String, Codable, Hashable, Unknowable {
|
|
||||||
case link, photo, video, rich, unknown
|
|
||||||
|
|
||||||
static var unknownCase: Self { .unknown }
|
|
||||||
}
|
|
||||||
|
|
||||||
let url: URL
|
|
||||||
let title: String
|
|
||||||
let description: String
|
|
||||||
let type: CardType
|
|
||||||
let authorName: String?
|
|
||||||
let authorUrl: String?
|
|
||||||
let providerName: String?
|
|
||||||
let providerUrl: String?
|
|
||||||
let html: String?
|
|
||||||
let width: Int?
|
|
||||||
let height: Int?
|
|
||||||
let image: URL?
|
|
||||||
let embedUrl: String?
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
// Copyright © 2020 Metabolist. All rights reserved.
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
struct Emoji: Codable, Hashable {
|
|
||||||
let shortcode: String
|
|
||||||
let staticUrl: URL
|
|
||||||
let url: URL
|
|
||||||
let visibleInPicker: Bool
|
|
||||||
}
|
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright © 2020 Metabolist. All rights reserved.
|
// Copyright © 2020 Metabolist. All rights reserved.
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
import Mastodon
|
||||||
|
|
||||||
struct Identity: Codable, Hashable, Identifiable {
|
struct Identity: Codable, Hashable, Identifiable {
|
||||||
let id: UUID
|
let id: UUID
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
// Copyright © 2020 Metabolist. All rights reserved.
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
struct Instance: Codable, Hashable {
|
|
||||||
struct URLs: Codable, Hashable {
|
|
||||||
let streamingApi: URL
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Stats: Codable, Hashable {
|
|
||||||
let userCount: Int
|
|
||||||
let statusCount: Int
|
|
||||||
let domainCount: Int
|
|
||||||
}
|
|
||||||
|
|
||||||
let uri: String
|
|
||||||
let title: String
|
|
||||||
let description: String
|
|
||||||
let shortDescription: String?
|
|
||||||
let email: String
|
|
||||||
let version: String
|
|
||||||
@DecodableDefault.EmptyList private(set) var languages: [String]
|
|
||||||
@DecodableDefault.False private(set) var registrations: Bool
|
|
||||||
@DecodableDefault.False private(set) var approvalRequired: Bool
|
|
||||||
@DecodableDefault.False private(set) var invitesEnabled: Bool
|
|
||||||
let urls: URLs
|
|
||||||
let stats: Stats
|
|
||||||
let thumbnail: URL?
|
|
||||||
let contactAccount: Account?
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
// Copyright © 2020 Metabolist. All rights reserved.
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
struct MastodonList: Codable, Hashable, Identifiable {
|
|
||||||
let id: String
|
|
||||||
let title: String
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
// Copyright © 2020 Metabolist. All rights reserved.
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
struct MastodonContext: Codable, Hashable {
|
|
||||||
let ancestors: [Status]
|
|
||||||
let descendants: [Status]
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
// Copyright © 2020 Metabolist. All rights reserved.
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
struct MastodonError: Error, Codable {
|
|
||||||
let error: String
|
|
||||||
}
|
|
||||||
|
|
||||||
extension MastodonError: LocalizedError {
|
|
||||||
var errorDescription: String? { error }
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
// Copyright © 2020 Metabolist. All rights reserved.
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
struct Mention: Codable, Hashable {
|
|
||||||
let url: URL
|
|
||||||
let username: String
|
|
||||||
let acct: String
|
|
||||||
let id: String
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
// Copyright © 2020 Metabolist. All rights reserved.
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
struct Poll: Codable, Hashable {
|
|
||||||
struct Option: Codable, Hashable {
|
|
||||||
var title: String
|
|
||||||
var votesCount: Int
|
|
||||||
}
|
|
||||||
|
|
||||||
let id: String
|
|
||||||
let expiresAt: Date
|
|
||||||
let expired: Bool
|
|
||||||
let multiple: Bool
|
|
||||||
let votesCount: Int
|
|
||||||
let votersCount: Int?
|
|
||||||
@DecodableDefault.False private(set) var voted: Bool
|
|
||||||
@DecodableDefault.EmptyList private(set) var ownVotes: [Int]
|
|
||||||
let options: [Option]
|
|
||||||
let emojis: [Emoji]
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
// Copyright © 2020 Metabolist. All rights reserved.
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
struct PushNotification: Codable {
|
|
||||||
enum NotificationType: String, Codable, Unknowable {
|
|
||||||
case mention
|
|
||||||
case reblog
|
|
||||||
case favourite
|
|
||||||
case follow
|
|
||||||
case unknown
|
|
||||||
|
|
||||||
static var unknownCase: Self { .unknown }
|
|
||||||
}
|
|
||||||
|
|
||||||
let accessToken: String
|
|
||||||
let body: String
|
|
||||||
let title: String
|
|
||||||
let icon: URL
|
|
||||||
let notificationId: Int
|
|
||||||
let notificationType: NotificationType
|
|
||||||
let preferredLocale: String
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
// Copyright © 2020 Metabolist. All rights reserved.
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
struct PushSubscription: Codable {
|
|
||||||
struct Alerts: Codable, Hashable {
|
|
||||||
var follow: Bool
|
|
||||||
var favourite: Bool
|
|
||||||
var reblog: Bool
|
|
||||||
var mention: Bool
|
|
||||||
@DecodableDefault.True var poll: Bool
|
|
||||||
}
|
|
||||||
|
|
||||||
let endpoint: URL
|
|
||||||
let alerts: Alerts
|
|
||||||
let serverKey: String
|
|
||||||
}
|
|
||||||
|
|
||||||
extension PushSubscription.Alerts {
|
|
||||||
static let initial: Self = Self(
|
|
||||||
follow: true,
|
|
||||||
favourite: true,
|
|
||||||
reblog: true,
|
|
||||||
mention: true,
|
|
||||||
poll: DecodableDefault.True())
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
// Copyright © 2020 Metabolist. All rights reserved.
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
struct Tag: Codable, Hashable {
|
|
||||||
let name: String
|
|
||||||
let url: URL
|
|
||||||
}
|
|
|
@ -1,46 +0,0 @@
|
||||||
// Copyright © 2020 Metabolist. All rights reserved.
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
struct Paged<T: MastodonEndpoint> {
|
|
||||||
let endpoint: T
|
|
||||||
let maxID: String?
|
|
||||||
let minID: String?
|
|
||||||
let sinceID: String?
|
|
||||||
let limit: Int?
|
|
||||||
|
|
||||||
init(_ endpoint: T, maxID: String? = nil, minID: String? = nil, sinceID: String? = nil, limit: Int? = nil) {
|
|
||||||
self.endpoint = endpoint
|
|
||||||
self.maxID = maxID
|
|
||||||
self.minID = minID
|
|
||||||
self.sinceID = sinceID
|
|
||||||
self.limit = limit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension Paged: MastodonEndpoint {
|
|
||||||
typealias ResultType = T.ResultType
|
|
||||||
|
|
||||||
var APIVersion: String { endpoint.APIVersion }
|
|
||||||
|
|
||||||
var context: [String] { endpoint.context }
|
|
||||||
|
|
||||||
var pathComponentsInContext: [String] { endpoint.pathComponentsInContext }
|
|
||||||
|
|
||||||
var method: HTTPMethod { endpoint.method }
|
|
||||||
|
|
||||||
var encoding: ParameterEncoding { endpoint.encoding }
|
|
||||||
|
|
||||||
var parameters: [String: Any]? {
|
|
||||||
var parameters = endpoint.parameters ?? [String: Any]()
|
|
||||||
|
|
||||||
parameters["max_id"] = maxID
|
|
||||||
parameters["min_id"] = minID
|
|
||||||
parameters["since_id"] = sinceID
|
|
||||||
parameters["limit"] = limit
|
|
||||||
|
|
||||||
return parameters
|
|
||||||
}
|
|
||||||
|
|
||||||
var headers: HTTPHeaders? { endpoint.headers }
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
// Copyright © 2020 Metabolist. All rights reserved.
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
struct MastodonAPI {
|
|
||||||
static let dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
// Copyright © 2020 Metabolist. All rights reserved.
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
import Combine
|
|
||||||
|
|
||||||
class MastodonClient: HTTPClient {
|
|
||||||
var instanceURL: URL?
|
|
||||||
var accessToken: String?
|
|
||||||
|
|
||||||
required init(environment: AppEnvironment) {
|
|
||||||
let decoder = MastodonDecoder()
|
|
||||||
|
|
||||||
decoder.userInfo[.attributedStringCache] = environment.attributedStringCache
|
|
||||||
|
|
||||||
super.init(session: environment.session, decoder: decoder)
|
|
||||||
}
|
|
||||||
|
|
||||||
override func request<T: DecodableTarget>(_ target: T) -> AnyPublisher<T.ResultType, Error> {
|
|
||||||
super.request(target, decodeErrorsAs: MastodonError.self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension MastodonClient {
|
|
||||||
func request<E: MastodonEndpoint>(_ endpoint: E) -> AnyPublisher<E.ResultType, Error> {
|
|
||||||
guard let instanceURL = instanceURL else {
|
|
||||||
return Fail(error: URLError(.badURL)).eraseToAnyPublisher()
|
|
||||||
}
|
|
||||||
|
|
||||||
return super.request(
|
|
||||||
MastodonTarget(baseURL: instanceURL, endpoint: endpoint, accessToken: accessToken),
|
|
||||||
decodeErrorsAs: MastodonError.self)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,35 +0,0 @@
|
||||||
// Copyright © 2020 Metabolist. All rights reserved.
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
struct MastodonTarget<E: MastodonEndpoint> {
|
|
||||||
let baseURL: URL
|
|
||||||
let endpoint: E
|
|
||||||
let accessToken: String?
|
|
||||||
}
|
|
||||||
|
|
||||||
extension MastodonTarget: DecodableTarget {
|
|
||||||
typealias ResultType = E.ResultType
|
|
||||||
|
|
||||||
var pathComponents: [String] { endpoint.pathComponents }
|
|
||||||
|
|
||||||
var method: HTTPMethod { endpoint.method }
|
|
||||||
|
|
||||||
var encoding: ParameterEncoding { endpoint.encoding }
|
|
||||||
|
|
||||||
var parameters: [String: Any]? { endpoint.parameters }
|
|
||||||
|
|
||||||
var headers: HTTPHeaders? {
|
|
||||||
var headers = endpoint.headers
|
|
||||||
|
|
||||||
if let accessToken = accessToken {
|
|
||||||
if headers == nil {
|
|
||||||
headers = HTTPHeaders()
|
|
||||||
}
|
|
||||||
|
|
||||||
headers?.add(.authorization(bearerToken: accessToken))
|
|
||||||
}
|
|
||||||
|
|
||||||
return headers
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
import UserNotifications
|
import UserNotifications
|
||||||
import CryptoKit
|
import CryptoKit
|
||||||
|
import Mastodon
|
||||||
|
|
||||||
class NotificationService: UNNotificationServiceExtension {
|
class NotificationService: UNNotificationServiceExtension {
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
import Combine
|
import Combine
|
||||||
|
import Mastodon
|
||||||
|
|
||||||
struct AllIdentitiesService {
|
struct AllIdentitiesService {
|
||||||
let mostRecentlyUsedIdentityID: AnyPublisher<UUID?, Never>
|
let mostRecentlyUsedIdentityID: AnyPublisher<UUID?, Never>
|
||||||
|
@ -49,7 +50,7 @@ extension AllIdentitiesService {
|
||||||
|
|
||||||
func deleteIdentity(_ identity: Identity) -> AnyPublisher<Never, Error> {
|
func deleteIdentity(_ identity: Identity) -> AnyPublisher<Never, Error> {
|
||||||
let secretsService = SecretsService(identityID: identity.id, keychainService: environment.keychainServiceType)
|
let secretsService = SecretsService(identityID: identity.id, keychainService: environment.keychainServiceType)
|
||||||
let networkClient = MastodonClient(environment: environment)
|
let networkClient = MastodonClient(session: environment.session)
|
||||||
|
|
||||||
networkClient.instanceURL = identity.url
|
networkClient.instanceURL = identity.url
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
import Combine
|
import Combine
|
||||||
|
import Mastodon
|
||||||
|
|
||||||
struct AuthenticationService {
|
struct AuthenticationService {
|
||||||
private let networkClient: MastodonClient
|
private let networkClient: MastodonClient
|
||||||
|
@ -9,7 +10,7 @@ struct AuthenticationService {
|
||||||
private let webAuthSessionContextProvider = WebAuthSessionContextProvider()
|
private let webAuthSessionContextProvider = WebAuthSessionContextProvider()
|
||||||
|
|
||||||
init(environment: AppEnvironment) {
|
init(environment: AppEnvironment) {
|
||||||
networkClient = MastodonClient(environment: environment)
|
networkClient = MastodonClient(session: environment.session)
|
||||||
webAuthSessionType = environment.webAuthSessionType
|
webAuthSessionType = environment.webAuthSessionType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
import Combine
|
import Combine
|
||||||
|
import Mastodon
|
||||||
|
|
||||||
class IdentityService {
|
class IdentityService {
|
||||||
@Published private(set) var identity: Identity
|
@Published private(set) var identity: Identity
|
||||||
|
@ -34,11 +35,11 @@ class IdentityService {
|
||||||
secretsService = SecretsService(
|
secretsService = SecretsService(
|
||||||
identityID: identityID,
|
identityID: identityID,
|
||||||
keychainService: environment.keychainServiceType)
|
keychainService: environment.keychainServiceType)
|
||||||
networkClient = MastodonClient(environment: environment)
|
networkClient = MastodonClient(session: environment.session)
|
||||||
networkClient.instanceURL = identity.url
|
networkClient.instanceURL = identity.url
|
||||||
networkClient.accessToken = try? secretsService.item(.accessToken)
|
networkClient.accessToken = try? secretsService.item(.accessToken)
|
||||||
|
|
||||||
contentDatabase = try ContentDatabase(identityID: identityID, environment: environment)
|
contentDatabase = try ContentDatabase(identityID: identityID, inMemory: environment.inMemoryContent)
|
||||||
|
|
||||||
observation.catch { [weak self] error -> Empty<Identity, Never> in
|
observation.catch { [weak self] error -> Empty<Identity, Never> in
|
||||||
self?.observationErrorsInput.send(error)
|
self?.observationErrorsInput.send(error)
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
import Combine
|
import Combine
|
||||||
|
import Mastodon
|
||||||
|
|
||||||
struct ContextService {
|
struct ContextService {
|
||||||
let statusSections: AnyPublisher<[[Status]], Error>
|
let statusSections: AnyPublisher<[[Status]], Error>
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
import Combine
|
import Combine
|
||||||
|
import Mastodon
|
||||||
|
|
||||||
protocol StatusListService {
|
protocol StatusListService {
|
||||||
var statusSections: AnyPublisher<[[Status]], Error> { get }
|
var statusSections: AnyPublisher<[[Status]], Error> { get }
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
import Combine
|
import Combine
|
||||||
|
import Mastodon
|
||||||
|
|
||||||
struct TimelineService {
|
struct TimelineService {
|
||||||
let statusSections: AnyPublisher<[[Status]], Error>
|
let statusSections: AnyPublisher<[[Status]], Error>
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
import Combine
|
import Combine
|
||||||
|
import Mastodon
|
||||||
|
|
||||||
struct StatusService {
|
struct StatusService {
|
||||||
let status: Status
|
let status: Status
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright © 2020 Metabolist. All rights reserved.
|
// Copyright © 2020 Metabolist. All rights reserved.
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
import Mastodon
|
||||||
|
|
||||||
struct AttachmentViewModel {
|
struct AttachmentViewModel {
|
||||||
let attachment: Attachment
|
let attachment: Attachment
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
import Combine
|
import Combine
|
||||||
|
import Mastodon
|
||||||
|
|
||||||
class EditFilterViewModel: ObservableObject {
|
class EditFilterViewModel: ObservableObject {
|
||||||
@Published var filter: Filter
|
@Published var filter: Filter
|
||||||
|
@ -56,3 +57,22 @@ extension EditFilterViewModel {
|
||||||
.store(in: &cancellables)
|
.store(in: &cancellables)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension Filter.Context {
|
||||||
|
var localized: String {
|
||||||
|
switch self {
|
||||||
|
case .home:
|
||||||
|
return NSLocalizedString("filter.context.home", comment: "")
|
||||||
|
case .notifications:
|
||||||
|
return NSLocalizedString("filter.context.notifications", comment: "")
|
||||||
|
case .public:
|
||||||
|
return NSLocalizedString("filter.context.public", comment: "")
|
||||||
|
case .thread:
|
||||||
|
return NSLocalizedString("filter.context.thread", comment: "")
|
||||||
|
case .account:
|
||||||
|
return NSLocalizedString("filter.context.account", comment: "")
|
||||||
|
case .unknown:
|
||||||
|
return NSLocalizedString("filter.context.unknown", comment: "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue