parent
fe32356bce
commit
8bd6f53f01
@ -0,0 +1,129 @@
|
||||
//
|
||||
// PinnedTimeline.swift
|
||||
// Tusker
|
||||
//
|
||||
// Created by Shadowfacts on 1/27/23.
|
||||
// Copyright © 2023 Shadowfacts. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import Pachyderm
|
||||
|
||||
enum PinnedTimeline: Codable, Equatable, Hashable {
|
||||
case home
|
||||
case `public`(local: Bool)
|
||||
case tag(hashtag: String)
|
||||
case list(id: String)
|
||||
case instance(URL)
|
||||
|
||||
init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
let type = try container.decode(String.self, forKey: .type)
|
||||
switch type {
|
||||
case "home":
|
||||
self = .home
|
||||
case "public":
|
||||
self = .public(local: try container.decode(Bool.self, forKey: .local))
|
||||
case "tag":
|
||||
self = .tag(hashtag: try container.decode(String.self, forKey: .hashtag))
|
||||
case "list":
|
||||
self = .list(id: try container.decode(String.self, forKey: .listID))
|
||||
case "instance":
|
||||
self = .instance(try container.decode(URL.self, forKey: .instanceURL))
|
||||
default:
|
||||
throw DecodingError.dataCorruptedError(forKey: CodingKeys.type, in: container, debugDescription: "PinnedTimeline type must be one of 'home', 'local', 'tag', 'list', or 'instance'")
|
||||
}
|
||||
}
|
||||
|
||||
func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
switch self {
|
||||
case .home:
|
||||
try container.encode("home", forKey: .type)
|
||||
case .public(let local):
|
||||
try container.encode("public", forKey: .type)
|
||||
try container.encode(local, forKey: .local)
|
||||
case .tag(let hashtag):
|
||||
try container.encode("tag", forKey: .type)
|
||||
try container.encode(hashtag, forKey: .hashtag)
|
||||
case .list(let id):
|
||||
try container.encode("list", forKey: .type)
|
||||
try container.encode(id, forKey: .listID)
|
||||
case .instance(let url):
|
||||
try container.encode("instance", forKey: .type)
|
||||
try container.encode(url, forKey: .instanceURL)
|
||||
}
|
||||
}
|
||||
|
||||
init?(timeline: Timeline) {
|
||||
switch timeline {
|
||||
case .home:
|
||||
self = .home
|
||||
case .public(let local):
|
||||
self = .public(local: local)
|
||||
case .tag(let hashtag):
|
||||
self = .tag(hashtag: hashtag)
|
||||
case .list(let id):
|
||||
self = .list(id: id)
|
||||
case .direct:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
var timeline: Timeline? {
|
||||
switch self {
|
||||
case .home:
|
||||
return .home
|
||||
case .public(let local):
|
||||
return .public(local: local)
|
||||
case .tag(let hashtag):
|
||||
return .tag(hashtag: hashtag)
|
||||
case .list(let id):
|
||||
return .list(id: id)
|
||||
case .instance(_):
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
var title: String {
|
||||
switch self {
|
||||
case .home:
|
||||
return "Home"
|
||||
case let .public(local):
|
||||
return local ? "Local" : "Federated"
|
||||
case let .tag(hashtag):
|
||||
return "#\(hashtag)"
|
||||
case .list:
|
||||
return "List"
|
||||
case .instance(let url):
|
||||
return url.host!
|
||||
}
|
||||
}
|
||||
|
||||
var image: UIImage {
|
||||
switch self {
|
||||
case .home:
|
||||
return UIImage(systemName: "house.fill")!
|
||||
case let .public(local):
|
||||
if local {
|
||||
return UIImage(systemName: "person.and.person.fill")!
|
||||
} else {
|
||||
return UIImage(systemName: "globe")!
|
||||
}
|
||||
case .list(id: _):
|
||||
return UIImage(systemName: "list.bullet")!
|
||||
case .tag(hashtag: _):
|
||||
return UIImage(systemName: "number")!
|
||||
case .instance(_):
|
||||
return UIImage(systemName: "globe")!
|
||||
}
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case type
|
||||
case local
|
||||
case hashtag
|
||||
case listID
|
||||
case instanceURL
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
//
|
||||
// AddInstancePinnedTimelineView.swift
|
||||
// Tusker
|
||||
//
|
||||
// Created by Shadowfacts on 1/27/23.
|
||||
// Copyright © 2023 Shadowfacts. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import Pachyderm
|
||||
|
||||
struct AddInstancePinnedTimelineView: UIViewControllerRepresentable {
|
||||
typealias UIViewControllerType = UINavigationController
|
||||
|
||||
@Binding var pinnedTimelines: [PinnedTimeline]
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
|
||||
func makeUIViewController(context: Context) -> UINavigationController {
|
||||
let vc = InstanceSelectorTableViewController()
|
||||
vc.title = "Add Instance"
|
||||
vc.delegate = context.coordinator
|
||||
vc.navigationItem.leftBarButtonItem = UIBarButtonItem(systemItem: .cancel, primaryAction: UIAction(handler: { _ in
|
||||
dismiss()
|
||||
}))
|
||||
return UINavigationController(rootViewController: vc)
|
||||
}
|
||||
|
||||
func updateUIViewController(_ uiViewController: UINavigationController, context: Context) {
|
||||
}
|
||||
|
||||
func makeCoordinator() -> Coordinator {
|
||||
let coordinator = Coordinator()
|
||||
coordinator.didSelect = {
|
||||
pinnedTimelines.append(.instance($0))
|
||||
dismiss()
|
||||
}
|
||||
return coordinator
|
||||
}
|
||||
|
||||
class Coordinator: InstanceSelectorTableViewControllerDelegate {
|
||||
var didSelect: ((URL) -> Void)?
|
||||
|
||||
func didSelectInstance(url: URL) {
|
||||
didSelect?(url)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
//
|
||||
// PinnedTimelineTests.swift
|
||||
// TuskerTests
|
||||
//
|
||||
// Created by Shadowfacts on 1/27/23.
|
||||
// Copyright © 2023 Shadowfacts. All rights reserved.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
@testable import Tusker
|
||||
import Pachyderm
|
||||
|
||||
final class PinnedTimelineTests: XCTestCase {
|
||||
|
||||
func testDecodeFromTimeline() throws {
|
||||
let timeline = Timeline.public(local: false)
|
||||
let data = try JSONEncoder().encode(timeline)
|
||||
let decoded = try JSONDecoder().decode(PinnedTimeline.self, from: data)
|
||||
switch decoded {
|
||||
case .public(local: false):
|
||||
break
|
||||
default:
|
||||
XCTFail()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in new issue