Merge branch 'feature/core-data-stack' into develop
This commit is contained in:
commit
3dc6ec165e
|
@ -0,0 +1,36 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="17709" systemVersion="20C69" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
|
||||||
|
<entity name="HomeTimelineIndex" representedClassName=".HomeTimelineIndex" syncable="YES">
|
||||||
|
<attribute name="createdAt" attributeType="Date" usesScalarValueType="NO"/>
|
||||||
|
<attribute name="domain" attributeType="String"/>
|
||||||
|
<attribute name="identifier" attributeType="String"/>
|
||||||
|
<attribute name="userIdentifier" attributeType="String"/>
|
||||||
|
<relationship name="toots" maxCount="1" deletionRule="Nullify" destinationEntity="Toots" inverseName="homeTimelineIndex" inverseEntity="Toots"/>
|
||||||
|
</entity>
|
||||||
|
<entity name="MastodonUser" representedClassName=".MastodonUser" syncable="YES">
|
||||||
|
<attribute name="acct" attributeType="String"/>
|
||||||
|
<attribute name="avatar" optional="YES" attributeType="String"/>
|
||||||
|
<attribute name="createdAt" attributeType="Date" usesScalarValueType="NO"/>
|
||||||
|
<attribute name="domain" attributeType="String"/>
|
||||||
|
<attribute name="id" attributeType="String"/>
|
||||||
|
<attribute name="identifier" attributeType="String"/>
|
||||||
|
<attribute name="updatedAt" attributeType="Date" usesScalarValueType="NO"/>
|
||||||
|
<attribute name="username" attributeType="String"/>
|
||||||
|
<relationship name="toots" toMany="YES" deletionRule="Nullify" destinationEntity="Toots" inverseName="author" inverseEntity="Toots"/>
|
||||||
|
</entity>
|
||||||
|
<entity name="Toots" representedClassName=".Toots" syncable="YES">
|
||||||
|
<attribute name="content" attributeType="String"/>
|
||||||
|
<attribute name="createdAt" attributeType="Date" usesScalarValueType="NO"/>
|
||||||
|
<attribute name="domain" attributeType="String"/>
|
||||||
|
<attribute name="id" attributeType="String"/>
|
||||||
|
<attribute name="identifier" attributeType="String"/>
|
||||||
|
<attribute name="updatedAt" attributeType="Date" usesScalarValueType="NO"/>
|
||||||
|
<relationship name="author" maxCount="1" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="toots" inverseEntity="MastodonUser"/>
|
||||||
|
<relationship name="homeTimelineIndex" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="HomeTimelineIndex" inverseName="toots" inverseEntity="HomeTimelineIndex"/>
|
||||||
|
</entity>
|
||||||
|
<elements>
|
||||||
|
<element name="Toots" positionX="-248.4609375" positionY="17.3203125" width="128" height="163"/>
|
||||||
|
<element name="MastodonUser" positionX="9.34375" positionY="71.8828125" width="128" height="178"/>
|
||||||
|
<element name="HomeTimelineIndex" positionX="-108" positionY="135" width="128" height="118"/>
|
||||||
|
</elements>
|
||||||
|
</model>
|
|
@ -0,0 +1,18 @@
|
||||||
|
//
|
||||||
|
// CoreDataStack.h
|
||||||
|
// CoreDataStack
|
||||||
|
//
|
||||||
|
// Created by MainasuK Cirno on 2021/1/27.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
//! Project version number for CoreDataStack.
|
||||||
|
FOUNDATION_EXPORT double CoreDataStackVersionNumber;
|
||||||
|
|
||||||
|
//! Project version string for CoreDataStack.
|
||||||
|
FOUNDATION_EXPORT const unsigned char CoreDataStackVersionString[];
|
||||||
|
|
||||||
|
// In this header, you should import all the public headers of your framework using statements like #import <CoreDataStack/PublicHeader.h>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,101 @@
|
||||||
|
//
|
||||||
|
// CoreDataStack.swift
|
||||||
|
// CoreDataStack
|
||||||
|
//
|
||||||
|
// Created by Cirno MainasuK on 2021-1-27.
|
||||||
|
//
|
||||||
|
|
||||||
|
import os
|
||||||
|
import Foundation
|
||||||
|
import CoreData
|
||||||
|
|
||||||
|
public final class CoreDataStack {
|
||||||
|
|
||||||
|
private(set) var storeDescriptions: [NSPersistentStoreDescription]
|
||||||
|
|
||||||
|
init(persistentStoreDescriptions storeDescriptions: [NSPersistentStoreDescription]) {
|
||||||
|
self.storeDescriptions = storeDescriptions
|
||||||
|
}
|
||||||
|
|
||||||
|
public convenience init(databaseName: String = "shared") {
|
||||||
|
let storeURL = URL.storeURL(for: "group.com.joinmastodon.mastodon-temp", databaseName: databaseName)
|
||||||
|
let storeDescription = NSPersistentStoreDescription(url: storeURL)
|
||||||
|
self.init(persistentStoreDescriptions: [storeDescription])
|
||||||
|
}
|
||||||
|
|
||||||
|
public private(set) lazy var persistentContainer: NSPersistentContainer = {
|
||||||
|
/*
|
||||||
|
The persistent container for the application. This implementation
|
||||||
|
creates and returns a container, having loaded the store for the
|
||||||
|
application to it. This property is optional since there are legitimate
|
||||||
|
error conditions that could cause the creation of the store to fail.
|
||||||
|
*/
|
||||||
|
let container = CoreDataStack.persistentContainer()
|
||||||
|
CoreDataStack.configure(persistentContainer: container, storeDescriptions: storeDescriptions)
|
||||||
|
CoreDataStack.load(persistentContainer: container)
|
||||||
|
|
||||||
|
return container
|
||||||
|
}()
|
||||||
|
|
||||||
|
static func persistentContainer() -> NSPersistentContainer {
|
||||||
|
let bundles = [Bundle(for: Toots.self)]
|
||||||
|
guard let managedObjectModel = NSManagedObjectModel.mergedModel(from: bundles) else {
|
||||||
|
fatalError("cannot locate bundles")
|
||||||
|
}
|
||||||
|
|
||||||
|
let container = NSPersistentContainer(name: "CoreDataStack", managedObjectModel: managedObjectModel)
|
||||||
|
return container
|
||||||
|
}
|
||||||
|
|
||||||
|
static func configure(persistentContainer container: NSPersistentContainer, storeDescriptions: [NSPersistentStoreDescription]) {
|
||||||
|
container.persistentStoreDescriptions = storeDescriptions
|
||||||
|
}
|
||||||
|
|
||||||
|
static func load(persistentContainer container: NSPersistentContainer) {
|
||||||
|
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
|
||||||
|
if let error = error as NSError? {
|
||||||
|
// Replace this implementation with code to handle the error appropriately.
|
||||||
|
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
|
||||||
|
|
||||||
|
/*
|
||||||
|
Typical reasons for an error here include:
|
||||||
|
* The parent directory does not exist, cannot be created, or disallows writing.
|
||||||
|
* The persistent store is not accessible, due to permissions or data protection when the device is locked.
|
||||||
|
* The device is out of space.
|
||||||
|
* The store could not be migrated to the current model version.
|
||||||
|
Check the error message to determine what the actual problem was.
|
||||||
|
*/
|
||||||
|
if let reason = error.userInfo["reason"] as? String,
|
||||||
|
(reason == "Can't find mapping model for migration" || reason == "Persistent store migration failed, missing mapping model.") {
|
||||||
|
if let storeDescription = container.persistentStoreDescriptions.first, let url = storeDescription.url {
|
||||||
|
try? container.persistentStoreCoordinator.destroyPersistentStore(at: url, ofType: NSSQLiteStoreType, options: nil)
|
||||||
|
os_log("%{public}s[%{public}ld], %{public}s: cannot migrate model. rebuild database…", ((#file as NSString).lastPathComponent), #line, #function)
|
||||||
|
} else {
|
||||||
|
assertionFailure()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fatalError("Unresolved error \(error), \(error.userInfo)")
|
||||||
|
}
|
||||||
|
|
||||||
|
container.viewContext.mergePolicy = NSMergePolicy.mergeByPropertyObjectTrump
|
||||||
|
|
||||||
|
// it's looks like the remote notification only trigger when app enter and leave background
|
||||||
|
container.viewContext.automaticallyMergesChangesFromParent = true
|
||||||
|
|
||||||
|
os_log("%{public}s[%{public}ld], %{public}s: %s", ((#file as NSString).lastPathComponent), #line, #function, storeDescription.debugDescription)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension CoreDataStack {
|
||||||
|
|
||||||
|
public func rebuild() {
|
||||||
|
let oldStoreURL = persistentContainer.persistentStoreCoordinator.url(for: persistentContainer.persistentStoreCoordinator.persistentStores.first!)
|
||||||
|
try! persistentContainer.persistentStoreCoordinator.destroyPersistentStore(at: oldStoreURL, ofType: NSSQLiteStoreType, options: nil)
|
||||||
|
|
||||||
|
CoreDataStack.load(persistentContainer: persistentContainer)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
//
|
||||||
|
// HomeTimelineIndex.swift
|
||||||
|
// CoreDataStack
|
||||||
|
//
|
||||||
|
// Created by MainasuK Cirno on 2021/1/27.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import CoreData
|
||||||
|
|
||||||
|
final class HomeTimelineIndex: NSManagedObject {
|
||||||
|
|
||||||
|
public typealias ID = String
|
||||||
|
@NSManaged public private(set) var identifier: ID
|
||||||
|
@NSManaged public private(set) var domain: String
|
||||||
|
@NSManaged public private(set) var userIdentifier: String
|
||||||
|
|
||||||
|
@NSManaged public private(set) var createdAt: Date
|
||||||
|
|
||||||
|
// many-to-one relationship
|
||||||
|
@NSManaged public private(set) var toots: Toots
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension HomeTimelineIndex {
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
public static func insert(
|
||||||
|
into context: NSManagedObjectContext,
|
||||||
|
property: Property,
|
||||||
|
toots: Toots
|
||||||
|
) -> HomeTimelineIndex {
|
||||||
|
let index: HomeTimelineIndex = context.insertObject()
|
||||||
|
|
||||||
|
index.identifier = property.identifier
|
||||||
|
index.domain = property.domain
|
||||||
|
index.userIdentifier = toots.author.identifier
|
||||||
|
index.createdAt = toots.createdAt
|
||||||
|
|
||||||
|
index.toots = toots
|
||||||
|
|
||||||
|
return index
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension HomeTimelineIndex {
|
||||||
|
public struct Property {
|
||||||
|
public let identifier: String
|
||||||
|
public let domain: String
|
||||||
|
|
||||||
|
public init(domain: String) {
|
||||||
|
self.identifier = UUID().uuidString + "@" + domain
|
||||||
|
self.domain = domain
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension HomeTimelineIndex: Managed {
|
||||||
|
public static var defaultSortDescriptors: [NSSortDescriptor] {
|
||||||
|
return [NSSortDescriptor(keyPath: \HomeTimelineIndex.createdAt, ascending: false)]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,96 @@
|
||||||
|
//
|
||||||
|
// MastodonUser.swift
|
||||||
|
// CoreDataStack
|
||||||
|
//
|
||||||
|
// Created by MainasuK Cirno on 2021/1/27.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import CoreData
|
||||||
|
|
||||||
|
final class MastodonUser: NSManagedObject {
|
||||||
|
|
||||||
|
public typealias ID = String
|
||||||
|
@NSManaged public private(set) var identifier: ID
|
||||||
|
@NSManaged public private(set) var domain: String
|
||||||
|
|
||||||
|
@NSManaged public private(set) var id: String
|
||||||
|
@NSManaged public private(set) var acct: String
|
||||||
|
@NSManaged public private(set) var username: String
|
||||||
|
@NSManaged public private(set) var displayName: String?
|
||||||
|
|
||||||
|
@NSManaged public private(set) var createdAt: Date
|
||||||
|
@NSManaged public private(set) var updatedAt: Date
|
||||||
|
|
||||||
|
@NSManaged public private(set) var toots: Set<Toots>?
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension MastodonUser {
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
public static func insert(
|
||||||
|
into context: NSManagedObjectContext,
|
||||||
|
property: Property
|
||||||
|
) -> MastodonUser {
|
||||||
|
let user: MastodonUser = context.insertObject()
|
||||||
|
|
||||||
|
user.identifier = property.identifier
|
||||||
|
user.domain = property.domain
|
||||||
|
|
||||||
|
user.id = property.id
|
||||||
|
user.acct = property.acct
|
||||||
|
user.username = property.username
|
||||||
|
user.displayName = property.displayName
|
||||||
|
|
||||||
|
user.createdAt = property.createdAt
|
||||||
|
user.updatedAt = property.networkDate
|
||||||
|
|
||||||
|
return user
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension MastodonUser {
|
||||||
|
public struct Property {
|
||||||
|
public let identifier: String
|
||||||
|
public let domain: String
|
||||||
|
|
||||||
|
public let id: String
|
||||||
|
public let acct: String
|
||||||
|
public let username: String
|
||||||
|
public let displayName: String?
|
||||||
|
|
||||||
|
public let createdAt: Date
|
||||||
|
public let networkDate: Date
|
||||||
|
|
||||||
|
public init(
|
||||||
|
id: String,
|
||||||
|
domain: String,
|
||||||
|
acct: String,
|
||||||
|
username: String,
|
||||||
|
displayName: String?,
|
||||||
|
content: String,
|
||||||
|
createdAt: Date,
|
||||||
|
networkDate: Date
|
||||||
|
) {
|
||||||
|
self.identifier = id + "@" + domain
|
||||||
|
self.domain = domain
|
||||||
|
self.id = id
|
||||||
|
self.acct = acct
|
||||||
|
self.username = username
|
||||||
|
self.displayName = displayName.flatMap { displayName in
|
||||||
|
return displayName.isEmpty ? nil : displayName
|
||||||
|
}
|
||||||
|
self.createdAt = createdAt
|
||||||
|
self.networkDate = networkDate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension MastodonUser: Managed {
|
||||||
|
public static var defaultSortDescriptors: [NSSortDescriptor] {
|
||||||
|
return [NSSortDescriptor(keyPath: \MastodonUser.createdAt, ascending: false)]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
//
|
||||||
|
// Toots.swift
|
||||||
|
// CoreDataStack
|
||||||
|
//
|
||||||
|
// Created by MainasuK Cirno on 2021/1/27.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import CoreData
|
||||||
|
|
||||||
|
final class Toots: NSManagedObject {
|
||||||
|
|
||||||
|
public typealias ID = String
|
||||||
|
@NSManaged public private(set) var identifier: ID
|
||||||
|
@NSManaged public private(set) var domain: String
|
||||||
|
|
||||||
|
@NSManaged public private(set) var id: String
|
||||||
|
@NSManaged public private(set) var content: String
|
||||||
|
|
||||||
|
@NSManaged public private(set) var createdAt: Date
|
||||||
|
@NSManaged public private(set) var updatedAt: Date
|
||||||
|
|
||||||
|
// many-to-one relationship
|
||||||
|
@NSManaged public private(set) var author: MastodonUser
|
||||||
|
|
||||||
|
// one-to-many relationship
|
||||||
|
@NSManaged public private(set) var homeTimelineIndexes: Set<HomeTimelineIndex>?
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Toots {
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
public static func insert(
|
||||||
|
into context: NSManagedObjectContext,
|
||||||
|
property: Property,
|
||||||
|
author: MastodonUser
|
||||||
|
) -> Toots {
|
||||||
|
let toots: Toots = context.insertObject()
|
||||||
|
|
||||||
|
toots.identifier = property.identifier
|
||||||
|
toots.domain = property.domain
|
||||||
|
|
||||||
|
toots.id = property.id
|
||||||
|
toots.content = property.content
|
||||||
|
toots.createdAt = property.createdAt
|
||||||
|
toots.updatedAt = property.networkDate
|
||||||
|
|
||||||
|
toots.author = author
|
||||||
|
|
||||||
|
return toots
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Toots {
|
||||||
|
public struct Property {
|
||||||
|
public let identifier: String
|
||||||
|
public let domain: String
|
||||||
|
|
||||||
|
public let id: String
|
||||||
|
public let content: String
|
||||||
|
public let createdAt: Date
|
||||||
|
public let networkDate: Date
|
||||||
|
|
||||||
|
public init(
|
||||||
|
id: String,
|
||||||
|
domain: String,
|
||||||
|
content: String,
|
||||||
|
createdAt: Date,
|
||||||
|
networkDate: Date
|
||||||
|
) {
|
||||||
|
self.identifier = id + "@" + domain
|
||||||
|
self.domain = domain
|
||||||
|
self.id = id
|
||||||
|
self.content = content
|
||||||
|
self.createdAt = createdAt
|
||||||
|
self.networkDate = networkDate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Toots: Managed {
|
||||||
|
public static var defaultSortDescriptors: [NSSortDescriptor] {
|
||||||
|
return [NSSortDescriptor(keyPath: \Toots.createdAt, ascending: false)]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
//
|
||||||
|
// Collection.swift
|
||||||
|
// CoreDataStack
|
||||||
|
//
|
||||||
|
// Created by Cirno MainasuK on 2020-10-14.
|
||||||
|
// Copyright © 2020 Twidere. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import CoreData
|
||||||
|
|
||||||
|
extension Collection where Iterator.Element: NSManagedObject {
|
||||||
|
public func fetchFaults() {
|
||||||
|
guard !self.isEmpty else { return }
|
||||||
|
guard let context = self.first?.managedObjectContext else {
|
||||||
|
fatalError("Managed object must have context")
|
||||||
|
}
|
||||||
|
let faults = self.filter { $0.isFault }
|
||||||
|
guard let object = faults.first else { return }
|
||||||
|
let request = NSFetchRequest<Iterator.Element>()
|
||||||
|
request.entity = object.entity
|
||||||
|
request.returnsObjectsAsFaults = false
|
||||||
|
request.predicate = NSPredicate(format: "self in %@", faults)
|
||||||
|
do {
|
||||||
|
let _ = try context.fetch(request)
|
||||||
|
} catch {
|
||||||
|
assertionFailure(error.localizedDescription)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
//
|
||||||
|
// NSManagedObjectContext.swift
|
||||||
|
// CoreDataStack
|
||||||
|
//
|
||||||
|
// Created by Cirno MainasuK on 2020-8-10.
|
||||||
|
// Copyright © 2020 Dimension. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import os
|
||||||
|
import Foundation
|
||||||
|
import Combine
|
||||||
|
import CoreData
|
||||||
|
|
||||||
|
extension NSManagedObjectContext {
|
||||||
|
public func insert<T: NSManagedObject>() -> T where T: Managed {
|
||||||
|
guard let object = NSEntityDescription.insertNewObject(forEntityName: T.entityName, into: self) as? T else {
|
||||||
|
fatalError("cannot insert object: \(T.self)")
|
||||||
|
}
|
||||||
|
|
||||||
|
return object
|
||||||
|
}
|
||||||
|
|
||||||
|
public func saveOrRollback() throws {
|
||||||
|
do {
|
||||||
|
guard hasChanges else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
try save()
|
||||||
|
} catch {
|
||||||
|
rollback()
|
||||||
|
|
||||||
|
os_log("%{public}s[%{public}ld], %{public}s: %s", ((#file as NSString).lastPathComponent), #line, #function, error.localizedDescription)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func performChanges(block: @escaping () -> Void) -> Future<Result<Void, Error>, Never> {
|
||||||
|
Future { promise in
|
||||||
|
self.perform {
|
||||||
|
block()
|
||||||
|
do {
|
||||||
|
try self.saveOrRollback()
|
||||||
|
promise(.success(Result.success(())))
|
||||||
|
} catch {
|
||||||
|
promise(.success(Result.failure(error)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
//
|
||||||
|
// URL.swift
|
||||||
|
// CoreDataStack
|
||||||
|
//
|
||||||
|
// Created by Cirno MainasuK on 2021-1-27.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
public extension URL {
|
||||||
|
|
||||||
|
/// Returns a URL for the given app group and database pointing to the sqlite database.
|
||||||
|
static func storeURL(for appGroup: String, databaseName: String) -> URL {
|
||||||
|
guard let fileContainer = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroup) else {
|
||||||
|
fatalError("Shared file container could not be created.")
|
||||||
|
}
|
||||||
|
|
||||||
|
return fileContainer
|
||||||
|
.appendingPathComponent("Databases", isDirectory: true)
|
||||||
|
.appendingPathComponent("\(databaseName).sqlite")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>$(PRODUCT_NAME)</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>1.0</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
|
@ -0,0 +1,82 @@
|
||||||
|
//
|
||||||
|
// Managed.swift
|
||||||
|
// CoreDataStack
|
||||||
|
//
|
||||||
|
// Created by Cirno MainasuK on 2020-8-6.
|
||||||
|
// Copyright © 2020 Dimension. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import CoreData
|
||||||
|
|
||||||
|
public protocol Managed: class, NSFetchRequestResult {
|
||||||
|
static var entityName: String { get }
|
||||||
|
static var defaultSortDescriptors: [NSSortDescriptor] { get }
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Managed {
|
||||||
|
public static var defaultSortDescriptors: [NSSortDescriptor] {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
public static var sortedFetchRequest: NSFetchRequest<Self> {
|
||||||
|
let request = NSFetchRequest<Self>(entityName: entityName)
|
||||||
|
request.sortDescriptors = defaultSortDescriptors
|
||||||
|
return request
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension NSManagedObjectContext {
|
||||||
|
public func insertObject<T: NSManagedObject>() -> T where T: Managed {
|
||||||
|
guard let object = NSEntityDescription.insertNewObject(forEntityName: T.entityName, into: self) as? T else {
|
||||||
|
fatalError("Wrong object type")
|
||||||
|
}
|
||||||
|
|
||||||
|
return object
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Managed where Self: NSManagedObject {
|
||||||
|
public static var entityName: String { return entity().name! }
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Managed where Self: NSManagedObject {
|
||||||
|
public static func findOrCreate(in context: NSManagedObjectContext, matching predicate: NSPredicate, configure: (Self) -> Void) -> Self {
|
||||||
|
guard let object = findOrFetch(in: context, matching: predicate) else {
|
||||||
|
let newObject: Self = context.insertObject()
|
||||||
|
configure(newObject)
|
||||||
|
return newObject
|
||||||
|
}
|
||||||
|
|
||||||
|
return object
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func findOrFetch(in context: NSManagedObjectContext, matching predicate: NSPredicate) -> Self? {
|
||||||
|
guard let object = materializedObject(in: context, matching: predicate) else {
|
||||||
|
return fetch(in: context) { request in
|
||||||
|
request.predicate = predicate
|
||||||
|
request.returnsObjectsAsFaults = false
|
||||||
|
request.fetchLimit = 1
|
||||||
|
}.first
|
||||||
|
}
|
||||||
|
|
||||||
|
return object
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func materializedObject(in context: NSManagedObjectContext, matching predicate: NSPredicate) -> Self? {
|
||||||
|
for object in context.registeredObjects where !object.isFault {
|
||||||
|
guard let result = object as? Self, predicate.evaluate(with: result) else { continue }
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func fetch(in context: NSManagedObjectContext, configurationBlock: (NSFetchRequest<Self>) -> Void = { _ in }) -> [Self] {
|
||||||
|
let request = NSFetchRequest<Self>(entityName: Self.entityName)
|
||||||
|
configurationBlock(request)
|
||||||
|
return try! context.fetch(request)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
//
|
||||||
|
// NetworkUpdatable.swift
|
||||||
|
// CoreDataStack
|
||||||
|
//
|
||||||
|
// Created by Cirno MainasuK on 2020-9-4.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
public protocol NetworkUpdatable {
|
||||||
|
var networkDate: Date { get }
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
//
|
||||||
|
// CoreDataStackTests.swift
|
||||||
|
// CoreDataStackTests
|
||||||
|
//
|
||||||
|
// Created by MainasuK Cirno on 2021/1/27.
|
||||||
|
//
|
||||||
|
|
||||||
|
import XCTest
|
||||||
|
@testable import CoreDataStack
|
||||||
|
|
||||||
|
class CoreDataStackTests: XCTestCase {
|
||||||
|
|
||||||
|
override func setUpWithError() throws {
|
||||||
|
// Put setup code here. This method is called before the invocation of each test method in the class.
|
||||||
|
}
|
||||||
|
|
||||||
|
override func tearDownWithError() throws {
|
||||||
|
// Put teardown code here. This method is called after the invocation of each test method in the class.
|
||||||
|
}
|
||||||
|
|
||||||
|
func testExample() throws {
|
||||||
|
// This is an example of a functional test case.
|
||||||
|
// Use XCTAssert and related functions to verify your tests produce the correct results.
|
||||||
|
}
|
||||||
|
|
||||||
|
func testPerformanceExample() throws {
|
||||||
|
// This is an example of a performance test case.
|
||||||
|
self.measure {
|
||||||
|
// Put the code you want to measure the time of here.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>$(PRODUCT_NAME)</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>1.0</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>1</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
|
@ -12,7 +12,6 @@
|
||||||
5E44BF88AD33646E64727BCF /* Pods_MastodonTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD92E0F10BDE4FE7C4B999F2 /* Pods_MastodonTests.framework */; };
|
5E44BF88AD33646E64727BCF /* Pods_MastodonTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD92E0F10BDE4FE7C4B999F2 /* Pods_MastodonTests.framework */; };
|
||||||
7A9135D4559750AF07CA9BE4 /* Pods_Mastodon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 602D783BEC22881EBAD84419 /* Pods_Mastodon.framework */; };
|
7A9135D4559750AF07CA9BE4 /* Pods_Mastodon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 602D783BEC22881EBAD84419 /* Pods_Mastodon.framework */; };
|
||||||
DB3D0FF325BAA61700EAA174 /* AlamofireImage in Frameworks */ = {isa = PBXBuildFile; productRef = DB3D0FF225BAA61700EAA174 /* AlamofireImage */; };
|
DB3D0FF325BAA61700EAA174 /* AlamofireImage in Frameworks */ = {isa = PBXBuildFile; productRef = DB3D0FF225BAA61700EAA174 /* AlamofireImage */; };
|
||||||
DB3D100025BAA6DA00EAA174 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB3D0FFF25BAA6DA00EAA174 /* ViewController.swift */; };
|
|
||||||
DB3D100D25BAA75E00EAA174 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = DB3D100F25BAA75E00EAA174 /* Localizable.strings */; };
|
DB3D100D25BAA75E00EAA174 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = DB3D100F25BAA75E00EAA174 /* Localizable.strings */; };
|
||||||
DB3D102425BAA7B400EAA174 /* Assets.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB3D102225BAA7B400EAA174 /* Assets.swift */; };
|
DB3D102425BAA7B400EAA174 /* Assets.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB3D102225BAA7B400EAA174 /* Assets.swift */; };
|
||||||
DB3D102525BAA7B400EAA174 /* Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB3D102325BAA7B400EAA174 /* Strings.swift */; };
|
DB3D102525BAA7B400EAA174 /* Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB3D102325BAA7B400EAA174 /* Strings.swift */; };
|
||||||
|
@ -23,6 +22,29 @@
|
||||||
DB427DE225BAA00100D1B89D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DB427DE025BAA00100D1B89D /* LaunchScreen.storyboard */; };
|
DB427DE225BAA00100D1B89D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DB427DE025BAA00100D1B89D /* LaunchScreen.storyboard */; };
|
||||||
DB427DED25BAA00100D1B89D /* MastodonTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB427DEC25BAA00100D1B89D /* MastodonTests.swift */; };
|
DB427DED25BAA00100D1B89D /* MastodonTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB427DEC25BAA00100D1B89D /* MastodonTests.swift */; };
|
||||||
DB427DF825BAA00100D1B89D /* MastodonUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB427DF725BAA00100D1B89D /* MastodonUITests.swift */; };
|
DB427DF825BAA00100D1B89D /* MastodonUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB427DF725BAA00100D1B89D /* MastodonUITests.swift */; };
|
||||||
|
DB89B9F725C10FD0008580ED /* CoreDataStack.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DB89B9EE25C10FD0008580ED /* CoreDataStack.framework */; };
|
||||||
|
DB89B9FE25C10FD0008580ED /* CoreDataStackTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB89B9FD25C10FD0008580ED /* CoreDataStackTests.swift */; };
|
||||||
|
DB89BA0025C10FD0008580ED /* CoreDataStack.h in Headers */ = {isa = PBXBuildFile; fileRef = DB89B9F025C10FD0008580ED /* CoreDataStack.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
|
DB89BA0325C10FD0008580ED /* CoreDataStack.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DB89B9EE25C10FD0008580ED /* CoreDataStack.framework */; };
|
||||||
|
DB89BA0425C10FD0008580ED /* CoreDataStack.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = DB89B9EE25C10FD0008580ED /* CoreDataStack.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||||
|
DB89BA1225C1105C008580ED /* CoreDataStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB89BA1125C1105C008580ED /* CoreDataStack.swift */; };
|
||||||
|
DB89BA1B25C1107F008580ED /* Collection.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB89BA1825C1107F008580ED /* Collection.swift */; };
|
||||||
|
DB89BA1C25C1107F008580ED /* NSManagedObjectContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB89BA1925C1107F008580ED /* NSManagedObjectContext.swift */; };
|
||||||
|
DB89BA1D25C1107F008580ED /* URL.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB89BA1A25C1107F008580ED /* URL.swift */; };
|
||||||
|
DB89BA2725C110B4008580ED /* Toots.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB89BA2625C110B4008580ED /* Toots.swift */; };
|
||||||
|
DB89BA3725C1145C008580ED /* CoreData.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = DB89BA3525C1145C008580ED /* CoreData.xcdatamodeld */; };
|
||||||
|
DB89BA4325C1165F008580ED /* NetworkUpdatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB89BA4125C1165F008580ED /* NetworkUpdatable.swift */; };
|
||||||
|
DB89BA4425C1165F008580ED /* Managed.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB89BA4225C1165F008580ED /* Managed.swift */; };
|
||||||
|
DB8AF52525C131D1002E6C99 /* MastodonUser.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB8AF52425C131D1002E6C99 /* MastodonUser.swift */; };
|
||||||
|
DB8AF52E25C13561002E6C99 /* ViewStateStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB8AF52B25C13561002E6C99 /* ViewStateStore.swift */; };
|
||||||
|
DB8AF52F25C13561002E6C99 /* DocumentStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB8AF52C25C13561002E6C99 /* DocumentStore.swift */; };
|
||||||
|
DB8AF53025C13561002E6C99 /* AppContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB8AF52D25C13561002E6C99 /* AppContext.swift */; };
|
||||||
|
DB8AF54425C13647002E6C99 /* SceneCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB8AF54225C13647002E6C99 /* SceneCoordinator.swift */; };
|
||||||
|
DB8AF54525C13647002E6C99 /* NeedsDependency.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB8AF54325C13647002E6C99 /* NeedsDependency.swift */; };
|
||||||
|
DB8AF55025C13703002E6C99 /* MainTabBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB8AF54F25C13703002E6C99 /* MainTabBarController.swift */; };
|
||||||
|
DB8AF55725C137A8002E6C99 /* HomeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB8AF55625C137A8002E6C99 /* HomeViewController.swift */; };
|
||||||
|
DB8AF55D25C138B7002E6C99 /* UIViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB8AF55C25C138B7002E6C99 /* UIViewController.swift */; };
|
||||||
|
DB8AF56825C13E2A002E6C99 /* HomeTimelineIndex.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB8AF56725C13E2A002E6C99 /* HomeTimelineIndex.swift */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
|
@ -40,8 +62,43 @@
|
||||||
remoteGlobalIDString = DB427DD125BAA00100D1B89D;
|
remoteGlobalIDString = DB427DD125BAA00100D1B89D;
|
||||||
remoteInfo = Mastodon;
|
remoteInfo = Mastodon;
|
||||||
};
|
};
|
||||||
|
DB89B9F825C10FD0008580ED /* PBXContainerItemProxy */ = {
|
||||||
|
isa = PBXContainerItemProxy;
|
||||||
|
containerPortal = DB427DCA25BAA00100D1B89D /* Project object */;
|
||||||
|
proxyType = 1;
|
||||||
|
remoteGlobalIDString = DB89B9ED25C10FD0008580ED;
|
||||||
|
remoteInfo = CoreDataStack;
|
||||||
|
};
|
||||||
|
DB89B9FA25C10FD0008580ED /* PBXContainerItemProxy */ = {
|
||||||
|
isa = PBXContainerItemProxy;
|
||||||
|
containerPortal = DB427DCA25BAA00100D1B89D /* Project object */;
|
||||||
|
proxyType = 1;
|
||||||
|
remoteGlobalIDString = DB427DD125BAA00100D1B89D;
|
||||||
|
remoteInfo = Mastodon;
|
||||||
|
};
|
||||||
|
DB89BA0125C10FD0008580ED /* PBXContainerItemProxy */ = {
|
||||||
|
isa = PBXContainerItemProxy;
|
||||||
|
containerPortal = DB427DCA25BAA00100D1B89D /* Project object */;
|
||||||
|
proxyType = 1;
|
||||||
|
remoteGlobalIDString = DB89B9ED25C10FD0008580ED;
|
||||||
|
remoteInfo = CoreDataStack;
|
||||||
|
};
|
||||||
/* End PBXContainerItemProxy section */
|
/* End PBXContainerItemProxy section */
|
||||||
|
|
||||||
|
/* Begin PBXCopyFilesBuildPhase section */
|
||||||
|
DB89BA0825C10FD0008580ED /* Embed Frameworks */ = {
|
||||||
|
isa = PBXCopyFilesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
dstPath = "";
|
||||||
|
dstSubfolderSpec = 10;
|
||||||
|
files = (
|
||||||
|
DB89BA0425C10FD0008580ED /* CoreDataStack.framework in Embed Frameworks */,
|
||||||
|
);
|
||||||
|
name = "Embed Frameworks";
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXCopyFilesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
2E1F6A67FDF9771D3E064FDC /* Pods-Mastodon.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon.debug.xcconfig"; path = "Target Support Files/Pods-Mastodon/Pods-Mastodon.debug.xcconfig"; sourceTree = "<group>"; };
|
2E1F6A67FDF9771D3E064FDC /* Pods-Mastodon.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon.debug.xcconfig"; path = "Target Support Files/Pods-Mastodon/Pods-Mastodon.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
459EA4F43058CAB47719E963 /* Pods-Mastodon-MastodonUITests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon-MastodonUITests.debug.xcconfig"; path = "Target Support Files/Pods-Mastodon-MastodonUITests/Pods-Mastodon-MastodonUITests.debug.xcconfig"; sourceTree = "<group>"; };
|
459EA4F43058CAB47719E963 /* Pods-Mastodon-MastodonUITests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon-MastodonUITests.debug.xcconfig"; path = "Target Support Files/Pods-Mastodon-MastodonUITests/Pods-Mastodon-MastodonUITests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
@ -52,7 +109,6 @@
|
||||||
BB482D32A7B9825BF5327C4F /* Pods-Mastodon-MastodonUITests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon-MastodonUITests.release.xcconfig"; path = "Target Support Files/Pods-Mastodon-MastodonUITests/Pods-Mastodon-MastodonUITests.release.xcconfig"; sourceTree = "<group>"; };
|
BB482D32A7B9825BF5327C4F /* Pods-Mastodon-MastodonUITests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon-MastodonUITests.release.xcconfig"; path = "Target Support Files/Pods-Mastodon-MastodonUITests/Pods-Mastodon-MastodonUITests.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
CD92E0F10BDE4FE7C4B999F2 /* Pods_MastodonTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_MastodonTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
CD92E0F10BDE4FE7C4B999F2 /* Pods_MastodonTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_MastodonTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
DB3D0FED25BAA42200EAA174 /* MastodonSDK */ = {isa = PBXFileReference; lastKnownFileType = folder; path = MastodonSDK; sourceTree = "<group>"; };
|
DB3D0FED25BAA42200EAA174 /* MastodonSDK */ = {isa = PBXFileReference; lastKnownFileType = folder; path = MastodonSDK; sourceTree = "<group>"; };
|
||||||
DB3D0FFF25BAA6DA00EAA174 /* ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
|
|
||||||
DB3D100E25BAA75E00EAA174 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
|
DB3D100E25BAA75E00EAA174 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||||
DB3D102225BAA7B400EAA174 /* Assets.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Assets.swift; sourceTree = "<group>"; };
|
DB3D102225BAA7B400EAA174 /* Assets.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Assets.swift; sourceTree = "<group>"; };
|
||||||
DB3D102325BAA7B400EAA174 /* Strings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Strings.swift; sourceTree = "<group>"; };
|
DB3D102325BAA7B400EAA174 /* Strings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Strings.swift; sourceTree = "<group>"; };
|
||||||
|
@ -69,6 +125,31 @@
|
||||||
DB427DF325BAA00100D1B89D /* MastodonUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MastodonUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
DB427DF325BAA00100D1B89D /* MastodonUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MastodonUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
DB427DF725BAA00100D1B89D /* MastodonUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonUITests.swift; sourceTree = "<group>"; };
|
DB427DF725BAA00100D1B89D /* MastodonUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonUITests.swift; sourceTree = "<group>"; };
|
||||||
DB427DF925BAA00100D1B89D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
DB427DF925BAA00100D1B89D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
|
DB89B9EE25C10FD0008580ED /* CoreDataStack.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = CoreDataStack.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
DB89B9F025C10FD0008580ED /* CoreDataStack.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CoreDataStack.h; sourceTree = "<group>"; };
|
||||||
|
DB89B9F125C10FD0008580ED /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
|
DB89B9F625C10FD0008580ED /* CoreDataStackTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CoreDataStackTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
DB89B9FD25C10FD0008580ED /* CoreDataStackTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataStackTests.swift; sourceTree = "<group>"; };
|
||||||
|
DB89B9FF25C10FD0008580ED /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
|
DB89BA1025C10FF5008580ED /* Mastodon.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Mastodon.entitlements; sourceTree = "<group>"; };
|
||||||
|
DB89BA1125C1105C008580ED /* CoreDataStack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreDataStack.swift; sourceTree = "<group>"; };
|
||||||
|
DB89BA1825C1107F008580ED /* Collection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Collection.swift; sourceTree = "<group>"; };
|
||||||
|
DB89BA1925C1107F008580ED /* NSManagedObjectContext.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSManagedObjectContext.swift; sourceTree = "<group>"; };
|
||||||
|
DB89BA1A25C1107F008580ED /* URL.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = URL.swift; sourceTree = "<group>"; };
|
||||||
|
DB89BA2625C110B4008580ED /* Toots.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Toots.swift; sourceTree = "<group>"; };
|
||||||
|
DB89BA3625C1145C008580ED /* CoreData.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = CoreData.xcdatamodel; sourceTree = "<group>"; };
|
||||||
|
DB89BA4125C1165F008580ED /* NetworkUpdatable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkUpdatable.swift; sourceTree = "<group>"; };
|
||||||
|
DB89BA4225C1165F008580ED /* Managed.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Managed.swift; sourceTree = "<group>"; };
|
||||||
|
DB8AF52425C131D1002E6C99 /* MastodonUser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonUser.swift; sourceTree = "<group>"; };
|
||||||
|
DB8AF52B25C13561002E6C99 /* ViewStateStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewStateStore.swift; sourceTree = "<group>"; };
|
||||||
|
DB8AF52C25C13561002E6C99 /* DocumentStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DocumentStore.swift; sourceTree = "<group>"; };
|
||||||
|
DB8AF52D25C13561002E6C99 /* AppContext.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppContext.swift; sourceTree = "<group>"; };
|
||||||
|
DB8AF54225C13647002E6C99 /* SceneCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SceneCoordinator.swift; sourceTree = "<group>"; };
|
||||||
|
DB8AF54325C13647002E6C99 /* NeedsDependency.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NeedsDependency.swift; sourceTree = "<group>"; };
|
||||||
|
DB8AF54F25C13703002E6C99 /* MainTabBarController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainTabBarController.swift; sourceTree = "<group>"; };
|
||||||
|
DB8AF55625C137A8002E6C99 /* HomeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeViewController.swift; sourceTree = "<group>"; };
|
||||||
|
DB8AF55C25C138B7002E6C99 /* UIViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIViewController.swift; sourceTree = "<group>"; };
|
||||||
|
DB8AF56725C13E2A002E6C99 /* HomeTimelineIndex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeTimelineIndex.swift; sourceTree = "<group>"; };
|
||||||
EC6E707B68A67DB08EC288FA /* Pods-MastodonTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MastodonTests.debug.xcconfig"; path = "Target Support Files/Pods-MastodonTests/Pods-MastodonTests.debug.xcconfig"; sourceTree = "<group>"; };
|
EC6E707B68A67DB08EC288FA /* Pods-MastodonTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MastodonTests.debug.xcconfig"; path = "Target Support Files/Pods-MastodonTests/Pods-MastodonTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
|
@ -77,6 +158,7 @@
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
DB89BA0325C10FD0008580ED /* CoreDataStack.framework in Frameworks */,
|
||||||
5D526FE225BE9AC400460CB9 /* MastodonSDK in Frameworks */,
|
5D526FE225BE9AC400460CB9 /* MastodonSDK in Frameworks */,
|
||||||
7A9135D4559750AF07CA9BE4 /* Pods_Mastodon.framework in Frameworks */,
|
7A9135D4559750AF07CA9BE4 /* Pods_Mastodon.framework in Frameworks */,
|
||||||
DB3D0FF325BAA61700EAA174 /* AlamofireImage in Frameworks */,
|
DB3D0FF325BAA61700EAA174 /* AlamofireImage in Frameworks */,
|
||||||
|
@ -99,6 +181,21 @@
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
DB89B9EB25C10FD0008580ED /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
DB89B9F325C10FD0008580ED /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
DB89B9F725C10FD0008580ED /* CoreDataStack.framework in Frameworks */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
/* End PBXFrameworksBuildPhase section */
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXGroup section */
|
/* Begin PBXGroup section */
|
||||||
|
@ -161,6 +258,8 @@
|
||||||
DB427DD425BAA00100D1B89D /* Mastodon */,
|
DB427DD425BAA00100D1B89D /* Mastodon */,
|
||||||
DB427DEB25BAA00100D1B89D /* MastodonTests */,
|
DB427DEB25BAA00100D1B89D /* MastodonTests */,
|
||||||
DB427DF625BAA00100D1B89D /* MastodonUITests */,
|
DB427DF625BAA00100D1B89D /* MastodonUITests */,
|
||||||
|
DB89B9EF25C10FD0008580ED /* CoreDataStack */,
|
||||||
|
DB89B9FC25C10FD0008580ED /* CoreDataStackTests */,
|
||||||
DB427DD325BAA00100D1B89D /* Products */,
|
DB427DD325BAA00100D1B89D /* Products */,
|
||||||
1EBA4F56E920856A3FC84ACB /* Pods */,
|
1EBA4F56E920856A3FC84ACB /* Pods */,
|
||||||
4E8E8B18DB8471A676012CF9 /* Frameworks */,
|
4E8E8B18DB8471A676012CF9 /* Frameworks */,
|
||||||
|
@ -173,6 +272,8 @@
|
||||||
DB427DD225BAA00100D1B89D /* Mastodon.app */,
|
DB427DD225BAA00100D1B89D /* Mastodon.app */,
|
||||||
DB427DE825BAA00100D1B89D /* MastodonTests.xctest */,
|
DB427DE825BAA00100D1B89D /* MastodonTests.xctest */,
|
||||||
DB427DF325BAA00100D1B89D /* MastodonUITests.xctest */,
|
DB427DF325BAA00100D1B89D /* MastodonUITests.xctest */,
|
||||||
|
DB89B9EE25C10FD0008580ED /* CoreDataStack.framework */,
|
||||||
|
DB89B9F625C10FD0008580ED /* CoreDataStackTests.xctest */,
|
||||||
);
|
);
|
||||||
name = Products;
|
name = Products;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -180,8 +281,12 @@
|
||||||
DB427DD425BAA00100D1B89D /* Mastodon */ = {
|
DB427DD425BAA00100D1B89D /* Mastodon */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
DB89BA1025C10FF5008580ED /* Mastodon.entitlements */,
|
||||||
DB427DE325BAA00100D1B89D /* Info.plist */,
|
DB427DE325BAA00100D1B89D /* Info.plist */,
|
||||||
DB3D0FFF25BAA6DA00EAA174 /* ViewController.swift */,
|
DB8AF52A25C13561002E6C99 /* State */,
|
||||||
|
DB8AF56225C138BC002E6C99 /* Extension */,
|
||||||
|
DB8AF55525C1379F002E6C99 /* Scene */,
|
||||||
|
DB8AF54125C13647002E6C99 /* Coordinator */,
|
||||||
DB3D101B25BAA79200EAA174 /* Generated */,
|
DB3D101B25BAA79200EAA174 /* Generated */,
|
||||||
DB3D0FF825BAA6B200EAA174 /* Resources */,
|
DB3D0FF825BAA6B200EAA174 /* Resources */,
|
||||||
DB3D0FF725BAA68500EAA174 /* Supporting Files */,
|
DB3D0FF725BAA68500EAA174 /* Supporting Files */,
|
||||||
|
@ -207,8 +312,115 @@
|
||||||
path = MastodonUITests;
|
path = MastodonUITests;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
DB89B9EF25C10FD0008580ED /* CoreDataStack */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
DB89B9F125C10FD0008580ED /* Info.plist */,
|
||||||
|
DB89B9F025C10FD0008580ED /* CoreDataStack.h */,
|
||||||
|
DB89BA1125C1105C008580ED /* CoreDataStack.swift */,
|
||||||
|
DB89BA3525C1145C008580ED /* CoreData.xcdatamodeld */,
|
||||||
|
DB89BA4025C1165F008580ED /* Protocol */,
|
||||||
|
DB89BA1725C1107F008580ED /* Extension */,
|
||||||
|
DB89BA2C25C110B7008580ED /* Entity */,
|
||||||
|
);
|
||||||
|
path = CoreDataStack;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
DB89B9FC25C10FD0008580ED /* CoreDataStackTests */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
DB89B9FD25C10FD0008580ED /* CoreDataStackTests.swift */,
|
||||||
|
DB89B9FF25C10FD0008580ED /* Info.plist */,
|
||||||
|
);
|
||||||
|
path = CoreDataStackTests;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
DB89BA1725C1107F008580ED /* Extension */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
DB89BA1825C1107F008580ED /* Collection.swift */,
|
||||||
|
DB89BA1925C1107F008580ED /* NSManagedObjectContext.swift */,
|
||||||
|
DB89BA1A25C1107F008580ED /* URL.swift */,
|
||||||
|
);
|
||||||
|
path = Extension;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
DB89BA2C25C110B7008580ED /* Entity */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
DB89BA2625C110B4008580ED /* Toots.swift */,
|
||||||
|
DB8AF52425C131D1002E6C99 /* MastodonUser.swift */,
|
||||||
|
DB8AF56725C13E2A002E6C99 /* HomeTimelineIndex.swift */,
|
||||||
|
);
|
||||||
|
path = Entity;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
DB89BA4025C1165F008580ED /* Protocol */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
DB89BA4125C1165F008580ED /* NetworkUpdatable.swift */,
|
||||||
|
DB89BA4225C1165F008580ED /* Managed.swift */,
|
||||||
|
);
|
||||||
|
path = Protocol;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
DB8AF52A25C13561002E6C99 /* State */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
DB8AF52B25C13561002E6C99 /* ViewStateStore.swift */,
|
||||||
|
DB8AF52C25C13561002E6C99 /* DocumentStore.swift */,
|
||||||
|
DB8AF52D25C13561002E6C99 /* AppContext.swift */,
|
||||||
|
);
|
||||||
|
path = State;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
DB8AF54125C13647002E6C99 /* Coordinator */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
DB8AF54225C13647002E6C99 /* SceneCoordinator.swift */,
|
||||||
|
DB8AF54325C13647002E6C99 /* NeedsDependency.swift */,
|
||||||
|
);
|
||||||
|
path = Coordinator;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
DB8AF54E25C13703002E6C99 /* MainTab */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
DB8AF54F25C13703002E6C99 /* MainTabBarController.swift */,
|
||||||
|
);
|
||||||
|
path = MainTab;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
DB8AF55525C1379F002E6C99 /* Scene */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
DB8AF54E25C13703002E6C99 /* MainTab */,
|
||||||
|
DB8AF55625C137A8002E6C99 /* HomeViewController.swift */,
|
||||||
|
);
|
||||||
|
path = Scene;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
DB8AF56225C138BC002E6C99 /* Extension */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
DB8AF55C25C138B7002E6C99 /* UIViewController.swift */,
|
||||||
|
);
|
||||||
|
path = Extension;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
|
/* Begin PBXHeadersBuildPhase section */
|
||||||
|
DB89B9E925C10FD0008580ED /* Headers */ = {
|
||||||
|
isa = PBXHeadersBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
DB89BA0025C10FD0008580ED /* CoreDataStack.h in Headers */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXHeadersBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
/* Begin PBXNativeTarget section */
|
||||||
DB427DD125BAA00100D1B89D /* Mastodon */ = {
|
DB427DD125BAA00100D1B89D /* Mastodon */ = {
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
|
@ -220,10 +432,12 @@
|
||||||
DB427DD025BAA00100D1B89D /* Resources */,
|
DB427DD025BAA00100D1B89D /* Resources */,
|
||||||
5532CB85BBE168B25B20720B /* [CP] Embed Pods Frameworks */,
|
5532CB85BBE168B25B20720B /* [CP] Embed Pods Frameworks */,
|
||||||
DB3D100425BAA71500EAA174 /* ShellScript */,
|
DB3D100425BAA71500EAA174 /* ShellScript */,
|
||||||
|
DB89BA0825C10FD0008580ED /* Embed Frameworks */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
dependencies = (
|
dependencies = (
|
||||||
|
DB89BA0225C10FD0008580ED /* PBXTargetDependency */,
|
||||||
);
|
);
|
||||||
name = Mastodon;
|
name = Mastodon;
|
||||||
packageProductDependencies = (
|
packageProductDependencies = (
|
||||||
|
@ -273,6 +487,43 @@
|
||||||
productReference = DB427DF325BAA00100D1B89D /* MastodonUITests.xctest */;
|
productReference = DB427DF325BAA00100D1B89D /* MastodonUITests.xctest */;
|
||||||
productType = "com.apple.product-type.bundle.ui-testing";
|
productType = "com.apple.product-type.bundle.ui-testing";
|
||||||
};
|
};
|
||||||
|
DB89B9ED25C10FD0008580ED /* CoreDataStack */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = DB89BA0525C10FD0008580ED /* Build configuration list for PBXNativeTarget "CoreDataStack" */;
|
||||||
|
buildPhases = (
|
||||||
|
DB89B9E925C10FD0008580ED /* Headers */,
|
||||||
|
DB89B9EA25C10FD0008580ED /* Sources */,
|
||||||
|
DB89B9EB25C10FD0008580ED /* Frameworks */,
|
||||||
|
DB89B9EC25C10FD0008580ED /* Resources */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
);
|
||||||
|
name = CoreDataStack;
|
||||||
|
productName = CoreDataStack;
|
||||||
|
productReference = DB89B9EE25C10FD0008580ED /* CoreDataStack.framework */;
|
||||||
|
productType = "com.apple.product-type.framework";
|
||||||
|
};
|
||||||
|
DB89B9F525C10FD0008580ED /* CoreDataStackTests */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = DB89BA0925C10FD0008580ED /* Build configuration list for PBXNativeTarget "CoreDataStackTests" */;
|
||||||
|
buildPhases = (
|
||||||
|
DB89B9F225C10FD0008580ED /* Sources */,
|
||||||
|
DB89B9F325C10FD0008580ED /* Frameworks */,
|
||||||
|
DB89B9F425C10FD0008580ED /* Resources */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
DB89B9F925C10FD0008580ED /* PBXTargetDependency */,
|
||||||
|
DB89B9FB25C10FD0008580ED /* PBXTargetDependency */,
|
||||||
|
);
|
||||||
|
name = CoreDataStackTests;
|
||||||
|
productName = CoreDataStackTests;
|
||||||
|
productReference = DB89B9F625C10FD0008580ED /* CoreDataStackTests.xctest */;
|
||||||
|
productType = "com.apple.product-type.bundle.unit-test";
|
||||||
|
};
|
||||||
/* End PBXNativeTarget section */
|
/* End PBXNativeTarget section */
|
||||||
|
|
||||||
/* Begin PBXProject section */
|
/* Begin PBXProject section */
|
||||||
|
@ -293,6 +544,14 @@
|
||||||
CreatedOnToolsVersion = 12.4;
|
CreatedOnToolsVersion = 12.4;
|
||||||
TestTargetID = DB427DD125BAA00100D1B89D;
|
TestTargetID = DB427DD125BAA00100D1B89D;
|
||||||
};
|
};
|
||||||
|
DB89B9ED25C10FD0008580ED = {
|
||||||
|
CreatedOnToolsVersion = 12.4;
|
||||||
|
LastSwiftMigration = 1240;
|
||||||
|
};
|
||||||
|
DB89B9F525C10FD0008580ED = {
|
||||||
|
CreatedOnToolsVersion = 12.4;
|
||||||
|
TestTargetID = DB427DD125BAA00100D1B89D;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
buildConfigurationList = DB427DCD25BAA00100D1B89D /* Build configuration list for PBXProject "Mastodon" */;
|
buildConfigurationList = DB427DCD25BAA00100D1B89D /* Build configuration list for PBXProject "Mastodon" */;
|
||||||
|
@ -314,6 +573,8 @@
|
||||||
DB427DD125BAA00100D1B89D /* Mastodon */,
|
DB427DD125BAA00100D1B89D /* Mastodon */,
|
||||||
DB427DE725BAA00100D1B89D /* MastodonTests */,
|
DB427DE725BAA00100D1B89D /* MastodonTests */,
|
||||||
DB427DF225BAA00100D1B89D /* MastodonUITests */,
|
DB427DF225BAA00100D1B89D /* MastodonUITests */,
|
||||||
|
DB89B9ED25C10FD0008580ED /* CoreDataStack */,
|
||||||
|
DB89B9F525C10FD0008580ED /* CoreDataStackTests */,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
/* End PBXProject section */
|
/* End PBXProject section */
|
||||||
|
@ -344,6 +605,20 @@
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
DB89B9EC25C10FD0008580ED /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
DB89B9F425C10FD0008580ED /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
/* End PBXResourcesBuildPhase section */
|
/* End PBXResourcesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXShellScriptBuildPhase section */
|
/* Begin PBXShellScriptBuildPhase section */
|
||||||
|
@ -471,8 +746,15 @@
|
||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
DB3D100025BAA6DA00EAA174 /* ViewController.swift in Sources */,
|
DB8AF53025C13561002E6C99 /* AppContext.swift in Sources */,
|
||||||
|
DB8AF52F25C13561002E6C99 /* DocumentStore.swift in Sources */,
|
||||||
|
DB8AF55D25C138B7002E6C99 /* UIViewController.swift in Sources */,
|
||||||
|
DB8AF55025C13703002E6C99 /* MainTabBarController.swift in Sources */,
|
||||||
|
DB8AF54525C13647002E6C99 /* NeedsDependency.swift in Sources */,
|
||||||
DB427DD625BAA00100D1B89D /* AppDelegate.swift in Sources */,
|
DB427DD625BAA00100D1B89D /* AppDelegate.swift in Sources */,
|
||||||
|
DB8AF54425C13647002E6C99 /* SceneCoordinator.swift in Sources */,
|
||||||
|
DB8AF52E25C13561002E6C99 /* ViewStateStore.swift in Sources */,
|
||||||
|
DB8AF55725C137A8002E6C99 /* HomeViewController.swift in Sources */,
|
||||||
DB3D102525BAA7B400EAA174 /* Strings.swift in Sources */,
|
DB3D102525BAA7B400EAA174 /* Strings.swift in Sources */,
|
||||||
DB3D102425BAA7B400EAA174 /* Assets.swift in Sources */,
|
DB3D102425BAA7B400EAA174 /* Assets.swift in Sources */,
|
||||||
DB427DD825BAA00100D1B89D /* SceneDelegate.swift in Sources */,
|
DB427DD825BAA00100D1B89D /* SceneDelegate.swift in Sources */,
|
||||||
|
@ -495,6 +777,31 @@
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
DB89B9EA25C10FD0008580ED /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
DB89BA1225C1105C008580ED /* CoreDataStack.swift in Sources */,
|
||||||
|
DB89BA1C25C1107F008580ED /* NSManagedObjectContext.swift in Sources */,
|
||||||
|
DB89BA3725C1145C008580ED /* CoreData.xcdatamodeld in Sources */,
|
||||||
|
DB8AF52525C131D1002E6C99 /* MastodonUser.swift in Sources */,
|
||||||
|
DB89BA1B25C1107F008580ED /* Collection.swift in Sources */,
|
||||||
|
DB89BA2725C110B4008580ED /* Toots.swift in Sources */,
|
||||||
|
DB89BA4425C1165F008580ED /* Managed.swift in Sources */,
|
||||||
|
DB89BA4325C1165F008580ED /* NetworkUpdatable.swift in Sources */,
|
||||||
|
DB8AF56825C13E2A002E6C99 /* HomeTimelineIndex.swift in Sources */,
|
||||||
|
DB89BA1D25C1107F008580ED /* URL.swift in Sources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
DB89B9F225C10FD0008580ED /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
DB89B9FE25C10FD0008580ED /* CoreDataStackTests.swift in Sources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
/* End PBXSourcesBuildPhase section */
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXTargetDependency section */
|
/* Begin PBXTargetDependency section */
|
||||||
|
@ -508,6 +815,21 @@
|
||||||
target = DB427DD125BAA00100D1B89D /* Mastodon */;
|
target = DB427DD125BAA00100D1B89D /* Mastodon */;
|
||||||
targetProxy = DB427DF425BAA00100D1B89D /* PBXContainerItemProxy */;
|
targetProxy = DB427DF425BAA00100D1B89D /* PBXContainerItemProxy */;
|
||||||
};
|
};
|
||||||
|
DB89B9F925C10FD0008580ED /* PBXTargetDependency */ = {
|
||||||
|
isa = PBXTargetDependency;
|
||||||
|
target = DB89B9ED25C10FD0008580ED /* CoreDataStack */;
|
||||||
|
targetProxy = DB89B9F825C10FD0008580ED /* PBXContainerItemProxy */;
|
||||||
|
};
|
||||||
|
DB89B9FB25C10FD0008580ED /* PBXTargetDependency */ = {
|
||||||
|
isa = PBXTargetDependency;
|
||||||
|
target = DB427DD125BAA00100D1B89D /* Mastodon */;
|
||||||
|
targetProxy = DB89B9FA25C10FD0008580ED /* PBXContainerItemProxy */;
|
||||||
|
};
|
||||||
|
DB89BA0225C10FD0008580ED /* PBXTargetDependency */ = {
|
||||||
|
isa = PBXTargetDependency;
|
||||||
|
target = DB89B9ED25C10FD0008580ED /* CoreDataStack */;
|
||||||
|
targetProxy = DB89BA0125C10FD0008580ED /* PBXContainerItemProxy */;
|
||||||
|
};
|
||||||
/* End PBXTargetDependency section */
|
/* End PBXTargetDependency section */
|
||||||
|
|
||||||
/* Begin PBXVariantGroup section */
|
/* Begin PBXVariantGroup section */
|
||||||
|
@ -589,7 +911,7 @@
|
||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
|
@ -644,7 +966,7 @@
|
||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
|
@ -660,6 +982,7 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
|
CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
DEVELOPMENT_TEAM = 7LFDZ96332;
|
DEVELOPMENT_TEAM = 7LFDZ96332;
|
||||||
INFOPLIST_FILE = Mastodon/Info.plist;
|
INFOPLIST_FILE = Mastodon/Info.plist;
|
||||||
|
@ -681,6 +1004,7 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
|
CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
DEVELOPMENT_TEAM = 7LFDZ96332;
|
DEVELOPMENT_TEAM = 7LFDZ96332;
|
||||||
INFOPLIST_FILE = Mastodon/Info.plist;
|
INFOPLIST_FILE = Mastodon/Info.plist;
|
||||||
|
@ -700,7 +1024,6 @@
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = EC6E707B68A67DB08EC288FA /* Pods-MastodonTests.debug.xcconfig */;
|
baseConfigurationReference = EC6E707B68A67DB08EC288FA /* Pods-MastodonTests.debug.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
|
||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
DEVELOPMENT_TEAM = 7LFDZ96332;
|
DEVELOPMENT_TEAM = 7LFDZ96332;
|
||||||
|
@ -722,7 +1045,6 @@
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = 9780A4C98FFC65B32B50D1C0 /* Pods-MastodonTests.release.xcconfig */;
|
baseConfigurationReference = 9780A4C98FFC65B32B50D1C0 /* Pods-MastodonTests.release.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
|
||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
DEVELOPMENT_TEAM = 7LFDZ96332;
|
DEVELOPMENT_TEAM = 7LFDZ96332;
|
||||||
|
@ -780,6 +1102,103 @@
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
};
|
};
|
||||||
|
DB89BA0625C10FD0008580ED /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEFINES_MODULE = YES;
|
||||||
|
DEVELOPMENT_TEAM = 7LFDZ96332;
|
||||||
|
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||||
|
DYLIB_CURRENT_VERSION = 1;
|
||||||
|
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||||
|
INFOPLIST_FILE = CoreDataStack/Info.plist;
|
||||||
|
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@loader_path/Frameworks",
|
||||||
|
);
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.CoreDataStack;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
VERSIONING_SYSTEM = "apple-generic";
|
||||||
|
VERSION_INFO_PREFIX = "";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
DB89BA0725C10FD0008580ED /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEFINES_MODULE = YES;
|
||||||
|
DEVELOPMENT_TEAM = 7LFDZ96332;
|
||||||
|
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||||
|
DYLIB_CURRENT_VERSION = 1;
|
||||||
|
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||||
|
INFOPLIST_FILE = CoreDataStack/Info.plist;
|
||||||
|
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@loader_path/Frameworks",
|
||||||
|
);
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.CoreDataStack;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
VERSIONING_SYSTEM = "apple-generic";
|
||||||
|
VERSION_INFO_PREFIX = "";
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
DB89BA0A25C10FD0008580ED /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
DEVELOPMENT_TEAM = 7LFDZ96332;
|
||||||
|
INFOPLIST_FILE = CoreDataStackTests/Info.plist;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@loader_path/Frameworks",
|
||||||
|
);
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.CoreDataStackTests;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Mastodon.app/Mastodon";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
DB89BA0B25C10FD0008580ED /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
DEVELOPMENT_TEAM = 7LFDZ96332;
|
||||||
|
INFOPLIST_FILE = CoreDataStackTests/Info.plist;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@loader_path/Frameworks",
|
||||||
|
);
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.CoreDataStackTests;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Mastodon.app/Mastodon";
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
/* End XCBuildConfiguration section */
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
/* Begin XCConfigurationList section */
|
/* Begin XCConfigurationList section */
|
||||||
|
@ -819,6 +1238,24 @@
|
||||||
defaultConfigurationIsVisible = 0;
|
defaultConfigurationIsVisible = 0;
|
||||||
defaultConfigurationName = Release;
|
defaultConfigurationName = Release;
|
||||||
};
|
};
|
||||||
|
DB89BA0525C10FD0008580ED /* Build configuration list for PBXNativeTarget "CoreDataStack" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
DB89BA0625C10FD0008580ED /* Debug */,
|
||||||
|
DB89BA0725C10FD0008580ED /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
DB89BA0925C10FD0008580ED /* Build configuration list for PBXNativeTarget "CoreDataStackTests" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
DB89BA0A25C10FD0008580ED /* Debug */,
|
||||||
|
DB89BA0B25C10FD0008580ED /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
/* End XCConfigurationList section */
|
/* End XCConfigurationList section */
|
||||||
|
|
||||||
/* Begin XCRemoteSwiftPackageReference section */
|
/* Begin XCRemoteSwiftPackageReference section */
|
||||||
|
@ -843,6 +1280,19 @@
|
||||||
productName = AlamofireImage;
|
productName = AlamofireImage;
|
||||||
};
|
};
|
||||||
/* End XCSwiftPackageProductDependency section */
|
/* End XCSwiftPackageProductDependency section */
|
||||||
|
|
||||||
|
/* Begin XCVersionGroup section */
|
||||||
|
DB89BA3525C1145C008580ED /* CoreData.xcdatamodeld */ = {
|
||||||
|
isa = XCVersionGroup;
|
||||||
|
children = (
|
||||||
|
DB89BA3625C1145C008580ED /* CoreData.xcdatamodel */,
|
||||||
|
);
|
||||||
|
currentVersion = DB89BA3625C1145C008580ED /* CoreData.xcdatamodel */;
|
||||||
|
path = CoreData.xcdatamodeld;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
versionGroupType = wrapper.xcdatamodel;
|
||||||
|
};
|
||||||
|
/* End XCVersionGroup section */
|
||||||
};
|
};
|
||||||
rootObject = DB427DCA25BAA00100D1B89D /* Project object */;
|
rootObject = DB427DCA25BAA00100D1B89D /* Project object */;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,10 +4,15 @@
|
||||||
<dict>
|
<dict>
|
||||||
<key>SchemeUserState</key>
|
<key>SchemeUserState</key>
|
||||||
<dict>
|
<dict>
|
||||||
|
<key>CoreDataStack.xcscheme_^#shared#^_</key>
|
||||||
|
<dict>
|
||||||
|
<key>orderHint</key>
|
||||||
|
<integer>8</integer>
|
||||||
|
</dict>
|
||||||
<key>Mastodon.xcscheme_^#shared#^_</key>
|
<key>Mastodon.xcscheme_^#shared#^_</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>orderHint</key>
|
<key>orderHint</key>
|
||||||
<integer>5</integer>
|
<integer>9</integer>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
//
|
||||||
|
// NeedsDependency.swift
|
||||||
|
// Mastodon
|
||||||
|
//
|
||||||
|
// Created by Cirno MainasuK on 2021-1-27.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
protocol NeedsDependency: class {
|
||||||
|
var context: AppContext! { get set }
|
||||||
|
var coordinator: SceneCoordinator! { get set }
|
||||||
|
}
|
||||||
|
|
||||||
|
extension UISceneSession {
|
||||||
|
private struct AssociatedKeys {
|
||||||
|
static var sceneCoordinator = "SceneCoordinator"
|
||||||
|
}
|
||||||
|
|
||||||
|
weak var sceneCoordinator: SceneCoordinator? {
|
||||||
|
get {
|
||||||
|
return objc_getAssociatedObject(self, &AssociatedKeys.sceneCoordinator) as? SceneCoordinator
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
objc_setAssociatedObject(self, &AssociatedKeys.sceneCoordinator, newValue, .OBJC_ASSOCIATION_ASSIGN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,124 @@
|
||||||
|
//
|
||||||
|
// SceneCoordinator.swift
|
||||||
|
// Mastodon
|
||||||
|
//
|
||||||
|
// Created by Cirno MainasuK on 2021-1-27.
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import SafariServices
|
||||||
|
|
||||||
|
final public class SceneCoordinator {
|
||||||
|
|
||||||
|
private weak var scene: UIScene!
|
||||||
|
private weak var sceneDelegate: SceneDelegate!
|
||||||
|
private weak var appContext: AppContext!
|
||||||
|
|
||||||
|
let id = UUID().uuidString
|
||||||
|
|
||||||
|
init(scene: UIScene, sceneDelegate: SceneDelegate, appContext: AppContext) {
|
||||||
|
self.scene = scene
|
||||||
|
self.sceneDelegate = sceneDelegate
|
||||||
|
self.appContext = appContext
|
||||||
|
|
||||||
|
scene.session.sceneCoordinator = self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SceneCoordinator {
|
||||||
|
enum Transition {
|
||||||
|
case show // push
|
||||||
|
case showDetail // replace
|
||||||
|
case modal(animated: Bool, completion: (() -> Void)? = nil)
|
||||||
|
case custom(transitioningDelegate: UIViewControllerTransitioningDelegate)
|
||||||
|
case customPush
|
||||||
|
case safariPresent(animated: Bool, completion: (() -> Void)? = nil)
|
||||||
|
case activityViewControllerPresent(animated: Bool, completion: (() -> Void)? = nil)
|
||||||
|
case alertController(animated: Bool, completion: (() -> Void)? = nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Scene {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SceneCoordinator {
|
||||||
|
|
||||||
|
func setup() {
|
||||||
|
let viewController = MainTabBarController(context: appContext, coordinator: self)
|
||||||
|
sceneDelegate.window?.rootViewController = viewController
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
func present(scene: Scene, from sender: UIViewController?, transition: Transition) -> UIViewController? {
|
||||||
|
guard let viewController = get(scene: scene) else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
guard var presentingViewController = sender ?? sceneDelegate.window?.rootViewController?.topMost else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if let mainTabBarController = presentingViewController as? MainTabBarController,
|
||||||
|
let navigationController = mainTabBarController.selectedViewController as? UINavigationController,
|
||||||
|
let topViewController = navigationController.topViewController {
|
||||||
|
presentingViewController = topViewController
|
||||||
|
}
|
||||||
|
|
||||||
|
switch transition {
|
||||||
|
case .show:
|
||||||
|
presentingViewController.show(viewController, sender: sender)
|
||||||
|
|
||||||
|
case .showDetail:
|
||||||
|
let navigationController = UINavigationController(rootViewController: viewController)
|
||||||
|
presentingViewController.showDetailViewController(navigationController, sender: sender)
|
||||||
|
|
||||||
|
case .modal(let animated, let completion):
|
||||||
|
let modalNavigationController = UINavigationController(rootViewController: viewController)
|
||||||
|
if let adaptivePresentationControllerDelegate = viewController as? UIAdaptivePresentationControllerDelegate {
|
||||||
|
modalNavigationController.presentationController?.delegate = adaptivePresentationControllerDelegate
|
||||||
|
}
|
||||||
|
presentingViewController.present(modalNavigationController, animated: animated, completion: completion)
|
||||||
|
|
||||||
|
case .custom(let transitioningDelegate):
|
||||||
|
viewController.modalPresentationStyle = .custom
|
||||||
|
viewController.transitioningDelegate = transitioningDelegate
|
||||||
|
sender?.present(viewController, animated: true, completion: nil)
|
||||||
|
|
||||||
|
case .customPush:
|
||||||
|
// set delegate in view controller
|
||||||
|
assert(sender?.navigationController?.delegate != nil)
|
||||||
|
sender?.navigationController?.pushViewController(viewController, animated: true)
|
||||||
|
|
||||||
|
case .safariPresent(let animated, let completion):
|
||||||
|
presentingViewController.present(viewController, animated: animated, completion: completion)
|
||||||
|
|
||||||
|
case .activityViewControllerPresent(let animated, let completion):
|
||||||
|
presentingViewController.present(viewController, animated: animated, completion: completion)
|
||||||
|
|
||||||
|
case .alertController(let animated, let completion):
|
||||||
|
presentingViewController.present(viewController, animated: animated, completion: completion)
|
||||||
|
}
|
||||||
|
|
||||||
|
return viewController
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private extension SceneCoordinator {
|
||||||
|
|
||||||
|
func get(scene: Scene) -> UIViewController? {
|
||||||
|
let viewController: UIViewController?
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
viewController = nil
|
||||||
|
|
||||||
|
setupDependency(for: viewController as? NeedsDependency)
|
||||||
|
|
||||||
|
return viewController
|
||||||
|
}
|
||||||
|
|
||||||
|
private func setupDependency(for needs: NeedsDependency?) {
|
||||||
|
needs?.context = appContext
|
||||||
|
needs?.coordinator = self
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
//
|
||||||
|
// UIViewController.swift
|
||||||
|
// Mastodon
|
||||||
|
//
|
||||||
|
// Created by Cirno MainasuK on 2021-1-27.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
extension UIViewController {
|
||||||
|
|
||||||
|
/// Returns the top most view controller from given view controller's stack.
|
||||||
|
var topMost: UIViewController? {
|
||||||
|
// presented view controller
|
||||||
|
if let presentedViewController = presentedViewController {
|
||||||
|
return presentedViewController.topMost
|
||||||
|
}
|
||||||
|
|
||||||
|
// UITabBarController
|
||||||
|
if let tabBarController = self as? UITabBarController,
|
||||||
|
let selectedViewController = tabBarController.selectedViewController {
|
||||||
|
return selectedViewController.topMost
|
||||||
|
}
|
||||||
|
|
||||||
|
// UINavigationController
|
||||||
|
if let navigationController = self as? UINavigationController,
|
||||||
|
let visibleViewController = navigationController.visibleViewController {
|
||||||
|
return visibleViewController.topMost
|
||||||
|
}
|
||||||
|
|
||||||
|
// UIPageController
|
||||||
|
if let pageViewController = self as? UIPageViewController,
|
||||||
|
pageViewController.viewControllers?.count == 1 {
|
||||||
|
return pageViewController.viewControllers?.first?.topMost ?? self
|
||||||
|
}
|
||||||
|
|
||||||
|
// child view controller
|
||||||
|
for subview in self.view?.subviews ?? [] {
|
||||||
|
if let childViewController = subview.next as? UIViewController {
|
||||||
|
return childViewController.topMost
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension UIViewController {
|
||||||
|
|
||||||
|
/// https://bluelemonbits.com/2018/08/26/inserting-cells-at-the-top-of-a-uitableview-with-no-scrolling/
|
||||||
|
static func topVisibleTableViewCellIndexPath(in tableView: UITableView, navigationBar: UINavigationBar) -> IndexPath? {
|
||||||
|
let navigationBarRectInTableView = tableView.convert(navigationBar.bounds, from: navigationBar)
|
||||||
|
let navigationBarMaxYPosition = CGPoint(x: 0, y: navigationBarRectInTableView.origin.y + navigationBarRectInTableView.size.height + 1) // +1pt for UIKit cell locate
|
||||||
|
let mostTopVisiableIndexPath = tableView.indexPathForRow(at: navigationBarMaxYPosition)
|
||||||
|
return mostTopVisiableIndexPath
|
||||||
|
}
|
||||||
|
|
||||||
|
static func tableViewCellOriginOffsetToWindowTop(in tableView: UITableView, at indexPath: IndexPath, navigationBar: UINavigationBar) -> CGFloat {
|
||||||
|
let rectForTopRow = tableView.rectForRow(at: indexPath)
|
||||||
|
let navigationBarRectInTableView = tableView.convert(navigationBar.bounds, from: navigationBar)
|
||||||
|
let navigationBarMaxYPosition = CGPoint(x: 0, y: navigationBarRectInTableView.origin.y + navigationBarRectInTableView.size.height) // without +1pt
|
||||||
|
let differenceBetweenTopRowAndNavigationBar = rectForTopRow.origin.y - navigationBarMaxYPosition.y
|
||||||
|
return differenceBetweenTopRowAndNavigationBar
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>com.apple.security.application-groups</key>
|
||||||
|
<array>
|
||||||
|
<string>group.org.joinmastodon.mastodon-temp</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
|
@ -0,0 +1,27 @@
|
||||||
|
//
|
||||||
|
// HomeViewController.swift
|
||||||
|
// Mastodon
|
||||||
|
//
|
||||||
|
// Created by MainasuK Cirno on 2021/1/27.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
final class HomeViewController: UIViewController, NeedsDependency {
|
||||||
|
|
||||||
|
weak var context: AppContext! { willSet { precondition(!isViewLoaded) } }
|
||||||
|
weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extension HomeViewController {
|
||||||
|
|
||||||
|
override func viewDidLoad() {
|
||||||
|
super.viewDidLoad()
|
||||||
|
|
||||||
|
title = "Home"
|
||||||
|
view.backgroundColor = .systemBackground
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
//
|
||||||
|
// MainTabBarController.swift
|
||||||
|
// Mastodon
|
||||||
|
//
|
||||||
|
// Created by Cirno MainasuK on 2021-1-27.
|
||||||
|
//
|
||||||
|
|
||||||
|
import os.log
|
||||||
|
import UIKit
|
||||||
|
import Combine
|
||||||
|
import SafariServices
|
||||||
|
|
||||||
|
class MainTabBarController: UITabBarController {
|
||||||
|
|
||||||
|
var disposeBag = Set<AnyCancellable>()
|
||||||
|
|
||||||
|
weak var context: AppContext!
|
||||||
|
weak var coordinator: SceneCoordinator!
|
||||||
|
|
||||||
|
enum Tab: Int, CaseIterable {
|
||||||
|
case home
|
||||||
|
|
||||||
|
|
||||||
|
var title: String {
|
||||||
|
switch self {
|
||||||
|
case .home: return "Home"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var image: UIImage {
|
||||||
|
switch self {
|
||||||
|
case .home: return UIImage(systemName: "house")!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func viewController(context: AppContext, coordinator: SceneCoordinator) -> UIViewController {
|
||||||
|
let viewController: UIViewController
|
||||||
|
switch self {
|
||||||
|
case .home:
|
||||||
|
let _viewController = HomeViewController()
|
||||||
|
_viewController.context = context
|
||||||
|
_viewController.coordinator = coordinator
|
||||||
|
viewController = _viewController
|
||||||
|
}
|
||||||
|
viewController.title = self.title
|
||||||
|
return UINavigationController(rootViewController: viewController)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init(context: AppContext, coordinator: SceneCoordinator) {
|
||||||
|
self.context = context
|
||||||
|
self.coordinator = coordinator
|
||||||
|
super.init(nibName: nil, bundle: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension MainTabBarController {
|
||||||
|
|
||||||
|
override func viewDidLoad() {
|
||||||
|
super.viewDidLoad()
|
||||||
|
|
||||||
|
view.backgroundColor = .systemBackground
|
||||||
|
|
||||||
|
let tabs = Tab.allCases
|
||||||
|
let viewControllers: [UIViewController] = tabs.map { tab in
|
||||||
|
let viewController = tab.viewController(context: context, coordinator: coordinator)
|
||||||
|
viewController.tabBarItem.title = "" // set text to empty string for image only style (SDK failed to layout when set to nil)
|
||||||
|
viewController.tabBarItem.image = tab.image
|
||||||
|
return viewController
|
||||||
|
}
|
||||||
|
setViewControllers(viewControllers, animated: false)
|
||||||
|
selectedIndex = 0
|
||||||
|
|
||||||
|
// TODO: custom accent color
|
||||||
|
let tabBarAppearance = UITabBarAppearance()
|
||||||
|
tabBarAppearance.configureWithDefaultBackground()
|
||||||
|
tabBar.standardAppearance = tabBarAppearance
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
// selectedIndex = 1
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
//
|
||||||
|
// AppContext.swift
|
||||||
|
// Mastodon
|
||||||
|
//
|
||||||
|
// Created by Cirno MainasuK on 2021-1-27.
|
||||||
|
//
|
||||||
|
|
||||||
|
import os.log
|
||||||
|
import UIKit
|
||||||
|
import Combine
|
||||||
|
import CoreData
|
||||||
|
import CoreDataStack
|
||||||
|
|
||||||
|
class AppContext: ObservableObject {
|
||||||
|
|
||||||
|
var disposeBag = Set<AnyCancellable>()
|
||||||
|
|
||||||
|
@Published var viewStateStore = ViewStateStore()
|
||||||
|
|
||||||
|
let coreDataStack: CoreDataStack
|
||||||
|
let managedObjectContext: NSManagedObjectContext
|
||||||
|
let backgroundManagedObjectContext: NSManagedObjectContext
|
||||||
|
|
||||||
|
|
||||||
|
let documentStore: DocumentStore
|
||||||
|
private var documentStoreSubscription: AnyCancellable!
|
||||||
|
|
||||||
|
let overrideTraitCollection = CurrentValueSubject<UITraitCollection?, Never>(nil)
|
||||||
|
|
||||||
|
init() {
|
||||||
|
let _coreDataStack = CoreDataStack()
|
||||||
|
let _managedObjectContext = _coreDataStack.persistentContainer.viewContext
|
||||||
|
let _backgroundManagedObjectContext = _coreDataStack.persistentContainer.newBackgroundContext()
|
||||||
|
coreDataStack = _coreDataStack
|
||||||
|
managedObjectContext = _managedObjectContext
|
||||||
|
backgroundManagedObjectContext = _backgroundManagedObjectContext
|
||||||
|
|
||||||
|
documentStore = DocumentStore()
|
||||||
|
documentStoreSubscription = documentStore.objectWillChange
|
||||||
|
.receive(on: DispatchQueue.main)
|
||||||
|
.sink { [unowned self] in
|
||||||
|
self.objectWillChange.send()
|
||||||
|
}
|
||||||
|
|
||||||
|
backgroundManagedObjectContext.mergePolicy = NSMergePolicy.mergeByPropertyObjectTrump
|
||||||
|
NotificationCenter.default.publisher(for: .NSManagedObjectContextDidSave, object: backgroundManagedObjectContext)
|
||||||
|
.sink { [weak self] notification in
|
||||||
|
guard let self = self else { return }
|
||||||
|
self.managedObjectContext.perform {
|
||||||
|
self.managedObjectContext.mergeChanges(fromContextDidSave: notification)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.store(in: &disposeBag)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
//
|
||||||
|
// DocumentStore.swift
|
||||||
|
// Mastodon
|
||||||
|
//
|
||||||
|
// Created by Cirno MainasuK on 2021-1-27.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import Combine
|
||||||
|
|
||||||
|
class DocumentStore: ObservableObject { }
|
|
@ -0,0 +1,14 @@
|
||||||
|
//
|
||||||
|
// ViewStateStore.swift
|
||||||
|
// Mastodon
|
||||||
|
//
|
||||||
|
// Created by Cirno MainasuK on 2021-1-27.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Combine
|
||||||
|
|
||||||
|
struct ViewStateStore {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ViewState { }
|
|
@ -10,7 +10,7 @@ import UIKit
|
||||||
@main
|
@main
|
||||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||||
|
|
||||||
|
let appContext = AppContext()
|
||||||
|
|
||||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
||||||
// Override point for customization after application launch.
|
// Override point for customization after application launch.
|
||||||
|
@ -34,3 +34,21 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extension AppDelegate {
|
||||||
|
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
|
||||||
|
#if DEBUG
|
||||||
|
return .all
|
||||||
|
#else
|
||||||
|
return UIDevice.current.userInterfaceIdiom == .pad ? .all : .portrait
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extension AppContext {
|
||||||
|
static var shared: AppContext {
|
||||||
|
let appDelegate = UIApplication.shared.delegate as! AppDelegate
|
||||||
|
return appDelegate.appContext
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,24 +1,33 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
|
||||||
|
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
|
<deployment identifier="iOS"/>
|
||||||
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
|
||||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||||
|
<capability name="System colors in document resources" minToolsVersion="11.0"/>
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<scenes>
|
<scenes>
|
||||||
<!--View Controller-->
|
<!--View Controller-->
|
||||||
<scene sceneID="tne-QT-ifu">
|
<scene sceneID="tne-QT-ifu">
|
||||||
<objects>
|
<objects>
|
||||||
<viewController id="BYZ-38-t0r" customClass="ViewController" customModuleProvider="target" sceneMemberID="viewController">
|
<viewController id="BYZ-38-t0r" sceneMemberID="viewController">
|
||||||
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
|
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
|
||||||
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
|
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
|
||||||
|
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||||
</view>
|
</view>
|
||||||
</viewController>
|
</viewController>
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
||||||
</objects>
|
</objects>
|
||||||
|
<point key="canvasLocation" x="226" y="166"/>
|
||||||
</scene>
|
</scene>
|
||||||
</scenes>
|
</scenes>
|
||||||
|
<resources>
|
||||||
|
<systemColor name="systemBackgroundColor">
|
||||||
|
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
|
</systemColor>
|
||||||
|
</resources>
|
||||||
</document>
|
</document>
|
||||||
|
|
|
@ -10,13 +10,22 @@ import UIKit
|
||||||
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||||
|
|
||||||
var window: UIWindow?
|
var window: UIWindow?
|
||||||
|
var coordinator: SceneCoordinator?
|
||||||
|
|
||||||
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
|
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
|
||||||
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
|
guard let windowScene = scene as? UIWindowScene else { return }
|
||||||
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
|
|
||||||
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
|
let window = UIWindow(windowScene: windowScene)
|
||||||
guard let _ = (scene as? UIWindowScene) else { return }
|
self.window = window
|
||||||
|
|
||||||
|
|
||||||
|
let appContext = AppContext.shared
|
||||||
|
let sceneCoordinator = SceneCoordinator(scene: scene, sceneDelegate: self, appContext: appContext)
|
||||||
|
self.coordinator = sceneCoordinator
|
||||||
|
|
||||||
|
sceneCoordinator.setup()
|
||||||
|
|
||||||
|
window.makeKeyAndVisible()
|
||||||
}
|
}
|
||||||
|
|
||||||
func sceneDidDisconnect(_ scene: UIScene) {
|
func sceneDidDisconnect(_ scene: UIScene) {
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
//
|
|
||||||
// ViewController.swift
|
|
||||||
// Mastodon
|
|
||||||
//
|
|
||||||
// Created by MainasuK Cirno on 2021/1/22.
|
|
||||||
//
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
import MastodonSDK
|
|
||||||
|
|
||||||
class ViewController: UIViewController {
|
|
||||||
|
|
||||||
override func viewDidLoad() {
|
|
||||||
super.viewDidLoad()
|
|
||||||
|
|
||||||
// Do any additional setup after loading the view.
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -9,10 +9,14 @@ import Combine
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
public extension Mastodon.API.App {
|
public extension Mastodon.API.App {
|
||||||
|
|
||||||
static func appEndpointURL(domain: String) -> URL {
|
static func appEndpointURL(domain: String) -> URL {
|
||||||
return Mastodon.API.endpointURL(domain: domain).appendingPathComponent("apps")
|
return Mastodon.API.endpointURL(domain: domain).appendingPathComponent("apps")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Mastodon.API.App {
|
||||||
|
|
||||||
struct Application: Codable {
|
struct Application: Codable {
|
||||||
|
|
||||||
|
|
4
Podfile
4
Podfile
|
@ -1,4 +1,4 @@
|
||||||
platform :ios, '13.0'
|
platform :ios, '14.0'
|
||||||
|
|
||||||
target 'Mastodon' do
|
target 'Mastodon' do
|
||||||
# Comment the next line if you don't want to use dynamic frameworks
|
# Comment the next line if you don't want to use dynamic frameworks
|
||||||
|
@ -7,7 +7,7 @@ target 'Mastodon' do
|
||||||
# Pods for Mastodon
|
# Pods for Mastodon
|
||||||
|
|
||||||
# misc
|
# misc
|
||||||
pod 'SwiftGen', '~> 6.3.0'
|
pod 'SwiftGen', '~> 6.4.0'
|
||||||
pod 'DateToolsSwift', '~> 5.0.0'
|
pod 'DateToolsSwift', '~> 5.0.0'
|
||||||
|
|
||||||
target 'MastodonTests' do
|
target 'MastodonTests' do
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
PODS:
|
PODS:
|
||||||
- DateToolsSwift (5.0.0)
|
- DateToolsSwift (5.0.0)
|
||||||
- SwiftGen (6.3.0)
|
- SwiftGen (6.4.0)
|
||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
- DateToolsSwift (~> 5.0.0)
|
- DateToolsSwift (~> 5.0.0)
|
||||||
- SwiftGen (~> 6.3.0)
|
- SwiftGen (~> 6.4.0)
|
||||||
|
|
||||||
SPEC REPOS:
|
SPEC REPOS:
|
||||||
trunk:
|
trunk:
|
||||||
|
@ -13,8 +13,8 @@ SPEC REPOS:
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
DateToolsSwift: 4207ada6ad615d8dc076323d27037c94916dbfa6
|
DateToolsSwift: 4207ada6ad615d8dc076323d27037c94916dbfa6
|
||||||
SwiftGen: 3d5024a47ea79e408cded20763d7a17d18a4548c
|
SwiftGen: 67860cc7c3cfc2ed25b9b74cfd55495fc89f9108
|
||||||
|
|
||||||
PODFILE CHECKSUM: ed665713fa5980e9fe017a69012b7ec2b15a684f
|
PODFILE CHECKSUM: 5a58ccfd113912468e008313e1c91ed51b7cba20
|
||||||
|
|
||||||
COCOAPODS: 1.10.1
|
COCOAPODS: 1.10.1
|
||||||
|
|
Loading…
Reference in New Issue