mirror of
https://github.com/Ranchero-Software/NetNewsWire
synced 2025-08-12 06:26:36 +00:00
Continue removing ExtensionPoint code. Start fixing build errors.
This commit is contained in:
@@ -1,65 +0,0 @@
|
||||
//
|
||||
// AddExtensionListView.swift
|
||||
// NetNewsWire-iOS
|
||||
//
|
||||
// Created by Stuart Breckenridge on 13/12/2022.
|
||||
// Copyright © 2022 Ranchero Software. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import Accounts
|
||||
|
||||
struct AddExtensionListView: View {
|
||||
|
||||
@State private var availableExtensionPointTypes = ExtensionPointManager.shared.availableExtensionPointTypes.sorted(by: { $0.title < $1.title })
|
||||
@Environment(\.dismiss) var dismiss
|
||||
@State private var showExtensionPointView: (ExtensionPoint.Type?, Bool) = (nil, false)
|
||||
|
||||
var body: some View {
|
||||
NavigationView {
|
||||
List {
|
||||
Section(header: Text("label.text.feed-providers", comment: "Feed Providers"),
|
||||
footer: Text("label.text.feed-providers-explainer", comment: "Feed Providers allow you to subscribe to some pages as if they were RSS feeds")) {
|
||||
ForEach(0..<availableExtensionPointTypes.count, id: \.self) { i in
|
||||
Button {
|
||||
showExtensionPointView = (availableExtensionPointTypes[i], true)
|
||||
} label: {
|
||||
Image(uiImage: availableExtensionPointTypes[i].image)
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(width: 25, height: 25)
|
||||
|
||||
Text("\(availableExtensionPointTypes[i].title)")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.navigationTitle(Text("navigation.title.add-extensions", comment: "Add Extensions"))
|
||||
.sheet(isPresented: $showExtensionPointView.1, content: {
|
||||
if showExtensionPointView.0 != nil {
|
||||
EnableExtensionPointView(extensionPoint: showExtensionPointView.0!)
|
||||
}
|
||||
})
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .navigationBarLeading) {
|
||||
Button(role: .cancel) {
|
||||
dismiss()
|
||||
} label: {
|
||||
Text("button.title.cancel", comment: "Cancel")
|
||||
}
|
||||
}
|
||||
}
|
||||
.onReceive(NotificationCenter.default.publisher(for: .ActiveExtensionPointsDidChange), perform: { _ in
|
||||
dismiss()
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
struct AddExtensionListView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
AddExtensionListView()
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
//
|
||||
// EnableExtensionPointView.swift
|
||||
// NetNewsWire-iOS
|
||||
//
|
||||
// Created by Stuart Breckenridge on 19/12/2022.
|
||||
// Copyright © 2022 Ranchero Software. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct EnableExtensionPointView: View {
|
||||
|
||||
@Environment(\.dismiss) var dismiss
|
||||
@StateObject private var viewModel = EnableExtensionViewModel()
|
||||
@State private var extensionError: (Error?, Bool) = (nil, false)
|
||||
var extensionPoint: ExtensionPoint.Type
|
||||
|
||||
var body: some View {
|
||||
Form {
|
||||
ExtensionSectionHeader(extensionPoint: extensionPoint)
|
||||
Section(footer: extensionExplainer) {}
|
||||
Section { enableButton }
|
||||
}
|
||||
.alert(Text("alert.title.error", comment: "Error"), isPresented: $extensionError.1, actions: {
|
||||
}, message: {
|
||||
Text(verbatim: extensionError.0?.localizedDescription ?? "Unknown Error")
|
||||
})
|
||||
.alert(Text("alert.title.error", comment: "Error"), isPresented: $viewModel.showExtensionError.1, actions: {
|
||||
}, message: {
|
||||
Text(verbatim: viewModel.showExtensionError.0?.localizedDescription ?? "Unknown Error")
|
||||
})
|
||||
.navigationTitle(extensionPoint.title)
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.dismissOnExternalContextLaunch()
|
||||
.onReceive(NotificationCenter.default.publisher(for: .ActiveExtensionPointsDidChange), perform: { _ in
|
||||
dismiss()
|
||||
})
|
||||
.edgesIgnoringSafeArea(.bottom)
|
||||
}
|
||||
|
||||
var extensionExplainer: some View {
|
||||
Text(extensionPoint.description.string)
|
||||
.multilineTextAlignment(.center)
|
||||
}
|
||||
|
||||
var enableButton: some View {
|
||||
Button {
|
||||
Task {
|
||||
viewModel.configure(extensionPoint)
|
||||
do {
|
||||
try await viewModel.enableExtension()
|
||||
} catch {
|
||||
extensionError = (error, true)
|
||||
}
|
||||
}
|
||||
} label: {
|
||||
HStack {
|
||||
Spacer()
|
||||
Text("button.title.enable-extension", comment: "Enable Extension")
|
||||
Spacer()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,183 +0,0 @@
|
||||
//
|
||||
// EnableExtensionViewModel.swift
|
||||
// NetNewsWire-iOS
|
||||
//
|
||||
// Created by Stuart Breckenridge on 19/12/2022.
|
||||
// Copyright © 2022 Ranchero Software. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import AuthenticationServices
|
||||
import Account
|
||||
import OAuthSwift
|
||||
import Secrets
|
||||
import RSCore
|
||||
|
||||
|
||||
public final class EnableExtensionViewModel: NSObject, ObservableObject, OAuthSwiftURLHandlerType, ASWebAuthenticationPresentationContextProviding, Logging {
|
||||
|
||||
@Published public var showExtensionError: (Error?, Bool) = (nil, false)
|
||||
private var extensionPointType: ExtensionPoint.Type?
|
||||
private var oauth: OAuthSwift?
|
||||
private var callbackURL: URL? = nil
|
||||
|
||||
|
||||
func configure(_ extensionPointType: ExtensionPoint.Type) {
|
||||
self.extensionPointType = extensionPointType
|
||||
}
|
||||
|
||||
func enableExtension() async throws {
|
||||
guard let extensionPointType = extensionPointType else { return }
|
||||
if let oauth1 = extensionPointType as? OAuth1SwiftProvider.Type {
|
||||
try await enableOAuth1(oauth1)
|
||||
} else if let oauth2 = extensionPointType as? OAuth2SwiftProvider.Type {
|
||||
try await enableOAuth2(oauth2)
|
||||
} else {
|
||||
try await activateExtensionPoint(extensionPointType)
|
||||
}
|
||||
}
|
||||
|
||||
private func activateExtensionPoint(_ point: ExtensionPoint.Type) async throws {
|
||||
return try await withCheckedThrowingContinuation { continuation in
|
||||
ExtensionPointManager.shared.activateExtensionPoint(point) { result in
|
||||
switch result {
|
||||
case .success(_):
|
||||
continuation.resume()
|
||||
return
|
||||
case .failure(let failure):
|
||||
continuation.resume(throwing: failure)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Enable OAuth
|
||||
private func enableOAuth1(_ provider: OAuth1SwiftProvider.Type) async throws {
|
||||
callbackURL = provider.callbackURL
|
||||
|
||||
let oauth1 = provider.oauth1Swift
|
||||
self.oauth = oauth1
|
||||
oauth1.authorizeURLHandler = self
|
||||
|
||||
return try await withCheckedThrowingContinuation { continuation in
|
||||
oauth1.authorize(withCallbackURL: callbackURL!) { [weak self] result in
|
||||
|
||||
guard let self = self, let extensionPointType = self.extensionPointType else { return }
|
||||
|
||||
switch result {
|
||||
case .success(let tokenSuccess):
|
||||
ExtensionPointManager.shared.activateExtensionPoint(extensionPointType, tokenSuccess: tokenSuccess) { result in
|
||||
switch result {
|
||||
case .success(_):
|
||||
continuation.resume()
|
||||
return
|
||||
case .failure(let failure):
|
||||
continuation.resume(throwing: failure)
|
||||
return
|
||||
}
|
||||
}
|
||||
case .failure(let error):
|
||||
continuation.resume(throwing: error)
|
||||
return
|
||||
}
|
||||
|
||||
self.oauth?.cancel()
|
||||
self.oauth = nil
|
||||
}
|
||||
continuation.resume()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private func enableOAuth2(_ provider: OAuth2SwiftProvider.Type) async throws {
|
||||
|
||||
callbackURL = provider.callbackURL
|
||||
|
||||
let oauth2 = provider.oauth2Swift
|
||||
self.oauth = oauth2
|
||||
oauth2.authorizeURLHandler = self
|
||||
|
||||
let oauth2Vars = provider.oauth2Vars
|
||||
|
||||
return try await withCheckedThrowingContinuation { continuation in
|
||||
oauth2.authorize(withCallbackURL: callbackURL!, scope: oauth2Vars.scope, state: oauth2Vars.state, parameters: oauth2Vars.params) { [weak self] result in
|
||||
guard let self = self, let extensionPointType = self.extensionPointType else { return }
|
||||
|
||||
switch result {
|
||||
case .success(let tokenSuccess):
|
||||
ExtensionPointManager.shared.activateExtensionPoint(extensionPointType, tokenSuccess: tokenSuccess) { [weak self] result in
|
||||
switch result {
|
||||
case .success(_):
|
||||
self?.logger.debug("Enabled extension successfully.")
|
||||
case .failure(let failure):
|
||||
continuation.resume(throwing: failure)
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
case .failure(let oauthSwiftError):
|
||||
continuation.resume(throwing: oauthSwiftError)
|
||||
return
|
||||
}
|
||||
|
||||
self.oauth?.cancel()
|
||||
self.oauth = nil
|
||||
}
|
||||
continuation.resume()
|
||||
}
|
||||
}
|
||||
|
||||
public func handle(_ url: URL) {
|
||||
let session = ASWebAuthenticationSession(url: url, callbackURLScheme: callbackURL!.scheme, completionHandler: { (url, error) in
|
||||
if let callbackedURL = url {
|
||||
OAuth1Swift.handle(url: callbackedURL)
|
||||
}
|
||||
|
||||
guard let error = error else { return }
|
||||
|
||||
self.oauth?.cancel()
|
||||
self.oauth = nil
|
||||
|
||||
DispatchQueue.main.async {
|
||||
//self.dismiss(animated: true, completion: nil)
|
||||
//self.delegate?.dismiss()
|
||||
}
|
||||
|
||||
if case ASWebAuthenticationSessionError.canceledLogin = error {
|
||||
self.logger.debug("Login cancelled.")
|
||||
} else {
|
||||
self.showExtensionError = (error, true)
|
||||
}
|
||||
})
|
||||
|
||||
session.presentationContextProvider = self
|
||||
if !session.start() {
|
||||
logger.debug("Session failed to start!!!")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor {
|
||||
return rootViewController!.view.window!
|
||||
}
|
||||
|
||||
public var rootViewController: UIViewController? {
|
||||
var currentKeyWindow: UIWindow? {
|
||||
UIApplication.shared.connectedScenes
|
||||
.filter { $0.activationState == .foregroundActive }
|
||||
.map { $0 as? UIWindowScene }
|
||||
.compactMap { $0 }
|
||||
.first?.windows
|
||||
.filter { $0.isKeyWindow }
|
||||
.first
|
||||
}
|
||||
|
||||
var rootViewController: UIViewController? {
|
||||
currentKeyWindow?.rootViewController
|
||||
}
|
||||
|
||||
return rootViewController
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
//
|
||||
// ExtensionsManagementView.swift
|
||||
// NetNewsWire-iOS
|
||||
//
|
||||
// Created by Stuart Breckenridge on 30/11/2022.
|
||||
// Copyright © 2022 Ranchero Software. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import Account
|
||||
|
||||
struct ExtensionsManagementView: View {
|
||||
|
||||
@State private var availableExtensionPointTypes = ExtensionPointManager.shared.availableExtensionPointTypes.sorted(by: { $0.title < $1.title })
|
||||
@State private var showAddExtensionView: Bool = false
|
||||
@State private var showDeactivateAlert: Bool = false
|
||||
@State private var extensionToDeactivate: Dictionary<ExtensionPointIdentifer, any ExtensionPoint>.Element? = nil
|
||||
|
||||
var body: some View {
|
||||
List {
|
||||
activeExtensionsSection
|
||||
}
|
||||
.navigationTitle(Text("navigation.title.manage-extensions", comment: " Manage Extensions"))
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .navigationBarTrailing) {
|
||||
Button {
|
||||
showAddExtensionView = true
|
||||
} label: {
|
||||
Image(systemName: "plus")
|
||||
}
|
||||
}
|
||||
}
|
||||
.sheet(isPresented: $showAddExtensionView) {
|
||||
AddExtensionListView()
|
||||
}
|
||||
.alert(Text("alert.title.deactive-extension.\(extensionToDeactivate?.value.extensionPointID.extensionPointType.title ?? "").\(extensionToDeactivate?.value.title ?? "")", comment: "Are you sure you want to deactivate the %@ extension “%@“? Note: the ordering of the variables is extension type, extension name."),
|
||||
isPresented: $showDeactivateAlert) {
|
||||
|
||||
Button(role: .destructive) {
|
||||
ExtensionPointManager.shared.deactivateExtensionPoint(extensionToDeactivate!.value.extensionPointID)
|
||||
} label: {
|
||||
Text("button.title.deactivate-extension", comment: "Deactivate Extension")
|
||||
}
|
||||
|
||||
Button(role: .cancel) {
|
||||
extensionToDeactivate = nil
|
||||
} label: {
|
||||
Text("button.title.cancel", comment: "Button title")
|
||||
}
|
||||
|
||||
} message: {
|
||||
Text("alert.message.cannot-undo-action", comment: "You can't undo this action.")
|
||||
}
|
||||
.onReceive(NotificationCenter.default.publisher(for: .ActiveExtensionPointsDidChange), perform: { _ in
|
||||
availableExtensionPointTypes = ExtensionPointManager.shared.availableExtensionPointTypes.sorted(by: { $0.title < $1.title })
|
||||
})
|
||||
}
|
||||
|
||||
private var activeExtensionsSection: some View {
|
||||
Section(header: Text("label.text.active-extensions", comment: "Active Extensions")) {
|
||||
ForEach(0..<ExtensionPointManager.shared.activeExtensionPoints.count, id: \.self) { i in
|
||||
let point = Array(ExtensionPointManager.shared.activeExtensionPoints)[i]
|
||||
NavigationLink {
|
||||
ExtensionInspectorView(extensionPoint: point.value)
|
||||
} label: {
|
||||
Image(uiImage: point.value.image)
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(width: 25, height: 25)
|
||||
Text(point.value.title)
|
||||
}.swipeActions(edge: .trailing, allowsFullSwipe: false) {
|
||||
Button(role: .destructive) {
|
||||
extensionToDeactivate = point
|
||||
showDeactivateAlert = true
|
||||
} label: {
|
||||
Text("button.title.deactivate-extension", comment: "Deactivate Extension")
|
||||
Image(systemName: "minus.circle")
|
||||
}.tint(.red)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct ExtensionsManagementView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
ExtensionsManagementView()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user