From 039460803897a8df53ba2f9114d8e655f4835119 Mon Sep 17 00:00:00 2001 From: Lumaa Date: Thu, 4 Apr 2024 18:46:38 +0200 Subject: [PATCH] Timelines, AboutView, URLs and a lot more --- Threaded/Data/Navigator.swift | 77 +++++++++++++++++-------- Threaded/Localizable.xcstrings | 77 +++++++++++++++++++++++-- Threaded/Views/AccountView.swift | 5 ++ Threaded/Views/ContentView.swift | 8 +-- Threaded/Views/DiscoveryView.swift | 6 ++ Threaded/Views/NotificationsView.swift | 6 ++ Threaded/Views/Settings/AboutView.swift | 53 ++++++++++++----- Threaded/Views/TimelineView.swift | 6 ++ 8 files changed, 187 insertions(+), 51 deletions(-) diff --git a/Threaded/Data/Navigator.swift b/Threaded/Data/Navigator.swift index b49808d..4a8805e 100644 --- a/Threaded/Data/Navigator.swift +++ b/Threaded/Data/Navigator.swift @@ -10,40 +10,67 @@ public class Navigator: ObservableObject { public var presentedCover: SheetDestination? public var selectedTab: TabDestination = .timeline + public var client: Client? + public func navigate(to: RouterDestination) { path.append(to) } + public func handle(url: URL) -> OpenURLAction.Result { + guard let client = self.client else { return .systemAction } + let path: String = url.absoluteString.replacingOccurrences(of: AppInfo.scheme, with: "") // remove all path + let urlPath: URL = URL(string: path)! + + let server: String = urlPath.host() ?? client.server + let lastIndex = urlPath.pathComponents.count - 1 + + let actionType = urlPath.pathComponents[lastIndex - 1] + + if client.isAuth && client.hasConnection(with: url) { + if urlPath.lastPathComponent.starts(with: "@") { + Task { + do { + print("\(urlPath.lastPathComponent)@\(server.replacingOccurrences(of: "www.", with: ""))") + let search: SearchResults = try await client.get(endpoint: Search.search(query: "\(urlPath.lastPathComponent)@\(server.replacingOccurrences(of: "www.", with: ""))", type: "accounts", offset: nil, following: nil), forceVersion: .v2) + print(search) + let acc: Account = search.accounts.first ?? .placeholder() + self.navigate(to: .account(acc: acc)) + } catch { + print(error) + } + } + return OpenURLAction.Result.handled + } else { + self.presentedSheet = .safari(url: url) + } + } else { + Task { + do { + let connections: [String] = try await client.get(endpoint: Instances.peers) + client.addConnections(connections) + + + if client.hasConnection(with: url) { + _ = self.handle(url: url) + } else { + self.presentedSheet = .safari(url: url) + } + } catch { + self.presentedSheet = .safari(url: url) + } + } + + return OpenURLAction.Result.handled + } + return OpenURLAction.Result.handled + } + public func removeSettingsOfPath() { self.path = self.path.filter({ !RouterDestination.allSettings.contains($0) }) } } -public class UniversalNavigator: Navigator { - public var client: Client? - - public func handle(url: URL) -> OpenURLAction.Result { - guard let client = self.client else { return .systemAction } - let path: String = url.absoluteString.replacingOccurrences(of: AppInfo.scheme, with: "") // remove all path - let urlPath: URL = URL(string: path)! - - if client.isAuth && client.hasConnection(with: url) { - if urlPath.lastPathComponent.starts(with: "@") { - Task { - do { - let search: SearchResults = try await client.get(endpoint: Search.search(query: urlPath.lastPathComponent, type: "accounts", offset: nil, following: nil), forceVersion: .v2) - let acc: Account = search.accounts.first ?? .placeholder() - self.navigate(to: .account(acc: acc)) - } catch { - print(error) - } - } - } - } - - return .handled - } -} +public class UniversalNavigator: Navigator {} public enum TabDestination: Identifiable { case timeline diff --git a/Threaded/Localizable.xcstrings b/Threaded/Localizable.xcstrings index 7195480..fd1fb52 100644 --- a/Threaded/Localizable.xcstrings +++ b/Threaded/Localizable.xcstrings @@ -3447,19 +3447,84 @@ } }, "timeline.federated" : { - + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Federated" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fédéré" + } + } + } }, "timeline.home" : { - + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Home" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Accueil" + } + } + } }, "timeline.latest" : { - + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Latest" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Récent" + } + } + } }, "timeline.local" : { - + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Local" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Local" + } + } + } }, "timeline.trending" : { - + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Trending" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tendance" + } + } + } }, "tip.headline.meta" : { "extractionState" : "manual", @@ -3579,4 +3644,4 @@ } }, "version" : "1.0" -} +} \ No newline at end of file diff --git a/Threaded/Views/AccountView.swift b/Threaded/Views/AccountView.swift index ead10b3..9146b4d 100644 --- a/Threaded/Views/AccountView.swift +++ b/Threaded/Views/AccountView.swift @@ -16,6 +16,11 @@ struct AccountView: View { account = accountManager.forceAccount() } } + .environment(\.openURL, OpenURLAction { url in + // Open internal URL. + let handled = navigator.handle(url: url) + return handled + }) .environmentObject(navigator) } } diff --git a/Threaded/Views/ContentView.swift b/Threaded/Views/ContentView.swift index 14adfa6..6af99e0 100644 --- a/Threaded/Views/ContentView.swift +++ b/Threaded/Views/ContentView.swift @@ -71,16 +71,10 @@ struct ContentView: View { _ = HuggingFace.getToken() } - .environment(\.openURL, OpenURLAction { url in - // Open internal URL. - guard preferences.browserType == .inApp else { return .systemAction } -// let handled = uniNavigator.handle(url: url) - return OpenURLAction.Result.handled - }) .onOpenURL(perform: { url in guard preferences.browserType == .inApp else { return } uniNavigator.presentedSheet = .safari(url: url) -// let handled = uniNavigator.handle(url: url) + let handled = uniNavigator.handle(url: url) }) } diff --git a/Threaded/Views/DiscoveryView.swift b/Threaded/Views/DiscoveryView.swift index e7a4b1b..4dcc43e 100644 --- a/Threaded/Views/DiscoveryView.swift +++ b/Threaded/Views/DiscoveryView.swift @@ -91,6 +91,12 @@ struct DiscoveryView: View { .withAppRouter(navigator) .navigationTitle(Text("discovery")) } + .environment(\.openURL, OpenURLAction { url in + // Open internal URL. +// guard preferences.browserType == .inApp else { return .systemAction } + let handled = navigator.handle(url: url) + return handled + }) .environmentObject(navigator) .task { await fetchTrending() diff --git a/Threaded/Views/NotificationsView.swift b/Threaded/Views/NotificationsView.swift index 026761f..39cb16c 100644 --- a/Threaded/Views/NotificationsView.swift +++ b/Threaded/Views/NotificationsView.swift @@ -94,6 +94,12 @@ struct NotificationsView: View { } } } + .environment(\.openURL, OpenURLAction { url in + // Open internal URL. +// guard preferences.browserType == .inApp else { return .systemAction } + let handled = navigator.handle(url: url) + return handled + }) .environmentObject(navigator) .task { loadingNotifs = true diff --git a/Threaded/Views/Settings/AboutView.swift b/Threaded/Views/Settings/AboutView.swift index de327ea..dad822a 100644 --- a/Threaded/Views/Settings/AboutView.swift +++ b/Threaded/Views/Settings/AboutView.swift @@ -3,14 +3,15 @@ import SwiftUI struct AboutView: View { - @ObservedObject private var userPreferences: UserPreferences = .defaultPreferences + @Environment(AppDelegate.self) private var appDelegate: AppDelegate @EnvironmentObject private var navigator: Navigator + @ObservedObject private var userPreferences: UserPreferences = .defaultPreferences var body: some View { List { Section(footer: Text("about.version-\(AppInfo.appVersion)")) { NavigationLink { - ComingSoonView() + aboutApp } label: { Text("about.app") } @@ -47,18 +48,44 @@ struct AboutView: View { } var aboutApp: some View { - // TODO: Change this entire ugly thing - List { - Text("about.app.details") - .multilineTextAlignment(.leading) - .listRowThreaded() - Text("about.app.third-party") - .multilineTextAlignment(.leading) - .listRowThreaded() + ScrollView { + VStack(alignment: .center) { + Image("HeroIcon") + .resizable() + .scaledToFit() + .frame(height: 100) + + Text(String("Threaded")) + .font(.title.bold()) + + Text(String("© Lumaa 2023-2024")) + .font(.caption) + .foregroundStyle(Color.gray) + + Spacer() + .frame(height: 40) + + Text("about.app.details") + .multilineTextAlignment(.leading) + .frame(width: appDelegate.windowWidth - 50) + .padding() + .background(Material.bar) + .clipShape(.rect(cornerRadius: 7.5)) + + Spacer() + .frame(height: 10) + + Text("about.app.third-party") + .multilineTextAlignment(.leading) + .frame(width: appDelegate.windowWidth - 50) + .padding() + .background(Material.bar) + .clipShape(.rect(cornerRadius: 7.5)) + } + .padding() } - .padding(.horizontal) - .listThreaded(tint: Color.blue) + .background(Color("AppBackground")) .navigationTitle("about.app") - .navigationBarTitleDisplayMode(.large) + .navigationBarTitleDisplayMode(.inline) } } diff --git a/Threaded/Views/TimelineView.swift b/Threaded/Views/TimelineView.swift index 365a714..fab7438 100644 --- a/Threaded/Views/TimelineView.swift +++ b/Threaded/Views/TimelineView.swift @@ -158,6 +158,12 @@ struct TimelineView: View { } } } + .environment(\.openURL, OpenURLAction { url in + // Open internal URL. +// guard preferences.browserType == .inApp else { return .systemAction } + let handled = navigator.handle(url: url) + return handled + }) .environmentObject(navigator) .background(Color.appBackground) .toolbarBackground(Color.appBackground, for: .navigationBar)