Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into safari-swipe
Browse files Browse the repository at this point in the history
  • Loading branch information
twodayslate committed Sep 14, 2021
2 parents 92253ca + 4877ddb commit 8c62db7
Show file tree
Hide file tree
Showing 7 changed files with 121 additions and 45 deletions.
4 changes: 4 additions & 0 deletions claw.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
objects = {

/* Begin PBXBuildFile section */
F608CD1B26BF598E00F98817 /* GenericArrayFetcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = F608CD1A26BF598E00F98817 /* GenericArrayFetcher.swift */; };
F61CC1BE253676FC00CC7785 /* Font.swift in Sources */ = {isa = PBXBuildFile; fileRef = F61CC1BD253676FC00CC7785 /* Font.swift */; };
F61CC1C4253A876D00CC7785 /* SettingsTextSizeSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = F61CC1C3253A876D00CC7785 /* SettingsTextSizeSlider.swift */; };
F6291164251038810065C3E9 /* CommentHierarchy.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6291163251038810065C3E9 /* CommentHierarchy.swift */; };
Expand Down Expand Up @@ -132,6 +133,7 @@
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
F608CD1A26BF598E00F98817 /* GenericArrayFetcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GenericArrayFetcher.swift; sourceTree = "<group>"; };
F61CC1BD253676FC00CC7785 /* Font.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Font.swift; sourceTree = "<group>"; };
F61CC1C3253A876D00CC7785 /* SettingsTextSizeSlider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsTextSizeSlider.swift; sourceTree = "<group>"; };
F6291163251038810065C3E9 /* CommentHierarchy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommentHierarchy.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -394,6 +396,7 @@
F617B553251EDE0A0060B21A /* User */,
F617B54C251EDDD10060B21A /* Extensions */,
F6876706251A82FE003090D2 /* ShareSheet.swift */,
F608CD1A26BF598E00F98817 /* GenericArrayFetcher.swift */,
F6F2013425D5CCD6008BA024 /* ObservableURL.swift */,
F6E9EDE6251EE0E1005E2B1C /* ImageLoader.swift */,
F6F2015925D63C04008BA024 /* ActiveSheet.swift */,
Expand Down Expand Up @@ -705,6 +708,7 @@
F6E9EDB7251EDF98005E2B1C /* NewestStory.swift in Sources */,
F656F65825252563006FFAFD /* TagStoryFetcher.swift in Sources */,
F687667325141A27003090D2 /* MailView.swift in Sources */,
F608CD1B26BF598E00F98817 /* GenericArrayFetcher.swift in Sources */,
F629118B25105A3E0065C3E9 /* NewestUser.swift in Sources */,
F6E9EE16251EE548005E2B1C /* SettingsLinkView.swift in Sources */,
F6E9EDDB251EE081005E2B1C /* UserFetcher.swift in Sources */,
Expand Down
48 changes: 48 additions & 0 deletions claw/GenericArrayFetcher.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import Foundation
import Combine
import SwiftUI

class GenericArrayFetcher<T: Hashable & Codable>: ObservableObject {
@Published var items = [T]()

@Published var isLoadingMore = false
@Published var isReloading = false

public internal(set) var page: Int = 1
internal var session: URLSessionTask? = nil
internal var moreSession: URLSessionTask? = nil

deinit {
self.session?.cancel()
self.moreSession?.cancel()
}

func loadIfEmpty() {
if self.items.count <= 0 {
self.load()
}
}


func reload() {
self.session?.cancel()
self.moreSession?.cancel()
self.isReloading = true
self.load()
}


func load() {
self.page = 1
self.session?.cancel()
self.moreSession?.cancel()
}

func more(_ item: T? = nil) {
if self.items.last == item && !isLoadingMore {
self.isLoadingMore = true

self.moreSession?.cancel()
}
}
}
4 changes: 2 additions & 2 deletions claw/Stories/Hottest/HottestFetcher.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class HottestFetcher: ObservableObject {
completion?(nil)
}
}else {
print("No Data")
print("No Data for hottest")
completion?(nil) // todo: actually throw an error
}
} catch {
Expand Down Expand Up @@ -84,7 +84,7 @@ class HottestFetcher: ObservableObject {
completion?(nil)
}
}else {
print("No Data")
print("No Data for more hottest")
completion?(nil) // todo: throw actual error
}
} catch {
Expand Down
2 changes: 1 addition & 1 deletion claw/Stories/Story.swift
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ class StoryFetcher: ObservableObject {
}
}
}else {
print("No Data")
print("No Data for story")
}
} catch {
print ("Error fetching story \(error)")
Expand Down
28 changes: 22 additions & 6 deletions claw/Tags/SelectedTagsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,29 @@ struct SelectedTagsView: View {
UserDefaults.standard.set(self.tags, forKey: "selectedTags")
}
}

var body: some View {
TagStoryView(tags: self.tags).navigationBarItems(trailing: NavigationLink(
destination: SelectTagsView(tags: $tags).navigationBarTitle("Selected Tags", displayMode: .inline),
label: {
Text("Edit").bold()
}))
let wrapper = TagStoryView(tags: self.tags)

wrapper.id(self.tags)
.navigationBarItems(leading: NavigationLink(
destination: SelectTagsView(tags: $tags).navigationBarTitle("Selected Tags", displayMode: .inline),
label: {
Text("Edit").bold()
}), trailing: Button(action: {
DispatchQueue.main.async {
wrapper.stories.reload()
}
}, label: {
if wrapper.stories.isReloading {
ProgressView().progressViewStyle(CircularProgressViewStyle())
} else {
Image(systemName: "arrow.clockwise")
}
})).onChange(of: tags, perform: { value in
wrapper.stories.tags = tags
wrapper.stories.load()
})
}
}

