Skip to content

Commit a0758c4

Browse files
committed
Sidebar: Add recently visited section
1 parent e95b365 commit a0758c4

File tree

6 files changed

+58
-21
lines changed

6 files changed

+58
-21
lines changed

Packages/Backend/Sources/Backend/User/LocalDataStore.swift

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,34 @@ import Foundation
22
import SwiftUI
33

44
public class LocalDataStore: ObservableObject, PersistentDataStore {
5+
public static let shared = LocalDataStore()
6+
57
@Published public private(set) var favorites: [SubredditSmall] = [] {
68
didSet {
7-
persistData(data: SavedData(favorites: favorites))
9+
saveData()
10+
}
11+
}
12+
13+
@Published public private(set) var recentlyVisited: [SubredditSmall] = [] {
14+
didSet {
15+
saveData()
816
}
917
}
1018

1119
let persistedDataFilename = "redditOsData"
1220
typealias DataType = SavedData
21+
1322
struct SavedData: Codable {
1423
let favorites: [SubredditSmall]
24+
let recentlyVisited: [SubredditSmall]?
1525
}
1626

1727
public init() {
18-
var favorites = restorePersistedData()?.favorites ?? []
28+
let data = restorePersistedData()
29+
var favorites = data?.favorites ?? []
1930
favorites.sort{ $0.name.lowercased() < $1.name.lowercased() }
2031
self.favorites = favorites
32+
self.recentlyVisited = data?.recentlyVisited ?? []
2133
}
2234

2335
// MARK: - Favorites management
@@ -27,11 +39,29 @@ public class LocalDataStore: ObservableObject, PersistentDataStore {
2739
}
2840
}
2941

42+
public func add(recent: SubredditSmall) {
43+
guard !recentlyVisited.contains(recent) else {
44+
return
45+
}
46+
var edit = recentlyVisited
47+
edit.insert(recent, at: 0)
48+
if edit.count > 5 {
49+
edit.removeLast()
50+
}
51+
recentlyVisited = edit
52+
}
53+
3054
public func remove(favorite: SubredditSmall) {
3155
favorites.removeAll(where: { $0 == favorite })
3256
}
3357

3458
public func remove(favoriteNamed: String) {
3559
favorites.removeAll(where: { $0.name == favoriteNamed })
3660
}
61+
62+
// MARK: - Private
63+
64+
private func saveData() {
65+
persistData(data: SavedData(favorites: favorites, recentlyVisited: recentlyVisited))
66+
}
3767
}

RedditOs/Environements/UIState.swift

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,7 @@ class UIState: ObservableObject {
2828
enum Constants {
2929
static let searchTag = "search"
3030
}
31-
32-
init() {
33-
isSearchActive = .constant(false)
34-
isSearchActive = .init(get: {
35-
self.sidebarSelection == Constants.searchTag
36-
}, set: { _ in })
37-
}
38-
31+
3932
@Published var displayToolbarSearchBar = true
4033

4134
@Published var selectedSubreddit: SubredditViewModel?
@@ -51,7 +44,9 @@ class UIState: ObservableObject {
5144
}
5245
}
5346

54-
var isSearchActive: Binding<Bool>
47+
lazy var isSearchActive: Binding<Bool> = .init(get: {
48+
self.sidebarSelection == Constants.searchTag
49+
}, set: { _ in })
5550

5651
@Published var sidebarSelection: String? = DefaultChannels.hot.rawValue {
5752
didSet {

RedditOs/Features/Sidebar/SidebarItem.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import Foundation
99
import SwiftUI
1010

1111
enum SidebarItem: String, CaseIterable, Identifiable, Equatable {
12-
case home, account, favorites, subscription, multi
12+
case home, account, recentlyVisited, favorites, subscription, multi
1313

1414
var id: String {
1515
rawValue
@@ -23,6 +23,8 @@ enum SidebarItem: String, CaseIterable, Identifiable, Equatable {
2323
return "Account"
2424
case .favorites:
2525
return "Favorites"
26+
case .recentlyVisited:
27+
return "Recently Visited"
2628
case .subscription:
2729
return "Subscriptions"
2830
case .multi:

RedditOs/Features/Sidebar/SidebarView.swift

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@ struct SidebarView: View {
1313
@EnvironmentObject private var uiState: UIState
1414
@EnvironmentObject private var localData: LocalDataStore
1515
@EnvironmentObject private var currentUser: CurrentUserStore
16-
17-
@AppStorage(SettingsKey.sidebar_enabled_section) var enabledSections = SidebarItem.allCases.map{ $0.rawValue }
18-
16+
1917
@State private var isSearchPopoverPresented = false
2018
@State private var isHovered = false
2119
@State private var isInEditMode = false
@@ -27,6 +25,7 @@ struct SidebarView: View {
2725
List(selection: $uiState.sidebarSelection) {
2826
mainSection
2927
accountSection
28+
recentlyVisitedSection
3029
favoritesSection
3130
subscriptionSection
3231
multiSection
@@ -150,6 +149,14 @@ struct SidebarView: View {
150149
.animation(.easeInOut)
151150
}
152151

152+
private var recentlyVisitedSection: some View {
153+
Section(header: Text(SidebarItem.recentlyVisited.title())) {
154+
ForEach(localData.recentlyVisited) { reddit in
155+
SidebarSubredditRow(name: reddit.name, iconURL: reddit.iconImg)
156+
}
157+
}
158+
}
159+
153160
@ViewBuilder
154161
private var subscriptionSection: some View {
155162
if currentUser.user != nil, (!currentUser.subscriptions.isEmpty || currentUser.isRefreshingSubscriptions) {

RedditOs/Features/Subreddit/SubredditViewModel.swift

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,15 @@ class SubredditViewModel: ObservableObject {
3030
fetchListings(after: nil)
3131
}
3232
}
33-
@Published var errorLoadingAbout = false
3433

3534
private var postsSearchPublisher: AnyPublisher<ListingResponse<SubredditPost>, Never>?
3635
private var cancellableSet: Set<AnyCancellable> = Set()
3736

38-
init(name: String) {
37+
private let localData: LocalDataStore
38+
39+
init(name: String, localData: LocalDataStore = .shared) {
3940
self.name = name
41+
self.localData = localData
4042

4143
$searchText
4244
.subscribe(on: DispatchQueue.global())
@@ -58,9 +60,10 @@ class SubredditViewModel: ObservableObject {
5860
func fetchAbout() {
5961
Subreddit.fetchAbout(name: name)
6062
.receive(on: DispatchQueue.main)
61-
.sink { [weak self] holder in
62-
self?.errorLoadingAbout = holder == nil
63-
self?.subreddit = holder?.data
63+
.compactMap{ $0?.data }
64+
.sink { [weak self] subreddit in
65+
self?.subreddit = subreddit
66+
self?.localData.add(recent: SubredditSmall.makeSubredditSmall(with: subreddit))
6467
}
6568
.store(in: &cancellableSet)
6669
}

RedditOs/RedditOsApp.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import Backend
1212
@main
1313
struct RedditOsApp: App {
1414
@StateObject private var uiState = UIState()
15-
@StateObject private var localData = LocalDataStore()
15+
@StateObject private var localData = LocalDataStore.shared
1616
private let searchText = QuickSearchState()
1717

1818
@SceneBuilder

0 commit comments

Comments
 (0)