diff --git a/Multiplatform/Shared/Article/ArticleContainerView.swift b/Multiplatform/Shared/Article/ArticleContainerView.swift new file mode 100644 index 000000000..021c39d62 --- /dev/null +++ b/Multiplatform/Shared/Article/ArticleContainerView.swift @@ -0,0 +1,31 @@ +// +// ArticleContainerView.swift +// NetNewsWire +// +// Created by Maurice Parker on 7/2/20. +// Copyright © 2020 Ranchero Software. All rights reserved. +// + +import SwiftUI +import Articles + +struct ArticleContainerView: View { + + @EnvironmentObject private var sceneModel: SceneModel + @StateObject private var articleModel = ArticleModel() + var article: Article? = nil + + @ViewBuilder var body: some View { + if let article = article { + ArticleView() + .environmentObject(articleModel) + .onAppear { + sceneModel.articleModel = articleModel + articleModel.delegate = sceneModel + } + } else { + EmptyView() + } + } + +} diff --git a/Multiplatform/Shared/Article/ArticleModel.swift b/Multiplatform/Shared/Article/ArticleModel.swift new file mode 100644 index 000000000..7e2248d0b --- /dev/null +++ b/Multiplatform/Shared/Article/ArticleModel.swift @@ -0,0 +1,25 @@ +// +// ArticleModel.swift +// NetNewsWire +// +// Created by Maurice Parker on 7/2/20. +// Copyright © 2020 Ranchero Software. All rights reserved. +// + +import Foundation + +import Foundation +import RSCore +import Account +import Articles + +protocol ArticleModelDelegate: class { + func timelineRequestedWebFeedSelection(_: TimelineModel, webFeed: WebFeed) +} + +class ArticleModel: ObservableObject { + + weak var delegate: ArticleModelDelegate? + +} + diff --git a/Multiplatform/Shared/Article/ArticleView.swift b/Multiplatform/Shared/Article/ArticleView.swift new file mode 100644 index 000000000..309551225 --- /dev/null +++ b/Multiplatform/Shared/Article/ArticleView.swift @@ -0,0 +1,21 @@ +// +// ArticleView.swift +// NetNewsWire +// +// Created by Maurice Parker on 7/2/20. +// Copyright © 2020 Ranchero Software. All rights reserved. +// + +import SwiftUI + +struct ArticleView: View { + var body: some View { + Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/) + } +} + +struct ArticleView_Previews: PreviewProvider { + static var previews: some View { + ArticleView() + } +} diff --git a/Multiplatform/Shared/SceneModel.swift b/Multiplatform/Shared/SceneModel.swift index f09b48f6d..e199ac11c 100644 --- a/Multiplatform/Shared/SceneModel.swift +++ b/Multiplatform/Shared/SceneModel.swift @@ -13,6 +13,7 @@ final class SceneModel: ObservableObject { var sidebarModel: SidebarModel? var timelineModel: TimelineModel? + var articleModel: ArticleModel? } @@ -35,3 +36,10 @@ extension SceneModel: TimelineModelDelegate { } } + +// MARK: ArticleModelDelegate + +extension SceneModel: ArticleModelDelegate { + + +} diff --git a/Multiplatform/Shared/Sidebar/CompactSidebarContainerView.swift b/Multiplatform/Shared/Sidebar/CompactSidebarContainerView.swift index 23d986b46..a14b01503 100644 --- a/Multiplatform/Shared/Sidebar/CompactSidebarContainerView.swift +++ b/Multiplatform/Shared/Sidebar/CompactSidebarContainerView.swift @@ -30,38 +30,6 @@ struct CompactSidebarContainerView: View { },alignment: .bottom) } - - var compactToolBar: some View { - VStack { - Divider() - HStack(alignment: .center) { - Button(action: { - showSettings = true - }, label: { - Image(systemName: "gear") - .font(.title3) - .foregroundColor(.accentColor) - }).help("Settings") - Spacer() - Text("Last updated") - .font(.caption) - .foregroundColor(.secondary) - Spacer() - Button(action: {}, label: { - Image(systemName: "plus") - .font(.title3) - .foregroundColor(.accentColor) - }).help("Add") - } - .padding(.horizontal, 16) - .padding(.bottom, 12) - .padding(.top, 4) - } - .background(VisualEffectBlur(blurStyle: .systemChromeMaterial).edgesIgnoringSafeArea(.bottom)) - - } - - } struct CompactSidebarContainerView_Previews: PreviewProvider { diff --git a/Multiplatform/Shared/Sidebar/SidebarToolbar.swift b/Multiplatform/Shared/Sidebar/SidebarToolbar.swift index e7df534f6..70123ddc3 100644 --- a/Multiplatform/Shared/Sidebar/SidebarToolbar.swift +++ b/Multiplatform/Shared/Sidebar/SidebarToolbar.swift @@ -11,6 +11,11 @@ import SwiftUI struct SidebarToolbar: View { @State private var showSettings: Bool = false + @State private var showAddSheet: Bool = false + + var addActionSheetButtons = [ + Button(action: {}, label: { Text("Add Feed") }) + ] var body: some View { VStack { @@ -28,11 +33,23 @@ struct SidebarToolbar: View { .font(.caption) .foregroundColor(.secondary) Spacer() - Button(action: {}, label: { + Button(action: { + showAddSheet = true + }, label: { Image(systemName: "plus") .font(.title3) .foregroundColor(.accentColor) - }).help("Add") + }) + .help("Add") + .actionSheet(isPresented: $showAddSheet) { + ActionSheet(title: Text("Add"), buttons: [ + .cancel(), + .default(Text("Add Web Feed")), + .default(Text("Add Twitter Feed")), + .default(Text("Add Reddit Feed")), + .default(Text("Add Folder")) + ]) + } } .padding(.horizontal, 16) .padding(.bottom, 12) diff --git a/Multiplatform/Shared/Timeline/TimelineItemView.swift b/Multiplatform/Shared/Timeline/TimelineItemView.swift index 62c7dfaad..d4f4f172a 100644 --- a/Multiplatform/Shared/Timeline/TimelineItemView.swift +++ b/Multiplatform/Shared/Timeline/TimelineItemView.swift @@ -45,7 +45,6 @@ struct TimelineItemView: View { } } } - Divider() } .onAppear { articleIconImageLoader.loadImage(for: timelineItem.article) diff --git a/Multiplatform/Shared/Timeline/TimelineModel.swift b/Multiplatform/Shared/Timeline/TimelineModel.swift index d89da96a1..307bf0f03 100644 --- a/Multiplatform/Shared/Timeline/TimelineModel.swift +++ b/Multiplatform/Shared/Timeline/TimelineModel.swift @@ -55,6 +55,14 @@ class TimelineModel: ObservableObject { fetchAndReplaceArticlesAsync() } + // TODO: Replace this with ScrollViewReader if we have to keep it + func loadMoreTimelineItemsIfNecessary(_ timelineItem: TimelineItem) { + let thresholdIndex = timelineItems.index(timelineItems.endIndex, offsetBy: -10) + if timelineItems.firstIndex(where: { $0.id == timelineItem.id }) == thresholdIndex { + nextBatch() + } + } + } // MARK: Private @@ -112,12 +120,19 @@ private extension TimelineModel { func replaceArticles(with unsortedArticles: Set
) { articles = Array(unsortedArticles).sortedByDate(sortDirection ? .orderedDescending : .orderedAscending, groupByFeed: groupByFeed) - timelineItems = articles.map { TimelineItem(article: $0) } - + timelineItems = [TimelineItem]() + nextBatch() // TODO: Update unread counts and other item done in didSet on AppKit } - + func nextBatch() { + let rangeEndIndex = timelineItems.endIndex + 50 > articles.endIndex ? articles.endIndex : timelineItems.endIndex + 50 + let range = timelineItems.endIndex..