mirror of
https://github.com/metabolist/metatext.git
synced 2024-11-25 09:41: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 Combine
|
||||
import GRDB
|
||||
import Mastodon
|
||||
|
||||
// swiftlint:disable file_length
|
||||
struct ContentDatabase {
|
||||
private let databaseQueue: DatabaseQueue
|
||||
|
||||
init(identityID: UUID, environment: AppEnvironment) throws {
|
||||
init(identityID: UUID, inMemory: Bool) throws {
|
||||
guard
|
||||
let documentsDirectory = NSSearchPathForDirectoriesInDomains(
|
||||
.documentDirectory,
|
||||
|
@ -16,7 +17,7 @@ struct ContentDatabase {
|
|||
.first
|
||||
else { throw DatabaseError.documentsDirectoryNotFound }
|
||||
|
||||
if environment.inMemoryContent {
|
||||
if inMemory {
|
||||
databaseQueue = DatabaseQueue()
|
||||
} else {
|
||||
databaseQueue = try DatabaseQueue(path: "\(documentsDirectory)/\(identityID.uuidString).sqlite3")
|
||||
|
@ -24,7 +25,6 @@ struct ContentDatabase {
|
|||
|
||||
try Self.migrate(databaseQueue)
|
||||
try Self.createTemporaryTables(databaseQueue)
|
||||
Self.attributedStringCache = environment.attributedStringCache
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,8 +131,6 @@ extension ContentDatabase {
|
|||
}
|
||||
|
||||
private extension ContentDatabase {
|
||||
static var attributedStringCache: AttributedStringCache?
|
||||
|
||||
// swiftlint:disable function_body_length
|
||||
static func migrate(_ writer: DatabaseWriter) throws {
|
||||
var migrator = DatabaseMigrator()
|
||||
|
@ -244,21 +242,11 @@ private extension ContentDatabase {
|
|||
}
|
||||
|
||||
extension Account: 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 {
|
||||
public static func databaseJSONDecoder(for column: String) -> JSONDecoder {
|
||||
MastodonDecoder()
|
||||
}
|
||||
|
||||
static func databaseJSONEncoder(for column: String) -> JSONEncoder {
|
||||
public static func databaseJSONEncoder(for column: String) -> JSONEncoder {
|
||||
MastodonEncoder()
|
||||
}
|
||||
}
|
||||
|
@ -282,7 +270,7 @@ extension Timeline: StatusCollection {
|
|||
case id, listTitle
|
||||
}
|
||||
|
||||
init(row: Row) {
|
||||
public init(row: Row) {
|
||||
switch (row[Columns.id] as String, row[Columns.listTitle] as String?) {
|
||||
case (Timeline.home.id, _):
|
||||
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
|
||||
|
||||
if case let .list(list) = self {
|
||||
|
@ -336,11 +324,11 @@ private extension Timeline {
|
|||
}
|
||||
|
||||
extension Filter: TableRecord, FetchableRecord, PersistableRecord {
|
||||
static func databaseJSONDecoder(for column: String) -> JSONDecoder {
|
||||
public static func databaseJSONDecoder(for column: String) -> JSONDecoder {
|
||||
MastodonDecoder()
|
||||
}
|
||||
|
||||
static func databaseJSONEncoder(for column: String) -> JSONEncoder {
|
||||
public static func databaseJSONEncoder(for column: String) -> JSONEncoder {
|
||||
MastodonEncoder()
|
||||
}
|
||||
}
|
||||
|
@ -464,16 +452,6 @@ private extension StoredStatus {
|
|||
}
|
||||
|
||||
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 {
|
||||
MastodonDecoder()
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
import Foundation
|
||||
import Combine
|
||||
import GRDB
|
||||
import Mastodon
|
||||
|
||||
enum IdentityDatabaseError: Error {
|
||||
case identityNotFound
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import Foundation
|
||||
import Combine
|
||||
import Mastodon
|
||||
|
||||
// swiftlint:disable force_try
|
||||
private let decoder = MastodonDecoder()
|
||||
|
@ -119,7 +120,7 @@ extension FiltersViewModel {
|
|||
}
|
||||
|
||||
extension EditFilterViewModel {
|
||||
static let development = EditFilterViewModel(filter: .new, identityService: .development)
|
||||
static let development = EditFilterViewModel(filter: Filter.new, identityService: .development)
|
||||
}
|
||||
|
||||
extension StatusListViewModel {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright © 2020 Metabolist. All rights reserved.
|
||||
|
||||
import Foundation
|
||||
import Mastodon
|
||||
|
||||
struct HTTPStubs {
|
||||
static func stub(
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright © 2020 Metabolist. All rights reserved.
|
||||
|
||||
import Foundation
|
||||
import Mastodon
|
||||
|
||||
extension AccessTokenEndpoint: Stubbing {
|
||||
func dataString(url: URL) -> String? {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright © 2020 Metabolist. All rights reserved.
|
||||
|
||||
import Foundation
|
||||
import Mastodon
|
||||
|
||||
// swiftlint:disable line_length
|
||||
let officialAccountJSON = #"""
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright © 2020 Metabolist. All rights reserved.
|
||||
|
||||
import Foundation
|
||||
import Mastodon
|
||||
|
||||
extension AppAuthorizationEndpoint: Stubbing {
|
||||
func dataString(url: URL) -> String? {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright © 2020 Metabolist. All rights reserved.
|
||||
|
||||
import Foundation
|
||||
import Mastodon
|
||||
|
||||
extension ContextEndpoint: Stubbing {
|
||||
func dataString(url: URL) -> String? {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright © 2020 Metabolist. All rights reserved.
|
||||
|
||||
import Foundation
|
||||
import Mastodon
|
||||
|
||||
// swiftlint:disable line_length
|
||||
let officialInstanceJSON = #"""
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright © 2020 Metabolist. All rights reserved.
|
||||
|
||||
import Foundation
|
||||
import Mastodon
|
||||
|
||||
extension MastodonTarget: Stubbing {
|
||||
func stub(url: URL) -> HTTPStub? {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright © 2020 Metabolist. All rights reserved.
|
||||
|
||||
import Foundation
|
||||
import Mastodon
|
||||
|
||||
extension PreferencesEndpoint: Stubbing {
|
||||
func dataString(url: URL) -> String? {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import Foundation
|
||||
import UIKit
|
||||
import Mastodon
|
||||
|
||||
extension TimelinesEndpoint: Stubbing {
|
||||
func data(url: URL) -> Data? {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright © 2020 Metabolist. All rights reserved.
|
||||
|
||||
import Foundation
|
||||
import Mastodon
|
||||
|
||||
class StubbingURLProtocol: URLProtocol {
|
||||
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 Kingfisher
|
||||
import Mastodon
|
||||
|
||||
extension NSMutableAttributedString {
|
||||
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
|
||||
|
||||
struct Filter: Codable, Hashable, Identifiable {
|
||||
enum Context: String, Codable, Unknowable {
|
||||
public struct Filter: Codable, Hashable, Identifiable {
|
||||
public enum Context: String, Codable, Unknowable {
|
||||
case home
|
||||
case notifications
|
||||
case `public`
|
||||
|
@ -11,18 +11,18 @@ struct Filter: Codable, Hashable, Identifiable {
|
|||
case account
|
||||
case unknown
|
||||
|
||||
static var unknownCase: Self { .unknown }
|
||||
public static var unknownCase: Self { .unknown }
|
||||
}
|
||||
|
||||
let id: String
|
||||
var phrase: String
|
||||
var context: [Context]
|
||||
var expiresAt: Date?
|
||||
var irreversible: Bool
|
||||
var wholeWord: Bool
|
||||
public let id: String
|
||||
public var phrase: String
|
||||
public var context: [Context]
|
||||
public var expiresAt: Date?
|
||||
public var irreversible: Bool
|
||||
public var wholeWord: Bool
|
||||
}
|
||||
|
||||
extension Filter {
|
||||
public extension Filter {
|
||||
static let newFilterID: String = "com.metabolist.metatext.new-filter-id"
|
||||
static let new = Self(id: newFilterID,
|
||||
phrase: "",
|
||||
|
@ -36,7 +36,7 @@ extension Array where Element == Filter {
|
|||
// swiftlint:disable line_length
|
||||
// Adapted from https://github.com/tootsuite/mastodon/blob/bf477cee9f31036ebf3d164ddec1cebef5375513/app/javascript/mastodon/selectors/index.js#L43
|
||||
// swiftlint:enable line_length
|
||||
func regularExpression() -> String? {
|
||||
public func regularExpression() -> String? {
|
||||
guard !isEmpty else { return nil }
|
||||
|
||||
return map {
|
||||
|
@ -59,24 +59,5 @@ extension Array where Element == Filter {
|
|||
}
|
||||
|
||||
extension Filter.Context: Identifiable {
|
||||
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: "")
|
||||
}
|
||||
}
|
||||
public var id: Self { self }
|
||||
}
|
|
@ -1,30 +1,26 @@
|
|||
// Copyright © 2020 Metabolist. All rights reserved.
|
||||
|
||||
import Foundation
|
||||
#if !os(macOS)
|
||||
import UIKit
|
||||
#else
|
||||
import AppKit
|
||||
#endif
|
||||
|
||||
struct HTML: Hashable {
|
||||
let raw: String
|
||||
let attributed: NSAttributedString
|
||||
public struct HTML: Hashable {
|
||||
public let raw: String
|
||||
public let attributed: NSAttributedString
|
||||
}
|
||||
|
||||
extension HTML: Codable {
|
||||
init(from decoder: Decoder) throws {
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.singleValueContainer()
|
||||
let attributedStringCache = decoder.userInfo[.attributedStringCache] as? AttributedStringCache
|
||||
|
||||
raw = try container.decode(String.self)
|
||||
|
||||
if let attributed = attributedStringCache?.object(forKey: raw as NSString) {
|
||||
self.attributed = attributed
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
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()
|
||||
|
||||
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
|
||||
|
||||
struct MastodonPreferences: Codable {
|
||||
public struct MastodonPreferences: Codable {
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case postingDefaultVisibility = "posting:default:visibility"
|
||||
case postingDefaultSensitive = "posting:default:sensitive"
|
||||
|
@ -11,20 +11,20 @@ struct MastodonPreferences: Codable {
|
|||
case readingExpandSpoilers = "reading:expand:spoilers"
|
||||
}
|
||||
|
||||
let postingDefaultVisibility: Status.Visibility
|
||||
let postingDefaultSensitive: Bool
|
||||
let postingDefaultLanguage: String?
|
||||
let readingExpandMedia: ExpandMedia
|
||||
let readingExpandSpoilers: Bool
|
||||
public let postingDefaultVisibility: Status.Visibility
|
||||
public let postingDefaultSensitive: Bool
|
||||
public let postingDefaultLanguage: String?
|
||||
public let readingExpandMedia: ExpandMedia
|
||||
public let readingExpandSpoilers: Bool
|
||||
}
|
||||
|
||||
extension MastodonPreferences {
|
||||
public extension MastodonPreferences {
|
||||
enum ExpandMedia: String, Codable, Unknowable {
|
||||
case `default`
|
||||
case showAll
|
||||
case hideAll
|
||||
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
|
||||
|
||||
class Status: Codable, Identifiable {
|
||||
enum Visibility: String, Codable, Unknowable {
|
||||
public class Status: Codable, Identifiable {
|
||||
public enum Visibility: String, Codable, Unknowable {
|
||||
case `public`
|
||||
case unlisted
|
||||
case `private`
|
||||
case direct
|
||||
case unknown
|
||||
|
||||
static var unknownCase: Self { .unknown }
|
||||
public static var unknownCase: Self { .unknown }
|
||||
}
|
||||
|
||||
let id: String
|
||||
let uri: String
|
||||
let createdAt: Date
|
||||
let account: Account
|
||||
let content: HTML
|
||||
let visibility: Visibility
|
||||
let sensitive: Bool
|
||||
let spoilerText: String
|
||||
let mediaAttachments: [Attachment]
|
||||
let mentions: [Mention]
|
||||
let tags: [Tag]
|
||||
let emojis: [Emoji]
|
||||
let reblogsCount: Int
|
||||
let favouritesCount: Int
|
||||
@DecodableDefault.Zero private(set) var repliesCount: Int
|
||||
let application: Application?
|
||||
let url: URL?
|
||||
let inReplyToId: String?
|
||||
let inReplyToAccountId: String?
|
||||
let reblog: Status?
|
||||
let poll: Poll?
|
||||
let card: Card?
|
||||
let language: String?
|
||||
let text: String?
|
||||
@DecodableDefault.False private(set) var favourited: Bool
|
||||
@DecodableDefault.False private(set) var reblogged: Bool
|
||||
@DecodableDefault.False private(set) var muted: Bool
|
||||
@DecodableDefault.False private(set) var bookmarked: Bool
|
||||
let pinned: Bool?
|
||||
public let id: String
|
||||
public let uri: String
|
||||
public let createdAt: Date
|
||||
public let account: Account
|
||||
public let content: HTML
|
||||
public let visibility: Visibility
|
||||
public let sensitive: Bool
|
||||
public let spoilerText: String
|
||||
public let mediaAttachments: [Attachment]
|
||||
public let mentions: [Mention]
|
||||
public let tags: [Tag]
|
||||
public let emojis: [Emoji]
|
||||
public let reblogsCount: Int
|
||||
public let favouritesCount: Int
|
||||
@DecodableDefault.Zero public private(set) var repliesCount: Int
|
||||
public let application: Application?
|
||||
public let url: URL?
|
||||
public let inReplyToId: String?
|
||||
public let inReplyToAccountId: String?
|
||||
public let reblog: Status?
|
||||
public let poll: Poll?
|
||||
public let card: Card?
|
||||
public let language: String?
|
||||
public let text: String?
|
||||
@DecodableDefault.False public private(set) var favourited: Bool
|
||||
@DecodableDefault.False public private(set) var reblogged: Bool
|
||||
@DecodableDefault.False public private(set) var muted: Bool
|
||||
@DecodableDefault.False public private(set) var bookmarked: Bool
|
||||
public let pinned: Bool?
|
||||
|
||||
// Xcode-generated memberwise initializer
|
||||
init(
|
||||
public init(
|
||||
id: String,
|
||||
uri: String,
|
||||
createdAt: Date,
|
||||
|
@ -88,7 +88,6 @@ class Status: Codable, Identifiable {
|
|||
self.emojis = emojis
|
||||
self.reblogsCount = reblogsCount
|
||||
self.favouritesCount = favouritesCount
|
||||
self.repliesCount = repliesCount
|
||||
self.application = application
|
||||
self.url = url
|
||||
self.inReplyToId = inReplyToId
|
||||
|
@ -98,15 +97,16 @@ class Status: Codable, Identifiable {
|
|||
self.card = card
|
||||
self.language = language
|
||||
self.text = text
|
||||
self.pinned = pinned
|
||||
self.repliesCount = repliesCount
|
||||
self.favourited = favourited
|
||||
self.reblogged = reblogged
|
||||
self.muted = muted
|
||||
self.bookmarked = bookmarked
|
||||
self.pinned = pinned
|
||||
}
|
||||
}
|
||||
|
||||
extension Status {
|
||||
public extension Status {
|
||||
var displayStatus: Status {
|
||||
reblog ?? self
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ extension Status {
|
|||
}
|
||||
|
||||
extension Status: Hashable {
|
||||
static func == (lhs: Status, rhs: Status) -> Bool {
|
||||
public static func == (lhs: Status, rhs: Status) -> Bool {
|
||||
lhs.id == rhs.id
|
||||
&& lhs.uri == rhs.uri
|
||||
&& lhs.createdAt == rhs.createdAt
|
||||
|
@ -153,7 +153,7 @@ extension Status: Hashable {
|
|||
&& lhs.pinned == rhs.pinned
|
||||
}
|
||||
|
||||
func hash(into hasher: inout Hasher) {
|
||||
public func hash(into hasher: inout Hasher) {
|
||||
hasher.combine(id)
|
||||
hasher.combine(uri)
|
||||
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
|
||||
|
||||
enum Timeline: Hashable {
|
||||
public enum Timeline: Hashable {
|
||||
case home
|
||||
case local
|
||||
case federated
|
||||
|
@ -10,7 +10,7 @@ enum Timeline: Hashable {
|
|||
case tag(String)
|
||||
}
|
||||
|
||||
extension Timeline {
|
||||
public extension Timeline {
|
||||
static let nonLists: [Timeline] = [.home, .local, .federated]
|
||||
|
||||
var endpoint: TimelinesEndpoint {
|
||||
|
@ -30,7 +30,7 @@ extension Timeline {
|
|||
}
|
||||
|
||||
extension Timeline: Identifiable {
|
||||
var id: String {
|
||||
public var id: String {
|
||||
switch self {
|
||||
case .home:
|
||||
return "home"
|
|
@ -4,22 +4,22 @@ import Foundation
|
|||
import Combine
|
||||
import Alamofire
|
||||
|
||||
typealias Session = Alamofire.Session
|
||||
public typealias Session = Alamofire.Session
|
||||
|
||||
class HTTPClient {
|
||||
public class HTTPClient {
|
||||
private let session: Session
|
||||
private let decoder: DataDecoder
|
||||
|
||||
init(session: Session, decoder: DataDecoder) {
|
||||
public init(session: Session, decoder: DataDecoder) {
|
||||
self.session = session
|
||||
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()
|
||||
}
|
||||
|
||||
func request<T: DecodableTarget, E: Error & Decodable>(
|
||||
public func request<T: DecodableTarget, E: Error & Decodable>(
|
||||
_ target: T,
|
||||
decodeErrorsAs errorType: E.Type) -> AnyPublisher<T.ResultType, Error> {
|
||||
let decoder = self.decoder
|
||||
|
@ -43,12 +43,12 @@ class HTTPClient {
|
|||
}
|
||||
|
||||
private extension HTTPClient {
|
||||
private func requestPublisher<T: DecodableTarget>(_ target: T) -> DataResponsePublisher<T.ResultType> {
|
||||
#if DEBUG
|
||||
if let url = try? target.asURLRequest().url {
|
||||
StubbingURLProtocol.setTarget(target, forURL: url)
|
||||
}
|
||||
#endif
|
||||
func requestPublisher<T: DecodableTarget>(_ target: T) -> DataResponsePublisher<T.ResultType> {
|
||||
// #if DEBUG
|
||||
// if let url = try? target.asURLRequest().url {
|
||||
// StubbingURLProtocol.setTarget(target, forURL: url)
|
||||
// }
|
||||
// #endif
|
||||
|
||||
return session.request(target)
|
||||
.validate()
|
|
@ -3,13 +3,13 @@
|
|||
import Foundation
|
||||
import Alamofire
|
||||
|
||||
typealias HTTPMethod = Alamofire.HTTPMethod
|
||||
typealias HTTPHeaders = Alamofire.HTTPHeaders
|
||||
typealias ParameterEncoding = Alamofire.ParameterEncoding
|
||||
typealias URLEncoding = Alamofire.URLEncoding
|
||||
typealias JSONEncoding = Alamofire.JSONEncoding
|
||||
public typealias HTTPMethod = Alamofire.HTTPMethod
|
||||
public typealias HTTPHeaders = Alamofire.HTTPHeaders
|
||||
public typealias ParameterEncoding = Alamofire.ParameterEncoding
|
||||
public typealias URLEncoding = Alamofire.URLEncoding
|
||||
public typealias JSONEncoding = Alamofire.JSONEncoding
|
||||
|
||||
protocol HTTPTarget: URLRequestConvertible {
|
||||
public protocol HTTPTarget: URLRequestConvertible {
|
||||
var baseURL: URL { get }
|
||||
var pathComponents: [String] { get }
|
||||
var method: HTTPMethod { get }
|
||||
|
@ -18,7 +18,7 @@ protocol HTTPTarget: URLRequestConvertible {
|
|||
var headers: HTTPHeaders? { get }
|
||||
}
|
||||
|
||||
extension HTTPTarget {
|
||||
public extension HTTPTarget {
|
||||
func asURLRequest() throws -> URLRequest {
|
||||
var url = baseURL
|
||||
|
||||
|
@ -30,6 +30,6 @@ extension HTTPTarget {
|
|||
}
|
||||
}
|
||||
|
||||
protocol DecodableTarget: HTTPTarget {
|
||||
public protocol DecodableTarget: HTTPTarget {
|
||||
associatedtype ResultType: Decodable
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
enum AccessTokenEndpoint {
|
||||
public enum AccessTokenEndpoint {
|
||||
case oauthToken(
|
||||
clientID: String,
|
||||
clientSecret: String,
|
||||
|
@ -14,21 +14,21 @@ enum AccessTokenEndpoint {
|
|||
}
|
||||
|
||||
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"]
|
||||
}
|
||||
|
||||
var method: HTTPMethod {
|
||||
public var method: HTTPMethod {
|
||||
switch self {
|
||||
case .oauthToken: return .post
|
||||
}
|
||||
}
|
||||
|
||||
var parameters: [String: Any]? {
|
||||
public var parameters: [String: Any]? {
|
||||
switch self {
|
||||
case let .oauthToken(clientID, clientSecret, code, grantType, scopes, redirectURI):
|
||||
return [
|
|
@ -2,24 +2,24 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
enum AccountEndpoint {
|
||||
public enum AccountEndpoint {
|
||||
case verifyCredentials
|
||||
}
|
||||
|
||||
extension AccountEndpoint: MastodonEndpoint {
|
||||
typealias ResultType = Account
|
||||
public typealias ResultType = Account
|
||||
|
||||
var context: [String] {
|
||||
public var context: [String] {
|
||||
defaultContext + ["accounts"]
|
||||
}
|
||||
|
||||
var pathComponentsInContext: [String] {
|
||||
public var pathComponentsInContext: [String] {
|
||||
switch self {
|
||||
case .verifyCredentials: return ["verify_credentials"]
|
||||
}
|
||||
}
|
||||
|
||||
var method: HTTPMethod {
|
||||
public var method: HTTPMethod {
|
||||
switch self {
|
||||
case .verifyCredentials: return .get
|
||||
}
|
|
@ -2,26 +2,26 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
enum AppAuthorizationEndpoint {
|
||||
public enum AppAuthorizationEndpoint {
|
||||
case apps(clientName: String, redirectURI: String, scopes: String, website: URL?)
|
||||
}
|
||||
|
||||
extension AppAuthorizationEndpoint: MastodonEndpoint {
|
||||
typealias ResultType = AppAuthorization
|
||||
public typealias ResultType = AppAuthorization
|
||||
|
||||
var pathComponentsInContext: [String] {
|
||||
public var pathComponentsInContext: [String] {
|
||||
switch self {
|
||||
case .apps: return ["apps"]
|
||||
}
|
||||
}
|
||||
|
||||
var method: HTTPMethod {
|
||||
public var method: HTTPMethod {
|
||||
switch self {
|
||||
case .apps: return .post
|
||||
}
|
||||
}
|
||||
|
||||
var parameters: [String: Any]? {
|
||||
public var parameters: [String: Any]? {
|
||||
switch self {
|
||||
case let .apps(clientName, redirectURI, scopes, website):
|
||||
var params = [
|
|
@ -2,23 +2,23 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
enum ContextEndpoint {
|
||||
public enum ContextEndpoint {
|
||||
case context(id: String)
|
||||
}
|
||||
|
||||
extension ContextEndpoint: MastodonEndpoint {
|
||||
typealias ResultType = MastodonContext
|
||||
public typealias ResultType = MastodonContext
|
||||
|
||||
var context: [String] {
|
||||
public var context: [String] {
|
||||
defaultContext + ["statuses"]
|
||||
}
|
||||
|
||||
var pathComponentsInContext: [String] {
|
||||
public var pathComponentsInContext: [String] {
|
||||
switch self {
|
||||
case let .context(id):
|
||||
return [id, "context"]
|
||||
}
|
||||
}
|
||||
|
||||
var method: HTTPMethod { .get }
|
||||
public var method: HTTPMethod { .get }
|
||||
}
|
|
@ -2,16 +2,16 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
enum DeletionEndpoint {
|
||||
public enum DeletionEndpoint {
|
||||
case oauthRevoke(token: String, clientID: String, clientSecret: String)
|
||||
case list(id: String)
|
||||
case filter(id: String)
|
||||
}
|
||||
|
||||
extension DeletionEndpoint: MastodonEndpoint {
|
||||
typealias ResultType = [String: String]
|
||||
public typealias ResultType = [String: String]
|
||||
|
||||
var context: [String] {
|
||||
public var context: [String] {
|
||||
switch self {
|
||||
case .oauthRevoke:
|
||||
return ["oauth"]
|
||||
|
@ -22,7 +22,7 @@ extension DeletionEndpoint: MastodonEndpoint {
|
|||
}
|
||||
}
|
||||
|
||||
var pathComponentsInContext: [String] {
|
||||
public var pathComponentsInContext: [String] {
|
||||
switch self {
|
||||
case .oauthRevoke:
|
||||
return ["revoke"]
|
||||
|
@ -31,7 +31,7 @@ extension DeletionEndpoint: MastodonEndpoint {
|
|||
}
|
||||
}
|
||||
|
||||
var method: HTTPMethod {
|
||||
public var method: HTTPMethod {
|
||||
switch self {
|
||||
case .oauthRevoke:
|
||||
return .post
|
||||
|
@ -40,7 +40,7 @@ extension DeletionEndpoint: MastodonEndpoint {
|
|||
}
|
||||
}
|
||||
|
||||
var parameters: [String: Any]? {
|
||||
public var parameters: [String: Any]? {
|
||||
switch self {
|
||||
case let .oauthRevoke(token, clientID, clientSecret):
|
||||
return ["token": token, "client_id": clientID, "client_secret": clientSecret]
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
enum FilterEndpoint {
|
||||
public enum FilterEndpoint {
|
||||
case create(
|
||||
phrase: String,
|
||||
context: [Filter.Context],
|
||||
|
@ -19,13 +19,13 @@ enum FilterEndpoint {
|
|||
}
|
||||
|
||||
extension FilterEndpoint: MastodonEndpoint {
|
||||
typealias ResultType = Filter
|
||||
public typealias ResultType = Filter
|
||||
|
||||
var context: [String] {
|
||||
public var context: [String] {
|
||||
defaultContext + ["filters"]
|
||||
}
|
||||
|
||||
var pathComponentsInContext: [String] {
|
||||
public var pathComponentsInContext: [String] {
|
||||
switch self {
|
||||
case .create:
|
||||
return []
|
||||
|
@ -34,7 +34,7 @@ extension FilterEndpoint: MastodonEndpoint {
|
|||
}
|
||||
}
|
||||
|
||||
var parameters: [String: Any]? {
|
||||
public var parameters: [String: Any]? {
|
||||
switch self {
|
||||
case let .create(phrase, context, irreversible, wholeWord, expiresIn):
|
||||
return params(phrase: phrase,
|
||||
|
@ -55,7 +55,7 @@ extension FilterEndpoint: MastodonEndpoint {
|
|||
}
|
||||
}
|
||||
|
||||
var method: HTTPMethod {
|
||||
public var method: HTTPMethod {
|
||||
switch self {
|
||||
case .create:
|
||||
return .post
|
|
@ -2,25 +2,25 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
enum FiltersEndpoint {
|
||||
public enum FiltersEndpoint {
|
||||
case filters
|
||||
}
|
||||
|
||||
extension FiltersEndpoint: MastodonEndpoint {
|
||||
typealias ResultType = [Filter]
|
||||
public typealias ResultType = [Filter]
|
||||
|
||||
var context: [String] {
|
||||
public var context: [String] {
|
||||
defaultContext + ["filters"]
|
||||
}
|
||||
|
||||
var pathComponentsInContext: [String] {
|
||||
public var pathComponentsInContext: [String] {
|
||||
switch self {
|
||||
case .filters:
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
var method: HTTPMethod {
|
||||
public var method: HTTPMethod {
|
||||
switch self {
|
||||
case .filters:
|
||||
return .get
|
|
@ -2,20 +2,20 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
enum InstanceEndpoint {
|
||||
public enum InstanceEndpoint {
|
||||
case instance
|
||||
}
|
||||
|
||||
extension InstanceEndpoint: MastodonEndpoint {
|
||||
typealias ResultType = Instance
|
||||
public typealias ResultType = Instance
|
||||
|
||||
var pathComponentsInContext: [String] {
|
||||
public var pathComponentsInContext: [String] {
|
||||
switch self {
|
||||
case .instance: return ["instance"]
|
||||
}
|
||||
}
|
||||
|
||||
var method: HTTPMethod {
|
||||
public var method: HTTPMethod {
|
||||
switch self {
|
||||
case .instance: return .get
|
||||
}
|
|
@ -2,32 +2,32 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
enum ListEndpoint {
|
||||
public enum ListEndpoint {
|
||||
case create(title: String)
|
||||
}
|
||||
|
||||
extension ListEndpoint: MastodonEndpoint {
|
||||
typealias ResultType = MastodonList
|
||||
public typealias ResultType = MastodonList
|
||||
|
||||
var context: [String] {
|
||||
public var context: [String] {
|
||||
defaultContext + ["lists"]
|
||||
}
|
||||
|
||||
var pathComponentsInContext: [String] {
|
||||
public var pathComponentsInContext: [String] {
|
||||
switch self {
|
||||
case .create:
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
var parameters: [String: Any]? {
|
||||
public var parameters: [String: Any]? {
|
||||
switch self {
|
||||
case let .create(title):
|
||||
return ["title": title]
|
||||
}
|
||||
}
|
||||
|
||||
var method: HTTPMethod {
|
||||
public var method: HTTPMethod {
|
||||
switch self {
|
||||
case .create:
|
||||
return .post
|
|
@ -2,18 +2,18 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
enum ListsEndpoint {
|
||||
public enum ListsEndpoint {
|
||||
case lists
|
||||
}
|
||||
|
||||
extension ListsEndpoint: MastodonEndpoint {
|
||||
typealias ResultType = [MastodonList]
|
||||
public typealias ResultType = [MastodonList]
|
||||
|
||||
var pathComponentsInContext: [String] {
|
||||
public var pathComponentsInContext: [String] {
|
||||
["lists"]
|
||||
}
|
||||
|
||||
var method: HTTPMethod {
|
||||
public var method: HTTPMethod {
|
||||
.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
|
||||
|
||||
enum PreferencesEndpoint {
|
||||
public enum PreferencesEndpoint {
|
||||
case preferences
|
||||
}
|
||||
|
||||
extension PreferencesEndpoint: MastodonEndpoint {
|
||||
typealias ResultType = MastodonPreferences
|
||||
public typealias ResultType = MastodonPreferences
|
||||
|
||||
var pathComponentsInContext: [String] {
|
||||
public var pathComponentsInContext: [String] {
|
||||
switch self {
|
||||
case .preferences: return ["preferences"]
|
||||
}
|
||||
}
|
||||
|
||||
var method: HTTPMethod {
|
||||
public var method: HTTPMethod {
|
||||
switch self {
|
||||
case .preferences: return .get
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
enum PushSubscriptionEndpoint {
|
||||
public enum PushSubscriptionEndpoint {
|
||||
case create(
|
||||
endpoint: URL,
|
||||
publicKey: String,
|
||||
|
@ -14,15 +14,15 @@ enum PushSubscriptionEndpoint {
|
|||
}
|
||||
|
||||
extension PushSubscriptionEndpoint: MastodonEndpoint {
|
||||
typealias ResultType = PushSubscription
|
||||
public typealias ResultType = PushSubscription
|
||||
|
||||
var context: [String] {
|
||||
public var context: [String] {
|
||||
defaultContext + ["push", "subscription"]
|
||||
}
|
||||
|
||||
var pathComponentsInContext: [String] { [] }
|
||||
public var pathComponentsInContext: [String] { [] }
|
||||
|
||||
var method: HTTPMethod {
|
||||
public var method: HTTPMethod {
|
||||
switch self {
|
||||
case .create: return .post
|
||||
case .read: return .get
|
||||
|
@ -31,7 +31,7 @@ extension PushSubscriptionEndpoint: MastodonEndpoint {
|
|||
}
|
||||
}
|
||||
|
||||
var parameters: [String: Any]? {
|
||||
public var parameters: [String: Any]? {
|
||||
switch self {
|
||||
case let .create(endpoint, publicKey, auth, alerts):
|
||||
return ["subscription":
|
|
@ -2,20 +2,20 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
enum StatusEndpoint {
|
||||
public enum StatusEndpoint {
|
||||
case status(id: String)
|
||||
case favourite(id: String)
|
||||
case unfavourite(id: String)
|
||||
}
|
||||
|
||||
extension StatusEndpoint: MastodonEndpoint {
|
||||
typealias ResultType = Status
|
||||
public typealias ResultType = Status
|
||||
|
||||
var context: [String] {
|
||||
public var context: [String] {
|
||||
defaultContext + ["statuses"]
|
||||
}
|
||||
|
||||
var pathComponentsInContext: [String] {
|
||||
public var pathComponentsInContext: [String] {
|
||||
switch self {
|
||||
case let .status(id):
|
||||
return [id]
|
||||
|
@ -26,7 +26,7 @@ extension StatusEndpoint: MastodonEndpoint {
|
|||
}
|
||||
}
|
||||
|
||||
var method: HTTPMethod {
|
||||
public var method: HTTPMethod {
|
||||
switch self {
|
||||
case .status:
|
||||
return .get
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
enum TimelinesEndpoint {
|
||||
public enum TimelinesEndpoint {
|
||||
case `public`(local: Bool)
|
||||
case tag(String)
|
||||
case home
|
||||
|
@ -10,13 +10,13 @@ enum TimelinesEndpoint {
|
|||
}
|
||||
|
||||
extension TimelinesEndpoint: MastodonEndpoint {
|
||||
typealias ResultType = [Status]
|
||||
public typealias ResultType = [Status]
|
||||
|
||||
var context: [String] {
|
||||
public var context: [String] {
|
||||
defaultContext + ["timelines"]
|
||||
}
|
||||
|
||||
var pathComponentsInContext: [String] {
|
||||
public var pathComponentsInContext: [String] {
|
||||
switch self {
|
||||
case .public:
|
||||
return ["public"]
|
||||
|
@ -29,7 +29,7 @@ extension TimelinesEndpoint: MastodonEndpoint {
|
|||
}
|
||||
}
|
||||
|
||||
var parameters: [String: Any]? {
|
||||
public var parameters: [String: Any]? {
|
||||
switch self {
|
||||
case let .public(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
|
||||
|
||||
class MastodonDecoder: JSONDecoder {
|
||||
override init() {
|
||||
public class MastodonDecoder: JSONDecoder {
|
||||
public override init() {
|
||||
super.init()
|
||||
|
||||
let dateFormatter = DateFormatter()
|
||||
|
||||
dateFormatter.dateFormat = MastodonAPI.dateFormat
|
||||
dateFormatter.dateFormat = Constants.dateFormat
|
||||
dateDecodingStrategy = .formatted(dateFormatter)
|
||||
keyDecodingStrategy = .convertFromSnakeCase
|
||||
}
|
|
@ -2,13 +2,13 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
class MastodonEncoder: JSONEncoder {
|
||||
override init() {
|
||||
public class MastodonEncoder: JSONEncoder {
|
||||
public override init() {
|
||||
super.init()
|
||||
|
||||
let dateFormatter = DateFormatter()
|
||||
|
||||
dateFormatter.dateFormat = MastodonAPI.dateFormat
|
||||
dateFormatter.dateFormat = Constants.dateFormat
|
||||
dateEncodingStrategy = .formatted(dateFormatter)
|
||||
keyEncodingStrategy = .convertToSnakeCase
|
||||
outputFormatting = .sortedKeys
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
protocol MastodonEndpoint {
|
||||
public protocol MastodonEndpoint {
|
||||
associatedtype ResultType: Decodable
|
||||
var APIVersion: String { get }
|
||||
var context: [String] { get }
|
||||
|
@ -13,7 +13,7 @@ protocol MastodonEndpoint {
|
|||
var headers: HTTPHeaders? { get }
|
||||
}
|
||||
|
||||
extension MastodonEndpoint {
|
||||
public extension MastodonEndpoint {
|
||||
var defaultContext: [String] {
|
||||
["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/
|
||||
|
||||
protocol DecodableDefaultSource {
|
||||
public protocol DecodableDefaultSource {
|
||||
associatedtype Value: Decodable
|
||||
static var defaultValue: Value { get }
|
||||
}
|
||||
|
||||
enum DecodableDefault {}
|
||||
public enum DecodableDefault {}
|
||||
|
||||
// swiftlint:disable nesting
|
||||
extension DecodableDefault {
|
||||
@propertyWrapper
|
||||
struct Wrapper<Source: DecodableDefaultSource> {
|
||||
typealias Value = Source.Value
|
||||
var wrappedValue = Source.defaultValue
|
||||
public struct Wrapper<Source: DecodableDefaultSource> {
|
||||
public typealias Value = Source.Value
|
||||
public var wrappedValue = Source.defaultValue
|
||||
|
||||
public init() {}
|
||||
}
|
||||
}
|
||||
|
||||
extension DecodableDefault {
|
||||
public extension DecodableDefault {
|
||||
typealias Source = DecodableDefaultSource
|
||||
typealias List = Decodable & ExpressibleByArrayLiteral
|
||||
typealias Map = Decodable & ExpressibleByDictionaryLiteral
|
||||
|
||||
enum Sources {
|
||||
enum True: Source {
|
||||
static var defaultValue: Bool { true }
|
||||
public enum True: Source {
|
||||
public static var defaultValue: Bool { true }
|
||||
}
|
||||
|
||||
enum False: Source {
|
||||
static var defaultValue: Bool { false }
|
||||
public enum False: Source {
|
||||
public static var defaultValue: Bool { false }
|
||||
}
|
||||
|
||||
enum EmptyString: Source {
|
||||
static var defaultValue: String { "" }
|
||||
public enum EmptyString: Source {
|
||||
public static var defaultValue: String { "" }
|
||||
}
|
||||
|
||||
enum EmptyList<T: List>: Source {
|
||||
static var defaultValue: T { [] }
|
||||
public enum EmptyList<T: List>: Source {
|
||||
public static var defaultValue: T { [] }
|
||||
}
|
||||
|
||||
enum EmptyMap<T: Map>: Source {
|
||||
static var defaultValue: T { [:] }
|
||||
public enum EmptyMap<T: Map>: Source {
|
||||
public static var defaultValue: T { [:] }
|
||||
}
|
||||
|
||||
enum Zero: Source {
|
||||
static var defaultValue: Int { 0 }
|
||||
public enum Zero: Source {
|
||||
public static var defaultValue: Int { 0 }
|
||||
}
|
||||
|
||||
enum StatusVisibilityPublic: Source {
|
||||
static var defaultValue: Status.Visibility { .public }
|
||||
public enum StatusVisibilityPublic: Source {
|
||||
public static var defaultValue: Status.Visibility { .public }
|
||||
}
|
||||
|
||||
enum ExpandMediaDefault: Source {
|
||||
static var defaultValue: MastodonPreferences.ExpandMedia { .default }
|
||||
public enum ExpandMediaDefault: Source {
|
||||
public static var defaultValue: MastodonPreferences.ExpandMedia { .default }
|
||||
}
|
||||
}
|
||||
}
|
||||
// swiftlint:enable nesting
|
||||
|
||||
extension DecodableDefault {
|
||||
public extension DecodableDefault {
|
||||
typealias True = Wrapper<Sources.True>
|
||||
typealias False = Wrapper<Sources.False>
|
||||
typealias EmptyString = Wrapper<Sources.EmptyString>
|
||||
|
@ -73,7 +75,7 @@ extension DecodableDefault {
|
|||
}
|
||||
|
||||
extension DecodableDefault.Wrapper: Decodable {
|
||||
init(from decoder: Decoder) throws {
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.singleValueContainer()
|
||||
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: Encodable where Value: Encodable {
|
||||
func encode(to encoder: Encoder) throws {
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.singleValueContainer()
|
||||
try container.encode(wrappedValue)
|
||||
}
|
||||
}
|
||||
|
||||
extension KeyedDecodingContainer {
|
||||
public extension KeyedDecodingContainer {
|
||||
func decode<T>(_ type: DecodableDefault.Wrapper<T>.Type,
|
||||
forKey key: Key) throws -> DecodableDefault.Wrapper<T> {
|
||||
try decodeIfPresent(type, forKey: key) ?? .init()
|
|
@ -2,16 +2,14 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
protocol Unknowable: RawRepresentable, CaseIterable where RawValue: Equatable {
|
||||
public protocol Unknowable: RawRepresentable, CaseIterable where RawValue: Equatable {
|
||||
static var unknownCase: Self { get }
|
||||
}
|
||||
|
||||
extension Unknowable {
|
||||
public extension Unknowable {
|
||||
init(rawValue: RawValue) {
|
||||
self = Self.allCases.first { $0.rawValue == rawValue } ?? Self.unknownCase
|
||||
}
|
||||
}
|
||||
|
||||
extension Unknowable {
|
||||
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 */; };
|
||||
D0A652AD24DE3EB6002EA33F /* PreferencesEndpoint+Stubbing.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0A652AC24DE3EB6002EA33F /* PreferencesEndpoint+Stubbing.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 */; };
|
||||
D0BEB1F924F9D627001B0F04 /* ListsEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEB1F824F9D627001B0F04 /* ListsEndpoint.swift */; };
|
||||
D0BEB1FD24F9E4E5001B0F04 /* ListsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEB1FC24F9E4E5001B0F04 /* ListsViewModel.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 */; };
|
||||
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 */; };
|
||||
D0BEB21324FA2C0A001B0F04 /* EditFilterViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEB21224FA2C0A001B0F04 /* EditFilterViewModel.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 */; };
|
||||
D0C7D4A324F7616A001EBDBB /* TabNavigationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D42E24F76169001EBDBB /* TabNavigationView.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 */; };
|
||||
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 */; };
|
||||
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 */; };
|
||||
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 */; };
|
||||
D0C7D4C324F7616A001EBDBB /* MetatextApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D45424F76169001EBDBB /* MetatextApp.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 */; };
|
||||
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 */; };
|
||||
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 */; };
|
||||
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 */; };
|
||||
D0C7D4F224F7616A001EBDBB /* TimelineService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D48C24F76169001EBDBB /* TimelineService.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 */; };
|
||||
D0C7D4F924F7616A001EBDBB /* UserNotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D49324F7616A001EBDBB /* UserNotificationService.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 */; };
|
||||
D0C7D4FF24F761D0001EBDBB /* KeychainService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D49024F7616A001EBDBB /* KeychainService.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 */; };
|
||||
D0DC174A24CFF15F00A75C65 /* AppAuthorizationEndpoint+Stubbing.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0DC174924CFF15F00A75C65 /* AppAuthorizationEndpoint+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 */; };
|
||||
D0DC175F24D016EA00A75C65 /* Alamofire in Frameworks */ = {isa = PBXBuildFile; productRef = D0DC175E24D016EA00A75C65 /* Alamofire */; };
|
||||
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 */; };
|
||||
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 */; };
|
||||
|
@ -207,17 +158,11 @@
|
|||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
|
@ -233,32 +178,10 @@
|
|||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
|
@ -286,26 +209,7 @@
|
|||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
|
@ -323,6 +227,7 @@
|
|||
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>"; };
|
||||
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; };
|
||||
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>"; };
|
||||
|
@ -337,6 +242,7 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D06B492324D4611300642749 /* KingfisherSwiftUI in Frameworks */,
|
||||
D0E0F1E624FC4B76002C04BF /* Mastodon in Frameworks */,
|
||||
D0666A4924C6C1A300F3F04B /* GRDB in Frameworks */,
|
||||
D0DC175F24D016EA00A75C65 /* Alamofire in Frameworks */,
|
||||
);
|
||||
|
@ -354,6 +260,7 @@
|
|||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D0E0F1E824FC5A61002C04BF /* Mastodon in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -382,6 +289,7 @@
|
|||
D047FA7F24C3E21000AF17C5 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D0E0F1E424FC49FC002C04BF /* Mastodon */,
|
||||
D0C7D45224F76169001EBDBB /* Assets.xcassets */,
|
||||
D0C7D46424F76169001EBDBB /* Databases */,
|
||||
D0ED1BB224CE3A1600B4899C /* Development Assets */,
|
||||
|
@ -392,7 +300,6 @@
|
|||
D0C7D47324F76169001EBDBB /* Networking */,
|
||||
D0E5361A24E3EB4D00FB1CE1 /* Notification Service Extension */,
|
||||
D047FA8D24C3E21200AF17C5 /* Products */,
|
||||
D0C7D43224F76169001EBDBB /* Property Wrappers */,
|
||||
D0C7D48924F76169001EBDBB /* Services */,
|
||||
D0C7D41D24F76169001EBDBB /* Supporting Files */,
|
||||
D0C7D45324F76169001EBDBB /* System */,
|
||||
|
@ -470,43 +377,13 @@
|
|||
path = "View Controllers";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D0C7D43224F76169001EBDBB /* Property Wrappers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D0C7D43324F76169001EBDBB /* DecodableDefault.swift */,
|
||||
);
|
||||
path = "Property Wrappers";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D0C7D43824F76169001EBDBB /* Model */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D0C7D43D24F76169001EBDBB /* AccessToken.swift */,
|
||||
D0C7D44D24F76169001EBDBB /* Account.swift */,
|
||||
D0C7D45024F76169001EBDBB /* AlertItem.swift */,
|
||||
D0C7D44A24F76169001EBDBB /* AppAuthorization.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 */,
|
||||
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 */,
|
||||
D0C7D44E24F76169001EBDBB /* Unknowable.swift */,
|
||||
);
|
||||
path = Model;
|
||||
sourceTree = "<group>";
|
||||
|
@ -563,7 +440,6 @@
|
|||
D0C7D46824F76169001EBDBB /* Extensions */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D0C7D47224F76169001EBDBB /* CodingUserInfoKey+Extensions.swift */,
|
||||
D0C7D47124F76169001EBDBB /* Data+Extensions.swift */,
|
||||
D0C7D47024F76169001EBDBB /* Date+Extensions.swift */,
|
||||
D0C7D46E24F76169001EBDBB /* KingfisherOptionsInfo+Extensions.swift */,
|
||||
|
@ -580,50 +456,11 @@
|
|||
D0C7D47324F76169001EBDBB /* Networking */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D0C7D47524F76169001EBDBB /* HTTPClient.swift */,
|
||||
D0C7D47424F76169001EBDBB /* HTTPTarget.swift */,
|
||||
D0C7D47724F76169001EBDBB /* Mastodon API */,
|
||||
D0C7D47624F76169001EBDBB /* WebAuthSession.swift */,
|
||||
);
|
||||
path = Networking;
|
||||
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 */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -731,6 +568,7 @@
|
|||
D0666A4824C6C1A300F3F04B /* GRDB */,
|
||||
D0DC175E24D016EA00A75C65 /* Alamofire */,
|
||||
D06B492224D4611300642749 /* KingfisherSwiftUI */,
|
||||
D0E0F1E524FC4B76002C04BF /* Mastodon */,
|
||||
);
|
||||
productName = "Metatext (iOS)";
|
||||
productReference = D047FA8C24C3E21200AF17C5 /* Metatext.app */;
|
||||
|
@ -771,6 +609,7 @@
|
|||
);
|
||||
name = "Notification Service Extension";
|
||||
packageProductDependencies = (
|
||||
D0E0F1E724FC5A61002C04BF /* Mastodon */,
|
||||
);
|
||||
productName = "Notification Service Extension";
|
||||
productReference = D0E5361924E3EB4D00FB1CE1 /* Notification Service Extension.appex */;
|
||||
|
@ -880,16 +719,9 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
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 */,
|
||||
D0C7D4B824F7616A001EBDBB /* Application.swift in Sources */,
|
||||
D0C7D4E724F7616A001EBDBB /* AppAuthorizationEndpoint.swift in Sources */,
|
||||
D0C7D4EA24F7616A001EBDBB /* DeletionEndpoint.swift in Sources */,
|
||||
D0C7D4B724F7616A001EBDBB /* TransientStatusCollection.swift in Sources */,
|
||||
D01F41DF24F8868800D55A2D /* AttachmentViewModel.swift in Sources */,
|
||||
D0C7D4E824F7616A001EBDBB /* AccountEndpoint.swift in Sources */,
|
||||
D0C7D4A324F7616A001EBDBB /* TabNavigationView.swift in Sources */,
|
||||
D0C7D49C24F7616A001EBDBB /* RootView.swift in Sources */,
|
||||
D0C7D4D224F7616A001EBDBB /* ContentDatabase.swift in Sources */,
|
||||
|
@ -900,55 +732,33 @@
|
|||
D0C7D4CD24F7616A001EBDBB /* AddIdentityViewModel.swift in Sources */,
|
||||
D03658D124EDD80900AC17EC /* ContextEndpoint+Stubbing.swift in Sources */,
|
||||
D0BEB1F324F8EE8C001B0F04 /* AttachmentView.swift in Sources */,
|
||||
D0BEB1F524F9A216001B0F04 /* Paged.swift in Sources */,
|
||||
D0DC174A24CFF15F00A75C65 /* AppAuthorizationEndpoint+Stubbing.swift in Sources */,
|
||||
D0BEB20D24FA193A001B0F04 /* FilterEndpoint.swift in Sources */,
|
||||
D0C7D49A24F7616A001EBDBB /* StatusListView.swift in Sources */,
|
||||
D01F41D924F880C400D55A2D /* TouchFallthroughTextView.swift in Sources */,
|
||||
D0BEB20924FA1136001B0F04 /* Filter.swift in Sources */,
|
||||
D0C7D4A524F7616A001EBDBB /* StatusListViewController.swift in Sources */,
|
||||
D0C7D4CC24F7616A001EBDBB /* IdentitiesViewModel.swift in Sources */,
|
||||
D0C7D4E024F7616A001EBDBB /* WebAuthSession.swift in Sources */,
|
||||
D0C7D4F024F7616A001EBDBB /* MastodonTarget.swift in Sources */,
|
||||
D0C7D4A624F7616A001EBDBB /* DecodableDefault.swift in Sources */,
|
||||
D0C7D4CB24F7616A001EBDBB /* RootViewModel.swift in Sources */,
|
||||
D0C7D4BC24F7616A001EBDBB /* Tag.swift in Sources */,
|
||||
D0C7D4E324F7616A001EBDBB /* PushSubscriptionEndpoint.swift in Sources */,
|
||||
D0C7D4CE24F7616A001EBDBB /* PreferencesViewModel.swift in Sources */,
|
||||
D0C7D4D124F7616A001EBDBB /* IdentityDatabase.swift in Sources */,
|
||||
D0C7D4ED24F7616A001EBDBB /* MastodonAPI.swift in Sources */,
|
||||
D0C7D4D624F7616A001EBDBB /* NSMutableAttributedString+Extensions.swift in Sources */,
|
||||
D05494FA24EA4E5E008B00A5 /* TimelinesEndpoint+Stubbing.swift in Sources */,
|
||||
D0A652AD24DE3EB6002EA33F /* PreferencesEndpoint+Stubbing.swift in Sources */,
|
||||
D0C7D4A924F7616A001EBDBB /* Mention.swift in Sources */,
|
||||
D0DC175524D00F0A00A75C65 /* AccessTokenEndpoint+Stubbing.swift in Sources */,
|
||||
D0C7D4B524F7616A001EBDBB /* Instance.swift in Sources */,
|
||||
D0C7D4D324F7616A001EBDBB /* DatabaseError.swift in Sources */,
|
||||
D0C7D4E224F7616A001EBDBB /* MastodonEndpoint.swift in Sources */,
|
||||
D0C7D4F224F7616A001EBDBB /* TimelineService.swift in Sources */,
|
||||
D0C7D4BF24F7616A001EBDBB /* AppEnvironment.swift in Sources */,
|
||||
D0C7D49D24F7616A001EBDBB /* PostingReadingPreferencesView.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 */,
|
||||
D0C7D4DF24F7616A001EBDBB /* HTTPClient.swift in Sources */,
|
||||
D0C7D4D424F7616A001EBDBB /* NSError+Extensions.swift in Sources */,
|
||||
D052BBCA24D74C9200A80A7A /* MockUserDefaults.swift in Sources */,
|
||||
D0C7D4DB24F7616A001EBDBB /* Date+Extensions.swift in Sources */,
|
||||
D0C7D4DA24F7616A001EBDBB /* View+Extensions.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 */,
|
||||
D0BEB20124FA0220001B0F04 /* ListEndpoint.swift in Sources */,
|
||||
D0C7D4BA24F7616A001EBDBB /* AppAuthorization.swift in Sources */,
|
||||
D0C7D4AB24F7616A001EBDBB /* Identity.swift in Sources */,
|
||||
D0C7D4C024F7616A001EBDBB /* AlertItem.swift in Sources */,
|
||||
D0C7D4B424F7616A001EBDBB /* MastodonContext.swift in Sources */,
|
||||
D0C7D4A224F7616A001EBDBB /* NotificationTypesPreferencesView.swift in Sources */,
|
||||
D0C7D4CF24F7616A001EBDBB /* StatusViewModel.swift in Sources */,
|
||||
D0C7D4C724F7616A001EBDBB /* PostingReadingPreferencesViewModel.swift in Sources */,
|
||||
|
@ -964,46 +774,28 @@
|
|||
D0DC174624CFEC2000A75C65 /* StubbingURLProtocol.swift in Sources */,
|
||||
D0BEB1FF24F9E5BB001B0F04 /* ListsView.swift in Sources */,
|
||||
D0C7D4F824F7616A001EBDBB /* SecretsService.swift in Sources */,
|
||||
D0C7D4DE24F7616A001EBDBB /* HTTPTarget.swift in Sources */,
|
||||
D0C7D4F624F7616A001EBDBB /* KeychainService.swift in Sources */,
|
||||
D0C7D4C124F7616A001EBDBB /* MastodonPreferences.swift in Sources */,
|
||||
D0DC174D24CFF1F100A75C65 /* Stubbing.swift in Sources */,
|
||||
D0C7D4E524F7616A001EBDBB /* InstanceEndpoint.swift in Sources */,
|
||||
D0C7D49724F7616A001EBDBB /* IdentitiesView.swift in Sources */,
|
||||
D074577724D29006004758DB /* MockWebAuthSession.swift in Sources */,
|
||||
D0C7D4F924F7616A001EBDBB /* UserNotificationService.swift in Sources */,
|
||||
D0C7D49824F7616A001EBDBB /* CustomEmojiText.swift in Sources */,
|
||||
D01F41E424F8889700D55A2D /* AttachmentsView.swift in Sources */,
|
||||
D0C7D4AA24F7616A001EBDBB /* Attachment.swift in Sources */,
|
||||
D0C7D4AF24F7616A001EBDBB /* PushNotification.swift in Sources */,
|
||||
D0BEB20724FA1121001B0F04 /* FiltersViewModel.swift in Sources */,
|
||||
D0C7D4C924F7616A001EBDBB /* TabNavigationViewModel.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 */,
|
||||
D074577A24D29366004758DB /* URLSessionConfiguration+Extensions.swift in Sources */,
|
||||
D0C7D4E424F7616A001EBDBB /* PreferencesEndpoint.swift in Sources */,
|
||||
D0C7D49924F7616A001EBDBB /* AddIdentityView.swift in Sources */,
|
||||
D0BEB1FD24F9E4E5001B0F04 /* ListsViewModel.swift in Sources */,
|
||||
D0C7D4C324F7616A001EBDBB /* MetatextApp.swift in Sources */,
|
||||
D0C7D4B124F7616A001EBDBB /* Card.swift in Sources */,
|
||||
D0C7D4F324F7616A001EBDBB /* ContextService.swift in Sources */,
|
||||
D0C7D4DD24F7616A001EBDBB /* CodingUserInfoKey+Extensions.swift in Sources */,
|
||||
D0C7D4D824F7616A001EBDBB /* Publisher+Extensions.swift in Sources */,
|
||||
D0BEB20524FA1107001B0F04 /* FiltersView.swift in Sources */,
|
||||
D01F41D824F880C400D55A2D /* StatusTableViewCell.swift in Sources */,
|
||||
D04FD73C24D4A83A007D572D /* InstanceEndpoint+Stubbing.swift in Sources */,
|
||||
D0C7D4BE24F7616A001EBDBB /* Unknowable.swift in Sources */,
|
||||
D0C7D4AE24F7616A001EBDBB /* Timeline.swift in Sources */,
|
||||
D0C7D49B24F7616A001EBDBB /* PreferencesView.swift in Sources */,
|
||||
D0C7D4EC24F7616A001EBDBB /* StatusEndpoint.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;
|
||||
};
|
||||
|
@ -1021,12 +813,8 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D0C7D4FC24F761A8001EBDBB /* Unknowable.swift in Sources */,
|
||||
D0C7D4FB24F7619F001EBDBB /* PushNotification.swift in Sources */,
|
||||
D0C7D4FE24F761C9001EBDBB /* SecretsService.swift in Sources */,
|
||||
D0C7D50124F761EC001EBDBB /* MastodonAPI.swift in Sources */,
|
||||
D0E5361C24E3EB4D00FB1CE1 /* NotificationService.swift in Sources */,
|
||||
D0C7D4FD24F761C1001EBDBB /* MastodonDecoder.swift in Sources */,
|
||||
D0C7D50024F761E0001EBDBB /* NSError+Extensions.swift in Sources */,
|
||||
D0C7D4FF24F761D0001EBDBB /* KeychainService.swift in Sources */,
|
||||
);
|
||||
|
@ -1404,6 +1192,14 @@
|
|||
package = D0DC175D24D016EA00A75C65 /* XCRemoteSwiftPackageReference "Alamofire" */;
|
||||
productName = Alamofire;
|
||||
};
|
||||
D0E0F1E524FC4B76002C04BF /* Mastodon */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
productName = Mastodon;
|
||||
};
|
||||
D0E0F1E724FC5A61002C04BF /* Mastodon */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
productName = Mastodon;
|
||||
};
|
||||
/* End XCSwiftPackageProductDependency section */
|
||||
};
|
||||
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.
|
||||
|
||||
import Foundation
|
||||
import Mastodon
|
||||
|
||||
struct AppEnvironment {
|
||||
let session: Session
|
||||
|
@ -8,7 +9,6 @@ struct AppEnvironment {
|
|||
let keychainServiceType: KeychainService.Type
|
||||
let userDefaults: UserDefaults
|
||||
let inMemoryContent: Bool
|
||||
let attributedStringCache = AttributedStringCache()
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
import Foundation
|
||||
import Mastodon
|
||||
|
||||
struct Identity: Codable, Hashable, Identifiable {
|
||||
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 CryptoKit
|
||||
import Mastodon
|
||||
|
||||
class NotificationService: UNNotificationServiceExtension {
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import Foundation
|
||||
import Combine
|
||||
import Mastodon
|
||||
|
||||
struct AllIdentitiesService {
|
||||
let mostRecentlyUsedIdentityID: AnyPublisher<UUID?, Never>
|
||||
|
@ -49,7 +50,7 @@ extension AllIdentitiesService {
|
|||
|
||||
func deleteIdentity(_ identity: Identity) -> AnyPublisher<Never, Error> {
|
||||
let secretsService = SecretsService(identityID: identity.id, keychainService: environment.keychainServiceType)
|
||||
let networkClient = MastodonClient(environment: environment)
|
||||
let networkClient = MastodonClient(session: environment.session)
|
||||
|
||||
networkClient.instanceURL = identity.url
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import Foundation
|
||||
import Combine
|
||||
import Mastodon
|
||||
|
||||
struct AuthenticationService {
|
||||
private let networkClient: MastodonClient
|
||||
|
@ -9,7 +10,7 @@ struct AuthenticationService {
|
|||
private let webAuthSessionContextProvider = WebAuthSessionContextProvider()
|
||||
|
||||
init(environment: AppEnvironment) {
|
||||
networkClient = MastodonClient(environment: environment)
|
||||
networkClient = MastodonClient(session: environment.session)
|
||||
webAuthSessionType = environment.webAuthSessionType
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import Foundation
|
||||
import Combine
|
||||
import Mastodon
|
||||
|
||||
class IdentityService {
|
||||
@Published private(set) var identity: Identity
|
||||
|
@ -34,11 +35,11 @@ class IdentityService {
|
|||
secretsService = SecretsService(
|
||||
identityID: identityID,
|
||||
keychainService: environment.keychainServiceType)
|
||||
networkClient = MastodonClient(environment: environment)
|
||||
networkClient = MastodonClient(session: environment.session)
|
||||
networkClient.instanceURL = identity.url
|
||||
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
|
||||
self?.observationErrorsInput.send(error)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import Foundation
|
||||
import Combine
|
||||
import Mastodon
|
||||
|
||||
struct ContextService {
|
||||
let statusSections: AnyPublisher<[[Status]], Error>
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import Foundation
|
||||
import Combine
|
||||
import Mastodon
|
||||
|
||||
protocol StatusListService {
|
||||
var statusSections: AnyPublisher<[[Status]], Error> { get }
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import Foundation
|
||||
import Combine
|
||||
import Mastodon
|
||||
|
||||
struct TimelineService {
|
||||
let statusSections: AnyPublisher<[[Status]], Error>
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import Foundation
|
||||
import Combine
|
||||
import Mastodon
|
||||
|
||||
struct StatusService {
|
||||
let status: Status
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright © 2020 Metabolist. All rights reserved.
|
||||
|
||||
import Foundation
|
||||
import Mastodon
|
||||
|
||||
struct AttachmentViewModel {
|
||||
let attachment: Attachment
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import Foundation
|
||||
import Combine
|
||||
import Mastodon
|
||||
|
||||
class EditFilterViewModel: ObservableObject {
|
||||
@Published var filter: Filter
|
||||
|
@ -56,3 +57,22 @@ extension EditFilterViewModel {
|
|||
.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