Compare commits
No commits in common. "46db70d58ba29f4caef9be29d5c9ecf4ad9f5db3" and "b688631937accf584942972969b731cee8c1dc15" have entirely different histories.
46db70d58b
...
b688631937
|
@ -37,7 +37,6 @@
|
||||||
D61A45E828DF477D002BE511 /* LoadingCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D61A45E728DF477D002BE511 /* LoadingCollectionViewCell.swift */; };
|
D61A45E828DF477D002BE511 /* LoadingCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D61A45E728DF477D002BE511 /* LoadingCollectionViewCell.swift */; };
|
||||||
D61A45EA28DF51EE002BE511 /* TimelineLikeCollectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D61A45E928DF51EE002BE511 /* TimelineLikeCollectionViewController.swift */; };
|
D61A45EA28DF51EE002BE511 /* TimelineLikeCollectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D61A45E928DF51EE002BE511 /* TimelineLikeCollectionViewController.swift */; };
|
||||||
D61ABEF628EE74D400B29151 /* StatusCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D61ABEF528EE74D400B29151 /* StatusCollectionViewCell.swift */; };
|
D61ABEF628EE74D400B29151 /* StatusCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D61ABEF528EE74D400B29151 /* StatusCollectionViewCell.swift */; };
|
||||||
D61ABEFC28F105DE00B29151 /* Pachyderm in Frameworks */ = {isa = PBXBuildFile; productRef = D61ABEFB28F105DE00B29151 /* Pachyderm */; };
|
|
||||||
D61AC1D5232E9FA600C54D2D /* InstanceSelectorTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D61AC1D4232E9FA600C54D2D /* InstanceSelectorTableViewController.swift */; };
|
D61AC1D5232E9FA600C54D2D /* InstanceSelectorTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D61AC1D4232E9FA600C54D2D /* InstanceSelectorTableViewController.swift */; };
|
||||||
D61AC1D8232EA42D00C54D2D /* InstanceTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D61AC1D6232EA42D00C54D2D /* InstanceTableViewCell.swift */; };
|
D61AC1D8232EA42D00C54D2D /* InstanceTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D61AC1D6232EA42D00C54D2D /* InstanceTableViewCell.swift */; };
|
||||||
D61AC1D9232EA42D00C54D2D /* InstanceTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D61AC1D7232EA42D00C54D2D /* InstanceTableViewCell.xib */; };
|
D61AC1D9232EA42D00C54D2D /* InstanceTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D61AC1D7232EA42D00C54D2D /* InstanceTableViewCell.xib */; };
|
||||||
|
@ -215,6 +214,8 @@
|
||||||
D6A6C11525B62E9700298D0F /* CacheExpiry.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6A6C11425B62E9700298D0F /* CacheExpiry.swift */; };
|
D6A6C11525B62E9700298D0F /* CacheExpiry.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6A6C11425B62E9700298D0F /* CacheExpiry.swift */; };
|
||||||
D6A6C11B25B63CEE00298D0F /* MemoryCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6A6C11A25B63CEE00298D0F /* MemoryCache.swift */; };
|
D6A6C11B25B63CEE00298D0F /* MemoryCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6A6C11A25B63CEE00298D0F /* MemoryCache.swift */; };
|
||||||
D6AC956723C4347E008C9946 /* MainSceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6AC956623C4347E008C9946 /* MainSceneDelegate.swift */; };
|
D6AC956723C4347E008C9946 /* MainSceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6AC956623C4347E008C9946 /* MainSceneDelegate.swift */; };
|
||||||
|
D6ACE1AC240C3BAD004EA8E2 /* Ambassador.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D65F613023AE99E000F3CFD3 /* Ambassador.framework */; };
|
||||||
|
D6ACE1AD240C3BAD004EA8E2 /* Embassy.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D65F612D23AE990C00F3CFD3 /* Embassy.framework */; };
|
||||||
D6ADB6E828E8C878009924AB /* PublicTimelineDescriptionCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6ADB6E728E8C878009924AB /* PublicTimelineDescriptionCollectionViewCell.swift */; };
|
D6ADB6E828E8C878009924AB /* PublicTimelineDescriptionCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6ADB6E728E8C878009924AB /* PublicTimelineDescriptionCollectionViewCell.swift */; };
|
||||||
D6ADB6EA28E91C30009924AB /* TimelineStatusCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6ADB6E928E91C30009924AB /* TimelineStatusCollectionViewCell.swift */; };
|
D6ADB6EA28E91C30009924AB /* TimelineStatusCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6ADB6E928E91C30009924AB /* TimelineStatusCollectionViewCell.swift */; };
|
||||||
D6ADB6EC28EA73CB009924AB /* StatusContentContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6ADB6EB28EA73CB009924AB /* StatusContentContainer.swift */; };
|
D6ADB6EC28EA73CB009924AB /* StatusContentContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6ADB6EB28EA73CB009924AB /* StatusContentContainer.swift */; };
|
||||||
|
@ -694,7 +695,8 @@
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
D61ABEFC28F105DE00B29151 /* Pachyderm in Frameworks */,
|
D6ACE1AC240C3BAD004EA8E2 /* Ambassador.framework in Frameworks */,
|
||||||
|
D6ACE1AD240C3BAD004EA8E2 /* Embassy.framework in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
@ -1544,7 +1546,6 @@
|
||||||
);
|
);
|
||||||
name = TuskerUITests;
|
name = TuskerUITests;
|
||||||
packageProductDependencies = (
|
packageProductDependencies = (
|
||||||
D61ABEFB28F105DE00B29151 /* Pachyderm */,
|
|
||||||
);
|
);
|
||||||
productName = TuskerUITests;
|
productName = TuskerUITests;
|
||||||
productReference = D6D4DDEB212518A200E1C4BB /* TuskerUITests.xctest */;
|
productReference = D6D4DDEB212518A200E1C4BB /* TuskerUITests.xctest */;
|
||||||
|
@ -2216,6 +2217,7 @@
|
||||||
MARKETING_VERSION = 2022.1;
|
MARKETING_VERSION = 2022.1;
|
||||||
OTHER_CODE_SIGN_FLAGS = "";
|
OTHER_CODE_SIGN_FLAGS = "";
|
||||||
OTHER_LDFLAGS = "";
|
OTHER_LDFLAGS = "";
|
||||||
|
"OTHER_SWIFT_FLAGS[sdk=iphone*14*]" = "$(inherited) -D SDK_IOS_14";
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = space.vaccor.Tusker;
|
PRODUCT_BUNDLE_IDENTIFIER = space.vaccor.Tusker;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
|
@ -2244,6 +2246,7 @@
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 2022.1;
|
MARKETING_VERSION = 2022.1;
|
||||||
OTHER_CODE_SIGN_FLAGS = "";
|
OTHER_CODE_SIGN_FLAGS = "";
|
||||||
|
"OTHER_SWIFT_FLAGS[sdk=iphone*14*]" = "$(inherited) -D SDK_IOS_14";
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = space.vaccor.Tusker;
|
PRODUCT_BUNDLE_IDENTIFIER = space.vaccor.Tusker;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
|
@ -2259,15 +2262,14 @@
|
||||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
DEVELOPMENT_TEAM = V4WK9KR9U2;
|
DEVELOPMENT_TEAM = HGYVAQA9FW;
|
||||||
INFOPLIST_FILE = TuskerTests/Info.plist;
|
INFOPLIST_FILE = TuskerTests/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
"@loader_path/Frameworks",
|
"@loader_path/Frameworks",
|
||||||
);
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = space.vaccor.Tusker.TuskerTests;
|
PRODUCT_BUNDLE_IDENTIFIER = net.shadowfacts.TuskerTests;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
@ -2281,15 +2283,14 @@
|
||||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
DEVELOPMENT_TEAM = V4WK9KR9U2;
|
DEVELOPMENT_TEAM = HGYVAQA9FW;
|
||||||
INFOPLIST_FILE = TuskerTests/Info.plist;
|
INFOPLIST_FILE = TuskerTests/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
"@loader_path/Frameworks",
|
"@loader_path/Frameworks",
|
||||||
);
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = space.vaccor.Tusker.TuskerTests;
|
PRODUCT_BUNDLE_IDENTIFIER = net.shadowfacts.TuskerTests;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
@ -2302,14 +2303,14 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
DEVELOPMENT_TEAM = V4WK9KR9U2;
|
DEVELOPMENT_TEAM = HGYVAQA9FW;
|
||||||
INFOPLIST_FILE = TuskerUITests/Info.plist;
|
INFOPLIST_FILE = TuskerUITests/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
"@loader_path/Frameworks",
|
"@loader_path/Frameworks",
|
||||||
);
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = space.vaccor.Tusker.TuskerUITests;
|
PRODUCT_BUNDLE_IDENTIFIER = net.shadowfacts.TuskerUITests;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
@ -2322,14 +2323,14 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
DEVELOPMENT_TEAM = V4WK9KR9U2;
|
DEVELOPMENT_TEAM = HGYVAQA9FW;
|
||||||
INFOPLIST_FILE = TuskerUITests/Info.plist;
|
INFOPLIST_FILE = TuskerUITests/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
"@loader_path/Frameworks",
|
"@loader_path/Frameworks",
|
||||||
);
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = space.vaccor.Tusker.TuskerUITests;
|
PRODUCT_BUNDLE_IDENTIFIER = net.shadowfacts.TuskerUITests;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
@ -2482,10 +2483,6 @@
|
||||||
package = D60CFFD924A290BA00D00083 /* XCRemoteSwiftPackageReference "SwiftSoup" */;
|
package = D60CFFD924A290BA00D00083 /* XCRemoteSwiftPackageReference "SwiftSoup" */;
|
||||||
productName = SwiftSoup;
|
productName = SwiftSoup;
|
||||||
};
|
};
|
||||||
D61ABEFB28F105DE00B29151 /* Pachyderm */ = {
|
|
||||||
isa = XCSwiftPackageProductDependency;
|
|
||||||
productName = Pachyderm;
|
|
||||||
};
|
|
||||||
D6552366289870790048A653 /* ScreenCorners */ = {
|
D6552366289870790048A653 /* ScreenCorners */ = {
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
package = D6552365289870790048A653 /* XCRemoteSwiftPackageReference "ScreenCorners" */;
|
package = D6552365289870790048A653 /* XCRemoteSwiftPackageReference "ScreenCorners" */;
|
||||||
|
|
|
@ -19,7 +19,7 @@ class MultiThreadDictionary<Key: Hashable & Sendable, Value: Sendable> {
|
||||||
if #available(iOS 16.0, *) {
|
if #available(iOS 16.0, *) {
|
||||||
self.lock = OSAllocatedUnfairLock(initialState: [:])
|
self.lock = OSAllocatedUnfairLock(initialState: [:])
|
||||||
} else {
|
} else {
|
||||||
self.lock = MutexLock(initialState: [:])
|
self.lock = UnfairLock(initialState: [:])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,41 +65,21 @@ fileprivate protocol Lock<State> {
|
||||||
extension OSAllocatedUnfairLock: Lock {
|
extension OSAllocatedUnfairLock: Lock {
|
||||||
}
|
}
|
||||||
|
|
||||||
// something is wrong with the UnfairLock impl and it results in segv_accerrs
|
// from http://www.russbishop.net/the-law
|
||||||
fileprivate class MutexLock<State>: Lock {
|
fileprivate class UnfairLock<State>: Lock {
|
||||||
|
private var lock: UnsafeMutablePointer<os_unfair_lock>
|
||||||
private var state: State
|
private var state: State
|
||||||
private var lock = NSLock()
|
|
||||||
|
|
||||||
init(initialState: State) {
|
init(initialState: State) {
|
||||||
self.state = initialState
|
self.state = initialState
|
||||||
|
self.lock = .allocate(capacity: 1)
|
||||||
|
self.lock.initialize(to: os_unfair_lock())
|
||||||
}
|
}
|
||||||
|
deinit {
|
||||||
func withLock<R>(_ body: @Sendable (inout State) throws -> R) rethrows -> R where R : Sendable {
|
self.lock.deallocate()
|
||||||
if !lock.lock(before: Date(timeIntervalSinceNow: 1)) {
|
|
||||||
// if we can't acquire the lock after 1 second, something has gone catastrophically wrong
|
|
||||||
fatalError()
|
|
||||||
}
|
}
|
||||||
defer { lock.unlock() }
|
func withLock<R>(_ body: (inout State) throws -> R) rethrows -> R where R: Sendable {
|
||||||
|
os_unfair_lock_lock(lock)
|
||||||
|
defer { os_unfair_lock_unlock(lock) }
|
||||||
return try body(&state)
|
return try body(&state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//// from http://www.russbishop.net/the-law
|
|
||||||
//fileprivate class UnfairLock<State>: Lock {
|
|
||||||
// private var lock: UnsafeMutablePointer<os_unfair_lock>
|
|
||||||
// private var state: State
|
|
||||||
// init(initialState: State) {
|
|
||||||
// self.state = initialState
|
|
||||||
// self.lock = .allocate(capacity: 1)
|
|
||||||
// self.lock.initialize(to: os_unfair_lock())
|
|
||||||
// }
|
|
||||||
// deinit {
|
|
||||||
// self.lock.deinitialize(count: 1)
|
|
||||||
// self.lock.deallocate()
|
|
||||||
// }
|
|
||||||
// func withLock<R>(_ body: (inout State) throws -> R) rethrows -> R where R: Sendable {
|
|
||||||
// os_unfair_lock_lock(lock)
|
|
||||||
// defer { os_unfair_lock_unlock(lock) }
|
|
||||||
// return try body(&state)
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
|
@ -63,6 +63,27 @@ extension TimelineLikeCollectionViewController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func handleEvent(_ event: TimelineLikeController<TimelineItem>.Event) async {
|
||||||
|
switch event {
|
||||||
|
case .addLoadingIndicator:
|
||||||
|
await handleAddLoadingIndicator()
|
||||||
|
case .removeLoadingIndicator:
|
||||||
|
await handleRemoveLoadingIndicator()
|
||||||
|
case .loadAllError(let error, _):
|
||||||
|
await handleLoadAllError(error)
|
||||||
|
case .replaceAllItems(let items, _):
|
||||||
|
await handleReplaceAllItems(items)
|
||||||
|
case .loadNewerError(let error, _):
|
||||||
|
await handleLoadNewerError(error)
|
||||||
|
case .prependItems(let items, _):
|
||||||
|
await handlePrependItems(items)
|
||||||
|
case .loadOlderError(let error, _):
|
||||||
|
await handleLoadOlderError(error)
|
||||||
|
case .appendItems(let items, _):
|
||||||
|
await handleAppendItems(items)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func handleAddLoadingIndicator() async {
|
func handleAddLoadingIndicator() async {
|
||||||
var snapshot = dataSource.snapshot()
|
var snapshot = dataSource.snapshot()
|
||||||
if !snapshot.sectionIdentifiers.contains(.footer) {
|
if !snapshot.sectionIdentifiers.contains(.footer) {
|
||||||
|
|
|
@ -20,14 +20,7 @@ protocol TimelineLikeControllerDelegate<TimelineItem>: AnyObject {
|
||||||
|
|
||||||
func canLoadOlder() async -> Bool
|
func canLoadOlder() async -> Bool
|
||||||
|
|
||||||
func handleAddLoadingIndicator() async
|
func handleEvent(_ event: TimelineLikeController<TimelineItem>.Event) async
|
||||||
func handleRemoveLoadingIndicator() async
|
|
||||||
func handleLoadAllError(_ error: Swift.Error) async
|
|
||||||
func handleReplaceAllItems(_ timelineItems: [TimelineItem]) async
|
|
||||||
func handleLoadNewerError(_ error: Swift.Error) async
|
|
||||||
func handlePrependItems(_ timelineItems: [TimelineItem]) async
|
|
||||||
func handleLoadOlderError(_ error: Swift.Error) async
|
|
||||||
func handleAppendItems(_ timelineItems: [TimelineItem]) async
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "TimelineLikeController")
|
private let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "TimelineLikeController")
|
||||||
|
@ -119,24 +112,7 @@ actor TimelineLikeController<Item> {
|
||||||
|
|
||||||
private func emit(event: Event) async {
|
private func emit(event: Event) async {
|
||||||
precondition(state.canEmit(event: event))
|
precondition(state.canEmit(event: event))
|
||||||
switch event {
|
await delegate.handleEvent(event)
|
||||||
case .addLoadingIndicator:
|
|
||||||
await delegate.handleAddLoadingIndicator()
|
|
||||||
case .removeLoadingIndicator:
|
|
||||||
await delegate.handleRemoveLoadingIndicator()
|
|
||||||
case .loadAllError(let error, _):
|
|
||||||
await delegate.handleLoadAllError(error)
|
|
||||||
case .replaceAllItems(let items, _):
|
|
||||||
await delegate.handleReplaceAllItems(items)
|
|
||||||
case .loadNewerError(let error, _):
|
|
||||||
await delegate.handleLoadNewerError(error)
|
|
||||||
case .prependItems(let items, _):
|
|
||||||
await delegate.handlePrependItems(items)
|
|
||||||
case .loadOlderError(let error, _):
|
|
||||||
await delegate.handleLoadOlderError(error)
|
|
||||||
case .appendItems(let items, _):
|
|
||||||
await delegate.handleAppendItems(items)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum State: Equatable, CustomDebugStringConvertible {
|
enum State: Equatable, CustomDebugStringConvertible {
|
||||||
|
|
|
@ -31,44 +31,4 @@ class TuskerTests: XCTestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func testFuckingLock() {
|
|
||||||
let lock = MutexLock<[Int: Bool]>(initialState: [:])
|
|
||||||
for i in 0..<100 {
|
|
||||||
Thread.detachNewThread {
|
|
||||||
for j in 0..<50_000 {
|
|
||||||
lock.withLock {
|
|
||||||
$0[i * 50_000 + j] = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while true {
|
|
||||||
if lock.withLock({ $0.count }) == 5_000_000 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lock.withLock({ _ in
|
|
||||||
print("WHAT THE FUUUUUUUUUUUUCK")
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fileprivate class MutexLock<State> {
|
|
||||||
private var state: State
|
|
||||||
private var lock = NSLock()
|
|
||||||
|
|
||||||
init(initialState: State) {
|
|
||||||
self.state = initialState
|
|
||||||
}
|
|
||||||
|
|
||||||
func withLock<R>(_ body: @Sendable (inout State) throws -> R) rethrows -> R where R : Sendable {
|
|
||||||
if !lock.lock(before: Date(timeIntervalSinceNow: 1)) {
|
|
||||||
// if we can't acquire the lock after 1 second, something has gone catastrophically wrong
|
|
||||||
fatalError()
|
|
||||||
}
|
|
||||||
defer { lock.unlock() }
|
|
||||||
return try body(&state)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,70 +7,70 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
//import Ambassador
|
import Ambassador
|
||||||
//
|
|
||||||
//fileprivate let notFound = ["error": "Record not found"]
|
fileprivate let notFound = ["error": "Record not found"]
|
||||||
//
|
|
||||||
//extension Router {
|
extension Router {
|
||||||
// func allRoutes() {
|
func allRoutes() {
|
||||||
// instanceRoutes()
|
instanceRoutes()
|
||||||
// accountRoutes()
|
accountRoutes()
|
||||||
// timelineRoutes()
|
timelineRoutes()
|
||||||
// notificationRoutes()
|
notificationRoutes()
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// func instanceRoutes() {
|
func instanceRoutes() {
|
||||||
// self["/api/v1/instance"] = JSONResponse(handler: { (_) in
|
self["/api/v1/instance"] = JSONResponse(handler: { (_) in
|
||||||
// return [
|
return [
|
||||||
// "description": "An instance description",
|
"description": "An instance description",
|
||||||
// "max_toot_chars": 500,
|
"max_toot_chars": 500,
|
||||||
// "thumbnail": "http://localhost:8080/thumbnail.png",
|
"thumbnail": "http://localhost:8080/thumbnail.png",
|
||||||
// "title": "Localhost",
|
"title": "Localhost",
|
||||||
// "uri": "http://localhost:8080",
|
"uri": "http://localhost:8080",
|
||||||
// "version": "2.7.2",
|
"version": "2.7.2",
|
||||||
// "urls": [:]
|
"urls": [:]
|
||||||
// ]
|
]
|
||||||
// })
|
})
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// func accountRoutes() {
|
func accountRoutes() {
|
||||||
// let selfAccount: [String: Any] = [
|
let selfAccount: [String: Any] = [
|
||||||
// "id": "1",
|
"id": "1",
|
||||||
// "username": "admin",
|
"username": "admin",
|
||||||
// "acct": "admin",
|
"acct": "admin",
|
||||||
// "display_name": "Admin Account",
|
"display_name": "Admin Account",
|
||||||
// "locked": false,
|
"locked": false,
|
||||||
// "created_at": "2019-12-31T11:13:42.0Z",
|
"created_at": "2019-12-31T11:13:42.0Z",
|
||||||
// "followers_count": 0,
|
"followers_count": 0,
|
||||||
// "following_count": 0,
|
"following_count": 0,
|
||||||
// "statuses_count": 0,
|
"statuses_count": 0,
|
||||||
// "note": "My profile description.",
|
"note": "My profile description.",
|
||||||
// "url": "http://localhost:8080/users/admin",
|
"url": "http://localhost:8080/users/admin",
|
||||||
// "avatar": "http://localhost:8080/avatar/admin.jpg",
|
"avatar": "http://localhost:8080/avatar/admin.jpg",
|
||||||
// "avatar_static": "http://localhost:8080/avatar/admin.jpg",
|
"avatar_static": "http://localhost:8080/avatar/admin.jpg",
|
||||||
// "header": "http://localhost:8080/header/admin.jpg",
|
"header": "http://localhost:8080/header/admin.jpg",
|
||||||
// "header_static": "http://localhost:8080/header/admin.jpg",
|
"header_static": "http://localhost:8080/header/admin.jpg",
|
||||||
// "emojis": []
|
"emojis": []
|
||||||
// ]
|
]
|
||||||
// self["/api/v1/accounts/verify_credentials"] = JSONResponse(result: selfAccount)
|
self["/api/v1/accounts/verify_credentials"] = JSONResponse(result: selfAccount)
|
||||||
// self["/api/v1/accounts/\\d+/statuses"] = JSONResponse(result: [])
|
self["/api/v1/accounts/\\d+/statuses"] = JSONResponse(result: [])
|
||||||
// self["/api/v1/accounts/(\\d+)"] = DelegatingResponse { (ctx) in
|
self["/api/v1/accounts/(\\d+)"] = DelegatingResponse { (ctx) in
|
||||||
// if ctx.captures[0] == "1" {
|
if ctx.captures[0] == "1" {
|
||||||
// return JSONResponse(result: selfAccount)
|
return JSONResponse(result: selfAccount)
|
||||||
// } else {
|
} else {
|
||||||
// return JSONResponse(statusCode: 404, statusMessage: "Not Found", result: notFound)
|
return JSONResponse(statusCode: 404, statusMessage: "Not Found", result: notFound)
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// func timelineRoutes() {
|
func timelineRoutes() {
|
||||||
// let emptyTimeline: [Any] = []
|
let emptyTimeline: [Any] = []
|
||||||
// self["/api/v1/timelines/home"] = JSONResponse(result: emptyTimeline)
|
self["/api/v1/timelines/home"] = JSONResponse(result: emptyTimeline)
|
||||||
// self["/api/v1/timelines/public"] = JSONResponse(result: emptyTimeline)
|
self["/api/v1/timelines/public"] = JSONResponse(result: emptyTimeline)
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// func notificationRoutes() {
|
func notificationRoutes() {
|
||||||
// let emptyTimeline: [Any] = []
|
let emptyTimeline: [Any] = []
|
||||||
// self["/api/v1/notifications"] = JSONResponse(result: emptyTimeline)
|
self["/api/v1/notifications"] = JSONResponse(result: emptyTimeline)
|
||||||
// }
|
}
|
||||||
//}
|
}
|
||||||
|
|
|
@ -7,23 +7,23 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
//import Ambassador
|
import Ambassador
|
||||||
//
|
|
||||||
//struct DelegatingResponse: WebApp {
|
struct DelegatingResponse: WebApp {
|
||||||
// let handler: (_ ctx: Context) -> WebApp
|
let handler: (_ ctx: Context) -> WebApp
|
||||||
//
|
|
||||||
// func app(_ environ: [String : Any], startResponse: @escaping ((String, [(String, String)]) -> Void), sendBody: @escaping ((Data) -> Void)) {
|
func app(_ environ: [String : Any], startResponse: @escaping ((String, [(String, String)]) -> Void), sendBody: @escaping ((Data) -> Void)) {
|
||||||
// let ctx = Context(environ: environ)
|
let ctx = Context(environ: environ)
|
||||||
// handler(ctx).app(environ, startResponse: startResponse, sendBody: sendBody)
|
handler(ctx).app(environ, startResponse: startResponse, sendBody: sendBody)
|
||||||
// }
|
}
|
||||||
//}
|
}
|
||||||
//
|
|
||||||
//extension DelegatingResponse {
|
extension DelegatingResponse {
|
||||||
// struct Context {
|
struct Context {
|
||||||
// let environ: [String: Any]
|
let environ: [String: Any]
|
||||||
//
|
|
||||||
// var captures: [String] {
|
var captures: [String] {
|
||||||
// environ["ambassador.router_captures"] as? [String] ?? []
|
environ["ambassador.router_captures"] as? [String] ?? []
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
//}
|
}
|
||||||
|
|
|
@ -7,12 +7,12 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
//import Ambassador
|
import Ambassador
|
||||||
//
|
|
||||||
//extension JSONResponse {
|
extension JSONResponse {
|
||||||
// init(statusCode: Int = 200, statusMessage: String = "OK", result: Any) {
|
init(statusCode: Int = 200, statusMessage: String = "OK", result: Any) {
|
||||||
// self.init(statusCode: statusCode, statusMessage: statusMessage, handler: { (_) in
|
self.init(statusCode: statusCode, statusMessage: statusMessage, handler: { (_) in
|
||||||
// return result
|
return result
|
||||||
// })
|
})
|
||||||
// }
|
}
|
||||||
//}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ class ComposeTests: TuskerUITests {
|
||||||
override func setUp() {
|
override func setUp() {
|
||||||
super.setUp()
|
super.setUp()
|
||||||
|
|
||||||
// router.allRoutes()
|
router.allRoutes()
|
||||||
|
|
||||||
app.launchEnvironment["UI_TESTING_LOGIN"] = "true"
|
app.launchEnvironment["UI_TESTING_LOGIN"] = "true"
|
||||||
app.launch()
|
app.launch()
|
||||||
|
|
|
@ -13,7 +13,7 @@ class MyProfileTests: TuskerUITests {
|
||||||
override func setUp() {
|
override func setUp() {
|
||||||
super.setUp()
|
super.setUp()
|
||||||
|
|
||||||
// router.allRoutes()
|
router.allRoutes()
|
||||||
|
|
||||||
app.launchEnvironment["UI_TESTING_LOGIN"] = "true"
|
app.launchEnvironment["UI_TESTING_LOGIN"] = "true"
|
||||||
app.launch()
|
app.launch()
|
||||||
|
|
|
@ -7,14 +7,14 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
import XCTest
|
import XCTest
|
||||||
//import Ambassador
|
import Ambassador
|
||||||
|
|
||||||
class OnboardingTests: TuskerUITests {
|
class OnboardingTests: TuskerUITests {
|
||||||
|
|
||||||
override func setUp() {
|
override func setUp() {
|
||||||
super.setUp()
|
super.setUp()
|
||||||
|
|
||||||
// router.instanceRoutes()
|
router.instanceRoutes()
|
||||||
|
|
||||||
app.launch()
|
app.launch()
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,40 +7,40 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
import XCTest
|
import XCTest
|
||||||
//import Embassy
|
import Embassy
|
||||||
//import Ambassador
|
import Ambassador
|
||||||
|
|
||||||
class TuskerUITests: XCTestCase {
|
class TuskerUITests: XCTestCase {
|
||||||
|
|
||||||
// var eventLoop: EventLoop!
|
var eventLoop: EventLoop!
|
||||||
// var router: Router!
|
var router: Router!
|
||||||
// var server: HTTPServer!
|
var server: HTTPServer!
|
||||||
// var eventLoopThreadCondition: NSCondition!
|
var eventLoopThreadCondition: NSCondition!
|
||||||
// var eventLoopThread: Thread!
|
var eventLoopThread: Thread!
|
||||||
|
|
||||||
var app: XCUIApplication!
|
var app: XCUIApplication!
|
||||||
|
|
||||||
// private func setupWebServer() {
|
private func setupWebServer() {
|
||||||
// eventLoop = try! SelectorEventLoop(selector: try! KqueueSelector())
|
eventLoop = try! SelectorEventLoop(selector: try! KqueueSelector())
|
||||||
// router = Router()
|
router = Router()
|
||||||
// server = DefaultHTTPServer(eventLoop: eventLoop, port: 8080, app: router.app)
|
server = DefaultHTTPServer(eventLoop: eventLoop, port: 8080, app: router.app)
|
||||||
// router["/hello"] = JSONResponse(handler: { (_) in
|
router["/hello"] = JSONResponse(handler: { (_) in
|
||||||
// return ["Hello", "World"]
|
return ["Hello", "World"]
|
||||||
// })
|
})
|
||||||
// try! server.start()
|
try! server.start()
|
||||||
//
|
|
||||||
// eventLoopThreadCondition = NSCondition()
|
eventLoopThreadCondition = NSCondition()
|
||||||
// eventLoopThread = Thread(block: {
|
eventLoopThread = Thread(block: {
|
||||||
// self.eventLoop.runForever()
|
self.eventLoop.runForever()
|
||||||
// self.eventLoopThreadCondition.lock()
|
self.eventLoopThreadCondition.lock()
|
||||||
// self.eventLoopThreadCondition.signal()
|
self.eventLoopThreadCondition.signal()
|
||||||
// self.eventLoopThreadCondition.unlock()
|
self.eventLoopThreadCondition.unlock()
|
||||||
// })
|
})
|
||||||
// eventLoopThread.start()
|
eventLoopThread.start()
|
||||||
// }
|
}
|
||||||
|
|
||||||
override func setUp() {
|
override func setUp() {
|
||||||
// setupWebServer()
|
setupWebServer()
|
||||||
|
|
||||||
continueAfterFailure = false
|
continueAfterFailure = false
|
||||||
app = XCUIApplication()
|
app = XCUIApplication()
|
||||||
|
@ -48,14 +48,14 @@ class TuskerUITests: XCTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
override func tearDown() {
|
override func tearDown() {
|
||||||
// server.stopAndWait()
|
server.stopAndWait()
|
||||||
// eventLoopThreadCondition.lock()
|
eventLoopThreadCondition.lock()
|
||||||
// eventLoop.stop()
|
eventLoop.stop()
|
||||||
// while eventLoop.running {
|
while eventLoop.running {
|
||||||
// if !eventLoopThreadCondition.wait(until: Date(timeIntervalSinceNow: 10)) {
|
if !eventLoopThreadCondition.wait(until: Date(timeIntervalSinceNow: 10)) {
|
||||||
// fatalError("Join eventLoopThread timeout")
|
fatalError("Join eventLoopThread timeout")
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue