mirror of
https://github.com/Dimillian/IceCubesApp.git
synced 2024-11-14 05:21:12 +00:00
add rss feed manager view
This commit is contained in:
parent
52655c6d11
commit
07ce48fe6c
8 changed files with 198 additions and 11 deletions
|
@ -149,6 +149,9 @@ extension View {
|
|||
.withEnvironments()
|
||||
case .addNewRSSFeed:
|
||||
RSSAddNewFeed()
|
||||
case .rssFeedManager:
|
||||
RSSFeedManager()
|
||||
.withEnvironments()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,8 @@ import CoreData
|
|||
|
||||
@MainActor
|
||||
public struct RSSTab: View {
|
||||
@FetchRequest(sortDescriptors: [SortDescriptor(\.date, order: .reverse)])
|
||||
@FetchRequest(sortDescriptors: [SortDescriptor(\.date, order: .reverse)],
|
||||
predicate: NSPredicate(format: "feed.isShowing == TRUE"))
|
||||
private var items: FetchedResults<RSSItem>
|
||||
|
||||
@Environment(\.managedObjectContext) private var moContext
|
||||
|
@ -50,6 +51,17 @@ public struct RSSTab: View {
|
|||
AppAccountsSelectorView(routerPath: routerPath)
|
||||
}
|
||||
|
||||
ToolbarItem(placement: .navigationBarTrailing) {
|
||||
Button {
|
||||
Task { @MainActor in
|
||||
routerPath.presentedSheet = SheetDestination.rssFeedManager
|
||||
HapticManager.shared.fireHaptic(.buttonPress)
|
||||
}
|
||||
} label: {
|
||||
Image(systemName: "list.bullet.rectangle.portrait")
|
||||
}
|
||||
}
|
||||
|
||||
ToolbarItem(placement: .navigationBarTrailing) {
|
||||
Button {
|
||||
Task { @MainActor in
|
||||
|
@ -58,13 +70,6 @@ public struct RSSTab: View {
|
|||
}
|
||||
} label: {
|
||||
Image(systemName: "plus")
|
||||
.accessibilityLabel("accessibility.tabs.timeline.new-post.label")
|
||||
.accessibilityInputLabels([
|
||||
LocalizedStringKey("accessibility.tabs.timeline.new-post.label"),
|
||||
LocalizedStringKey("accessibility.tabs.timeline.new-post.inputLabel1"),
|
||||
LocalizedStringKey("accessibility.tabs.timeline.new-post.inputLabel2"),
|
||||
])
|
||||
.offset(y: -2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,6 +71,7 @@ public enum SheetDestination: Identifiable, Hashable {
|
|||
case accountEditInfo
|
||||
case accountFiltersList
|
||||
case addNewRSSFeed
|
||||
case rssFeedManager
|
||||
|
||||
public var id: String {
|
||||
switch self {
|
||||
|
@ -107,6 +108,8 @@ public enum SheetDestination: Identifiable, Hashable {
|
|||
"accountFiltersList"
|
||||
case .addNewRSSFeed:
|
||||
"addNewRSSFeed"
|
||||
case .rssFeedManager:
|
||||
"rssFeedManager"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,5 +51,6 @@ extension RSSFeed {
|
|||
}
|
||||
|
||||
self.expired = sendableData.parsedFeed.expired
|
||||
self.isShowing = true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="22522" systemVersion="23D60" minimumToolsVersion="Automatic" sourceLanguage="Swift" usedWithSwiftData="YES" userDefinedModelVersionIdentifier="">
|
||||
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="22757" systemVersion="23E214" minimumToolsVersion="Automatic" sourceLanguage="Swift" usedWithSwiftData="YES" userDefinedModelVersionIdentifier="">
|
||||
<entity name="RSSAuthor" representedClassName="RSSAuthor" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="avatarURL" optional="YES" attributeType="URI"/>
|
||||
<attribute name="displayName" optional="YES" attributeType="String"/>
|
||||
|
@ -19,9 +19,10 @@
|
|||
<attribute name="expired" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="faviconURL" optional="YES" attributeType="URI"/>
|
||||
<attribute name="feedDescription" optional="YES" attributeType="String"/>
|
||||
<attribute name="feedURL" optional="YES" attributeType="URI"/>
|
||||
<attribute name="feedURL" attributeType="URI"/>
|
||||
<attribute name="homePageURL" optional="YES" attributeType="URI"/>
|
||||
<attribute name="iconURL" optional="YES" attributeType="URI"/>
|
||||
<attribute name="isShowing" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="nextURL" optional="YES" attributeType="URI"/>
|
||||
<attribute name="title" optional="YES" attributeType="String"/>
|
||||
<attribute name="type" optional="YES" attributeType="String"/>
|
||||
|
|
59
Packages/RSS/Sources/RSS/Views/RSSFeedManager.swift
Normal file
59
Packages/RSS/Sources/RSS/Views/RSSFeedManager.swift
Normal file
|
@ -0,0 +1,59 @@
|
|||
//
|
||||
// RSSFeedManager.swift
|
||||
//
|
||||
//
|
||||
// Created by Duong Thai on 12/3/24.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import DesignSystem
|
||||
|
||||
public struct RSSFeedManager: View {
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
@Environment(\.managedObjectContext) private var moContext
|
||||
@FetchRequest(sortDescriptors: [SortDescriptor(\.title, order: .reverse)])
|
||||
private var feeds: FetchedResults<RSSFeed>
|
||||
|
||||
public var body: some View {
|
||||
NavigationStack{
|
||||
List {
|
||||
ForEach(feeds) { feed in
|
||||
RSSFeedView(feed)
|
||||
}
|
||||
.onDelete { indices in
|
||||
for index in indices {
|
||||
moContext.delete(feeds[index])
|
||||
}
|
||||
}
|
||||
}
|
||||
.listStyle(PlainListStyle())
|
||||
.navigationTitle("rss.rssFeedManager.title")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .topBarLeading) {
|
||||
Button {
|
||||
dismiss()
|
||||
moContext.rollback()
|
||||
} label: {
|
||||
Image(systemName: "xmark")
|
||||
}
|
||||
}
|
||||
|
||||
ToolbarItem(placement: .topBarTrailing) {
|
||||
Button("rss.rssFeedManager.action.done") {
|
||||
dismiss()
|
||||
try? moContext.save()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.onDisappear { moContext.rollback() }
|
||||
.environment(Theme.shared)
|
||||
}
|
||||
|
||||
public init() {}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
RSSFeedManager()
|
||||
}
|
115
Packages/RSS/Sources/RSS/Views/RSSFeedView.swift
Normal file
115
Packages/RSS/Sources/RSS/Views/RSSFeedView.swift
Normal file
|
@ -0,0 +1,115 @@
|
|||
//
|
||||
// SwiftUIView.swift
|
||||
//
|
||||
//
|
||||
// Created by Duong Thai on 12/3/24.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import DesignSystem
|
||||
|
||||
public struct RSSFeedView: View {
|
||||
@ObservedObject private var feed: RSSFeed
|
||||
@Environment(Theme.self) private var theme
|
||||
|
||||
private var items: ArraySlice<RSSItem> {
|
||||
((feed.items?.allObjects as? [RSSItem]) ?? [])
|
||||
.sorted { i0, i1 in
|
||||
if let d0 = i0.date,
|
||||
let d1 = i1.date
|
||||
{ d0 > d1 } else { false }
|
||||
}.prefix(5)
|
||||
}
|
||||
|
||||
private var contentPadding: CGFloat {
|
||||
theme.avatarPosition == .top
|
||||
? 0
|
||||
: AvatarView.FrameConfig.status.width + .statusColumnsSpacing
|
||||
}
|
||||
|
||||
public var body: some View {
|
||||
VStack(alignment: .leading, spacing: .statusComponentSpacing) {
|
||||
headerView()
|
||||
VStack(alignment: .leading, spacing: theme.lineSpacing) {
|
||||
if let feedDescription = feed.feedDescription {
|
||||
Text(feedDescription)
|
||||
}
|
||||
Text("rss.rssFeedManager.latestItemsSection.label")
|
||||
.font(.scaledFootnote)
|
||||
.fontWeight(.bold)
|
||||
.lineLimit(1)
|
||||
ForEach(items) { item in
|
||||
HStack(alignment: .lastTextBaseline) {
|
||||
Text(" ⋅ \(item.title ?? "No Title")")
|
||||
Spacer()
|
||||
Text(item.date ?? .now, style: .offset)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
}
|
||||
.font(.scaledFootnote)
|
||||
.lineLimit(1)
|
||||
}
|
||||
|
||||
HStack {
|
||||
Button {
|
||||
feed.isShowing.toggle()
|
||||
feed.managedObjectContext?.refreshAllObjects()
|
||||
} label: {
|
||||
Image(systemName: "eye")
|
||||
.foregroundColor(Color(UIColor.secondaryLabel))
|
||||
.padding(.horizontal, 8)
|
||||
.frame(maxWidth: .infinity)
|
||||
.contentShape(Rectangle())
|
||||
}
|
||||
|
||||
Divider()
|
||||
|
||||
Button {
|
||||
feed.managedObjectContext!.delete(feed)
|
||||
} label: {
|
||||
Image(systemName: "trash")
|
||||
.foregroundColor(Color(UIColor.secondaryLabel))
|
||||
.padding(.horizontal, 8)
|
||||
.frame(maxWidth: .infinity)
|
||||
.contentShape(Rectangle())
|
||||
}
|
||||
}
|
||||
.padding(.leading, contentPadding)
|
||||
.padding(.top, 6)
|
||||
.buttonStyle(.borderless)
|
||||
#if targetEnvironment(macCatalyst)
|
||||
.font(.scaledBody)
|
||||
#else
|
||||
.font(.body)
|
||||
.dynamicTypeSize(.large)
|
||||
#endif
|
||||
}
|
||||
.opacity(feed.isShowing ? 1 : 0.5)
|
||||
}
|
||||
|
||||
|
||||
public init(_ feed: RSSFeed) {
|
||||
self.feed = feed
|
||||
}
|
||||
|
||||
private func headerView() -> some View {
|
||||
HStack {
|
||||
AvatarView(feed.iconURL ?? feed.faviconURL, config: .status)
|
||||
.accessibility(addTraits: .isButton)
|
||||
.contentShape(Circle())
|
||||
.hoverEffect()
|
||||
|
||||
HStack(alignment: .bottom) {
|
||||
HStack(spacing: 2) {
|
||||
Text(feed.feedURL?.host() ?? "")
|
||||
.foregroundColor(theme.labelColor)
|
||||
Image(systemName: "dot.radiowaves.up.forward")
|
||||
.foregroundColor(theme.tintColor)
|
||||
}
|
||||
.font(.scaledSubheadline)
|
||||
.fontWeight(.semibold)
|
||||
.lineLimit(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// SwiftUIView.swift
|
||||
// RSSItemView.swift
|
||||
//
|
||||
//
|
||||
// Created by Duong Thai on 03/03/2024.
|
||||
|
|
Loading…
Reference in a new issue