gemenon

[ACTIVE] The Safari of the Gemini ecosystem
git clone git://git.figbert.com/gemenon.git
Log | Files | Refs

commit 6a90ed51d65f0bdda2979def3d3f7021151e520c
parent 9a034ea75b8f270165648446930125915d20d0c5
Author: FIGBERT <figbert@figbert.com>
Date:   Wed, 14 Sep 2022 14:41:33 -0700

Implement more ergonomic Tab class

The new class will make implementing browser functionality (like
traversing history) much easier to implement.

History is no longer de-duplicated. This may return later. I am
undecided on the subject.

Diffstat:
MShared/BrowserFunctions.swift | 50+++++++++++++++++++++++++++++++-------------------
MShared/CapsuleView.swift | 8++++----
MShared/ContentView.swift | 10+++++-----
MShared/HistoryView.swift | 23++++++++++++++++++-----
4 files changed, 58 insertions(+), 33 deletions(-)

diff --git a/Shared/BrowserFunctions.swift b/Shared/BrowserFunctions.swift @@ -11,12 +11,8 @@ import SwiftGemtext @MainActor class BrowserData: ObservableObject { - @Published var url: String = "" - - @Published var history: [URL: Date] = [:] - - @Published var tabs: [UUID: SwiftGemini.GeminiResponse?] = [:] - @Published var currentTab: UUID? = nil // tabs.isEmpty => nil + @Published var url = "" + @Published var tab = Tab() @Published var currentView: GemenonView = .Capsule @Published var views: [GemenonView] = [.Capsule, .History] @@ -27,27 +23,43 @@ class BrowserData: ObservableObject { extension BrowserData { func goToStartPage() { - guard self.currentTab != nil else { return } - self.tabs[self.currentTab!] = nil + guard !self.tab.home else { return } + self.tab = Tab(prev: self.tab) self.url = "" } - func showStartPage() -> Bool { - return self.tabs.isEmpty || self.tabs[self.currentTab!] == nil - } } extension BrowserData { func openURL(_ url: URL) async { - var uuid = UUID() let response = try! await self.engine.request(url) - if self.tabs.count == 1 { - uuid = self.tabs.keys.first! - } - self.tabs[uuid] = response - self.currentTab = uuid - self.history[url] = Date.now - self.currentView = .Capsule + self.tab = Tab(url, prev: self.tab, response: response) self.url = url.absoluteString + self.currentView = .Capsule + } +} + +class Tab: Identifiable { + let id = UUID() + let timestamp = Date.now + + var home: Bool + var url: URL? + var next: Tab? + var prev: Tab? + var response: SwiftGemini.GeminiResponse? + + init() { + self.home = true + } + init(prev: Tab) { + self.home = true + self.prev = prev + } + init(_ url: URL, prev: Tab, response: SwiftGemini.GeminiResponse) { + self.home = false + self.url = url + self.prev = prev + self.response = response } } diff --git a/Shared/CapsuleView.swift b/Shared/CapsuleView.swift @@ -11,15 +11,15 @@ struct CapsuleView: View { @EnvironmentObject var data: BrowserData var body: some View { - if data.tabs.isEmpty { + if data.tab.home { StartPage() } else { ScrollView { HStack { Spacer() - if data.tabs[data.currentTab!]??.body?.gemtext != nil { + if data.tab.response?.body?.gemtext != nil { VStack(alignment: .leading, spacing: 10) { - renderGemtext((data.tabs[data.currentTab!]??.body?.gemtext)!, url: (data.tabs[data.currentTab!]??.url)!) + renderGemtext((data.tab.response?.body?.gemtext)!, url: data.tab.url) } } Spacer() @@ -29,7 +29,7 @@ struct CapsuleView: View { } } - func renderGemtext(_ gemtext: String, url: URL) -> some View { + func renderGemtext(_ gemtext: String, url: URL?) -> some View { ForEach(data.parser.parse(gemtext, url: url), id: \.self) { line in switch line { case .Text(let str): diff --git a/Shared/ContentView.swift b/Shared/ContentView.swift @@ -14,21 +14,21 @@ struct ContentView: View { var body: some View { NavigationSplitView(columnVisibility: $columnVisibility) { - List(data.views, id: \.self, selection: $data.currentView) { s in + List(data.views, id: \.self, selection: $data.currentView) { view in NavigationLink { - switch s { + switch view { case .Capsule: CapsuleView() case .History: HistoryView() } } label: { - switch s { + switch view { case .Capsule: - if data.tabs.isEmpty { + if data.tab.home { Label("Start Page", systemImage: "laptopcomputer") } else { - Label("\(data.tabs.count) Tab\(data.tabs.count > 1 ? "s" : "")", systemImage: "laptopcomputer") + Label("X Tabs", systemImage: "laptopcomputer") } case .History: Label("History", systemImage: "clock") diff --git a/Shared/HistoryView.swift b/Shared/HistoryView.swift @@ -9,21 +9,34 @@ import SwiftUI struct HistoryView: View { @EnvironmentObject var data: BrowserData + @State var tabs: [Tab] = [] var body: some View { List { - ForEach(data.history.sorted(by: { first, second in first.value > second.value }), id: \.value) { url, date in + ForEach(tabs) { tab in HStack { - Link(destination: url) { Text(url.absoluteString) } + Link(destination: tab.url!) { Text(tab.url?.absoluteString ?? "error") } Spacer() - if date.timeIntervalSince(.now) <= -1*60*60*24 { - Text(date.formatted(date: .long, time: .complete)) + if tab.timestamp.timeIntervalSince(.now) <= -1*60*60*24 { + Text(tab.timestamp.formatted(date: .long, time: .complete)) } else { - Text(date.formatted(date: .omitted, time: .complete)) + Text(tab.timestamp.formatted(date: .omitted, time: .complete)) } } } } + .onAppear { + appendToURLs(data.tab, list: &tabs) + } + } + + func appendToURLs(_ tab: Tab, list: inout [Tab]) { + if !tab.home { + list.append(tab) + } + if tab.prev != nil { + appendToURLs(tab.prev!, list: &list) + } } }