Expand Down
68 changes: 37 additions & 31 deletions claw/Tags/TagStoryFetcher.swift
Original file line number Diff line number Diff line change
@@ -1,42 +1,50 @@
import Foundation
import SwiftUI
import Combine

class TagStoryFetcher: ObservableObject {
@Published var stories = TagStoryFetcher.cachedStories
class TagStoryFetcher: GenericArrayFetcher<NewestStory> {

static var cachedStories = [NewestStory]()
static var cachedStories = [[String]: [NewestStory]]()

@Published var isLoadingMore = false


var tags: [String]

init(tags: [String]) {
self.tags = tags
var tags: [String] {
didSet {
self.page = 1
if let cachedStories = TagStoryFetcher.cachedStories[self.tags] {
self.items = cachedStories
} else {
self.items = []
}
}
}

deinit {
self.session?.cancel()
self.moreSession?.cancel()

init(tags: [String] = []) {
self.tags = tags
}

private var session: URLSessionTask? = nil
private var moreSession: URLSessionTask? = nil

func load() {
let url = URL(string: "https://lobste.rs/t/\(self.tags.joined(separator: ",")).json?page=\(self.page)")!

override func load() {
super.load()

if let cachedStories = TagStoryFetcher.cachedStories[self.tags] {
self.items = cachedStories
}

let url = URL(string: "https://lobste.rs/t/\(self.tags.joined(separator: ",")).json?page=\(self.page)")!

self.session = URLSession.shared.dataTask(with: url) {(data,response,error) in
do {
if let d = data {
let decodedLists = try JSONDecoder().decode([NewestStory].self, from: d)
DispatchQueue.main.async {
TagStoryFetcher.cachedStories = decodedLists
self.stories = decodedLists
if TagStoryFetcher.cachedStories.count > 10 {
// xxx: I'd like to remove the last used cache but this will do for now
TagStoryFetcher.cachedStories.removeAll()
}
TagStoryFetcher.cachedStories[self.tags] = decodedLists
self.items = decodedLists
self.page += 1
}
}else {
print("No Data")
print("No Data for tags \(self.tags)")
}
} catch {
print ("Error fetching tag story \(error) \(url)")
Expand All @@ -45,10 +53,8 @@ class TagStoryFetcher: ObservableObject {
self.session?.resume()
}

var page: Int = 1

func more(_ story: NewestStory? = nil) {
if self.stories.last == story && !isLoadingMore {
override func more(_ story: NewestStory? = nil) {
if self.items.last == story && !isLoadingMore {
self.isLoadingMore = true
let url = URL(string: "https://lobste.rs/t/\(self.tags.joined(separator: ",")).json?page=\(self.page)")!

Expand All @@ -59,15 +65,15 @@ class TagStoryFetcher: ObservableObject {
DispatchQueue.main.async {
let stories = decodedLists
for story in stories {
if !self.stories.contains(story) {
self.stories.append(story)
if !self.items.contains(story) {
self.items.append(story)
}
}
TagStoryFetcher.cachedStories = self.stories
TagStoryFetcher.cachedStories[self.tags] = self.items
self.page += 1
}
}else {
print("No Data")
print("No Data for more tags \(self.tags)")
}
} catch {
print ("Error fetching tag story more \(error)")
Expand Down
12 changes: 7 additions & 5 deletions claw/Tags/TagStoryView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ struct TagStoryView: View {
init(tags: [String]) {
self.stories = TagStoryFetcher(tags: tags)
}

@State private var scrollViewContentOffset = CGFloat(0)
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>

Expand All @@ -25,13 +26,13 @@ struct TagStoryView: View {
Divider().id(0).padding(0).padding([.leading])
}

if stories.stories.count <= 0 {
if stories.items.count <= 0 {
ForEach(1..<10) { _ in
StoryListCellView(story: NewestStory.placeholder).environmentObject(settings).redacted(reason: .placeholder).allowsTightening(false)
StoryListCellView(story: NewestStory.placeholder).environmentObject(settings).redacted(reason: .placeholder).allowsTightening(false).disabled(true)
Divider().padding(0).padding([.leading])
}
}
ForEach(stories.stories) { story in
ForEach(stories.items) { story in
StoryListCellView(story: story).id(story).environmentObject(settings).onAppear(perform: {
self.stories.more(story)
})
Expand All @@ -47,10 +48,11 @@ struct TagStoryView: View {
}.onDisappear(perform: {
self.isVisible = false
}).onAppear(perform: {
self.stories.load()
self.stories.loadIfEmpty()
self.tags.loadIfEmpty()
self.isVisible = true
}).navigationBarTitle(self.stories.tags.joined(separator: ", ")).onReceive(didReselect) { _ in
})
.navigationBarTitle(self.stories.tags.joined(separator: ", ")).onReceive(didReselect) { _ in
DispatchQueue.main.async {
if self.isVisible && scrollViewContentOffset > 0.1 {
withAnimation {
Expand Down

0 comments on commit 8c62db7

Please sign in to comment.