Skip to content

Commit

Permalink
#1899 (dashboard)
Browse files Browse the repository at this point in the history
- Populating the dashboard data.
- Loading each folder/feed stories.
- And more work in progress.
- Switched back to Swift 5; Swift 6 isn’t ready for prime time yet (changing rapidly, several Apple APIs that don’t fully support it).
  • Loading branch information
Dejal committed Nov 5, 2024
1 parent 0b900ed commit 2bf7f9a
Show file tree
Hide file tree
Showing 8 changed files with 135 additions and 14 deletions.
32 changes: 28 additions & 4 deletions clients/ios/Classes/DashList.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,36 @@ import Foundation
/// A list in the Dashboard.
@MainActor class DashList: Identifiable {
var index: Int
var feed: Feed

enum Side: String {
case left
case right
}

var side: Side
var order: Int

var feedId: String?
var folder: String

var feed: Feed?
var stories = [Story]()

init(index: Int, feed: Feed, stories: [Story] = [Story]()) {
var isLoaded: Bool {
return feed != nil
}

init(index: Int, side: Side, order: Int, feedId: String?, folder: String) {
self.index = index
self.feed = feed
self.stories = stories
self.side = side
self.order = order
self.feedId = feedId
self.folder = folder
}
}

extension DashList: @preconcurrency CustomStringConvertible {
var description: String {
return "DashList index: \(index), side: \(side), order: \(order), folder: \(folder), feed: \(feedId ?? "none"); \(feed != nil ? "\(feed?.name ?? "?"), stories: \(stories.count)" : "not loaded")"
}
}
4 changes: 2 additions & 2 deletions clients/ios/Classes/FeedDetailDashListView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,14 @@ struct DashListHeaderView: View {
HStack {
Spacer()

if let feedImage = dash.feed.image {
if let feedImage = dash.feed?.image {
Image(uiImage: feedImage)
.resizable()
.frame(width: 16, height: 16)
.padding(.leading, cache.settings.spacing == .compact ? 20 : 24)
}

Text(dash.feed.name)
Text(dash.feed?.name ?? "Loading…")
.lineLimit(1)
.foregroundColor(Color.themed([0x404040, 0x404040, 0xC0C0C0, 0xB0B0B0]))

Expand Down
4 changes: 4 additions & 0 deletions clients/ios/Classes/FeedDetailObjCViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -1332,6 +1332,10 @@ - (void)finishedLoadingFeed:(NSDictionary *)results feedPage:(NSInteger)feedPage
}
#endif

if (self.dashboardIndex >= 0) {
[appDelegate.feedsViewController loadDashboard];
}

self.pageFinished = NO;
[self renderStories:confirmedNewStories];

Expand Down
17 changes: 16 additions & 1 deletion clients/ios/Classes/FeedsObjCViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -1028,6 +1028,14 @@ - (void)loadOfflineFeeds:(BOOL)failed {
}];
}

- (void)clearDashboard {
@throw [NSException exceptionWithName:@"Missing clearDashboard implementation" reason:@"This is implemented in the Swift subclass, so should never reach here." userInfo:nil];
}

- (void)loadDashboard {
@throw [NSException exceptionWithName:@"Missing loadDashboard implementation" reason:@"This is implemented in the Swift subclass, so should never reach here." userInfo:nil];
}

- (void)loadNotificationStory {
@throw [NSException exceptionWithName:@"Missing loadNotificationStory implementation" reason:@"This is implemented in the Swift subclass, so should never reach here." userInfo:nil];
}
Expand Down Expand Up @@ -1690,6 +1698,8 @@ - (void)tableView:(UITableView *)tableView

[[tableView cellForRowAtIndexPath:indexPath] setNeedsDisplay];

[self clearDashboard];

if (searchFolder != nil) {
[appDelegate loadRiverFeedDetailView:appDelegate.feedDetailViewController withFolder:searchFolder];
} else {
Expand Down Expand Up @@ -1982,7 +1992,12 @@ - (void)didSelectSectionHeaderWithTag:(NSInteger)tag {
folder = [NSString stringWithFormat:@"%ld", (long)tag];
}

[appDelegate loadRiverFeedDetailView:appDelegate.feedDetailViewController withFolder:folder];
if ([folder isEqualToString:@"dashboard"]) {
[self loadDashboard];
} else {
[self clearDashboard];
[appDelegate loadRiverFeedDetailView:appDelegate.feedDetailViewController withFolder:folder];
}

if (!appDelegate.isPhone) {
[appDelegate.feedDetailViewController viewWillAppear:NO];
Expand Down
31 changes: 31 additions & 0 deletions clients/ios/Classes/FeedsViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,37 @@ class FeedsViewController: FeedsObjCViewController {
return parentTitles
}

@objc func clearDashboard() {
appDelegate.feedDetailViewController.dashboardIndex = -1
appDelegate.detailViewController.storyTitlesInDashboard = false
}

@objc func loadDashboard() {
if appDelegate.feedDetailViewController.dashboardIndex >= 0 {
appDelegate.feedDetailViewController.storyCache.reloadDashboard(for: appDelegate.feedDetailViewController.dashboardIndex)
}

appDelegate.feedDetailViewController.dashboardIndex += 1
appDelegate.detailViewController.storyTitlesInDashboard = true

let index = appDelegate.feedDetailViewController.dashboardIndex

if index == 0 {
appDelegate.feedDetailViewController.storyCache.prepareDashboard()
} else if index >= appDelegate.dashboardArray.count {
// Done.
return
}

let dash = appDelegate.feedDetailViewController.storyCache.dashboard[index]

if let feed = dash.feedId {
appDelegate.loadFolder(dash.folder, feedID: feed)
} else {
appDelegate.loadRiverFeedDetailView(appDelegate.feedDetailViewController, withFolder: dash.folder)
}
}

var loadWorkItem: DispatchWorkItem?

@objc func loadNotificationStory() {
Expand Down
32 changes: 27 additions & 5 deletions clients/ios/Classes/StoryCache.swift
Original file line number Diff line number Diff line change
Expand Up @@ -135,19 +135,41 @@ import Foundation
}
}

func reloadDashboard(for index: Int) {
if index == 0 {
dashboard.removeAll()
func prepareDashboard() {
dashboard.removeAll()

guard let dashboardArray = appDelegate.dashboardArray as? [[String : Any]] else {
return
}

for (index, dashInfo) in dashboardArray.enumerated() {
guard let dashId = dashInfo["river_id"] as? String,
let order = dashInfo["river_order"] as? Int,
let sideString = dashInfo["river_side"] as? String, let side = DashList.Side(rawValue: sideString) else {
continue
}

let feedId = dashId.hasPrefix("feed:") ? dashId.deletingPrefix("feed:") : nil
guard let folder = dashId == "river:" ? "everything" : dashId.hasPrefix("river:") ? dashId.deletingPrefix("river:") : appDelegate.parentFolders(forFeed: feedId).first as? String else {
continue
}

let dash = DashList(index: index, side: side, order: order, feedId: feedId, folder: folder)

dashboard.append(dash)
}
}

func reloadDashboard(for index: Int) {
reload()

guard let currentFeed, index >= 0, index <= dashboard.count else {
return
}

let dash = DashList(index: index, feed: currentFeed, stories: before)
let dash = dashboard[index]

dashboard.append(dash)
dash.feed = currentFeed
dash.stories = before
}
}
19 changes: 19 additions & 0 deletions clients/ios/Classes/SwiftUtilities.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//
// SwiftUtilities.swift
// NewsBlur
//
// Created by David Sinclair on 2024-11-04.
// Copyright © 2024 NewsBlur. All rights reserved.
//

import Foundation

extension String {
func deletingPrefix(_ prefix: String) -> String {
guard hasPrefix(prefix) else {
return self
}

return String(dropFirst(prefix.count))
}
}
10 changes: 8 additions & 2 deletions clients/ios/NewsBlur.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -748,6 +748,8 @@
176A5C7A24F8BD1B009E8DF9 /* DetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 176A5C7924F8BD1B009E8DF9 /* DetailViewController.swift */; };
176AC9EC2C797AA1007B8CB1 /* PreviewViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 176AC9EB2C797AA1007B8CB1 /* PreviewViewController.swift */; };
176AC9ED2C797AA1007B8CB1 /* PreviewViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 176AC9EB2C797AA1007B8CB1 /* PreviewViewController.swift */; };
176B59662CD9C66A003B0C48 /* SwiftUtilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = 176B59652CD9C66A003B0C48 /* SwiftUtilities.swift */; };
176B59672CD9C66A003B0C48 /* SwiftUtilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = 176B59652CD9C66A003B0C48 /* SwiftUtilities.swift */; };
17731A9D23DFAD3D00759A7D /* ImportExportPreferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17731A9C23DFAD3D00759A7D /* ImportExportPreferences.swift */; };
177551D5238E228A00E27818 /* NotificationCenter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 177551D4238E228A00E27818 /* NotificationCenter.framework */; platformFilter = ios; };
177551DB238E228A00E27818 /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 177551D9238E228A00E27818 /* MainInterface.storyboard */; };
Expand Down Expand Up @@ -1554,6 +1556,7 @@
17654E452B02C08700F61B2B /* NewsBlur Alpha Widget.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "NewsBlur Alpha Widget.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
176A5C7924F8BD1B009E8DF9 /* DetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailViewController.swift; sourceTree = "<group>"; };
176AC9EB2C797AA1007B8CB1 /* PreviewViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreviewViewController.swift; sourceTree = "<group>"; };
176B59652CD9C66A003B0C48 /* SwiftUtilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftUtilities.swift; sourceTree = "<group>"; };
17731A9C23DFAD3D00759A7D /* ImportExportPreferences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImportExportPreferences.swift; sourceTree = "<group>"; };
177551D3238E228A00E27818 /* Old NewsBlur Latest.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "Old NewsBlur Latest.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
177551D4238E228A00E27818 /* NotificationCenter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = NotificationCenter.framework; path = System/Library/Frameworks/NotificationCenter.framework; sourceTree = SDKROOT; };
Expand Down Expand Up @@ -3399,6 +3402,7 @@
FFE5322E144C8AC300ACFDE0 /* Utilities.m */,
43D818A115B940C200733444 /* DataUtilities.h */,
43D818A215B940C200733444 /* DataUtilities.m */,
176B59652CD9C66A003B0C48 /* SwiftUtilities.swift */,
172ECBFF298B156D006371BC /* SwiftUIUtilities.swift */,
172AD273251D9F40000BB264 /* Storyboards.swift */,
170E3CCE24F8A5D8009CE819 /* SplitViewController.swift */,
Expand Down Expand Up @@ -5175,6 +5179,7 @@
175792AF2930605500490924 /* FMDatabaseQueue.m in Sources */,
175792B02930605500490924 /* FMResultSet.m in Sources */,
175792B12930605500490924 /* NBNotifier.m in Sources */,
176B59662CD9C66A003B0C48 /* SwiftUtilities.swift in Sources */,
175792B22930605500490924 /* TUSafariActivity.m in Sources */,
17BC56AE2BBF6C0000A30C41 /* StoryCache.swift in Sources */,
175792B32930605500490924 /* PremiumViewController.m in Sources */,
Expand Down Expand Up @@ -5388,6 +5393,7 @@
FF753CD1175858FC00344EC9 /* FMDatabaseQueue.m in Sources */,
FF753CD3175858FC00344EC9 /* FMResultSet.m in Sources */,
FF6618C8176184560039913B /* NBNotifier.m in Sources */,
176B59672CD9C66A003B0C48 /* SwiftUtilities.swift in Sources */,
FF03AFF319F87F2E0063002A /* TUSafariActivity.m in Sources */,
17BC56AD2BBF6C0000A30C41 /* StoryCache.swift in Sources */,
FF83FF051FB52565008DAC0F /* PremiumViewController.m in Sources */,
Expand Down Expand Up @@ -6129,7 +6135,7 @@
RUN_CLANG_STATIC_ANALYZER = YES;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 6.0;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
Expand Down Expand Up @@ -6184,7 +6190,7 @@
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_VERSION = 6.0;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
Expand Down

0 comments on commit 2bf7f9a

Please sign in to comment.