Add note containers

This commit is contained in:
Jackson Harper
2023-11-01 17:56:54 +08:00
parent 67c3c8e84d
commit b92cbbc9a5
5 changed files with 85 additions and 117 deletions

View File

@ -79,6 +79,17 @@ public extension LinkedItem {
(labels?.count ?? 0) > 0
}
var noteText: String? {
if let highlights = highlights?.compactMap({ $0 as? Highlight }) {
let result = highlights
.filter { $0.type == "NOTE" }
.sorted(by: { $0.updatedAt ?? Date() < $1.updatedAt ?? Date() })
.first
return result?.annotation
}
return nil
}
var isUnread: Bool {
readingProgress <= 0
}

View File

@ -50,6 +50,7 @@ public extension Color {
static var extensionPanelBackground: Color { Color("_extensionPanelBackground", bundle: .module) }
static var extensionTextSubtle: Color { Color("_extensionTextSubtle", bundle: .module) }
static var noteContainer: Color { Color("_noteContainer", bundle: .module) }
static var textFieldBackground: Color { Color("_textFieldBackground", bundle: .module) }
// Apple system UIColor equivalents

View File

@ -0,0 +1,38 @@
{
"colors" : [
{
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "0xED",
"green" : "0xED",
"red" : "0xED"
}
},
"idiom" : "universal"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "0x2A",
"green" : "0x2A",
"red" : "0x2A"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -1,117 +0,0 @@
import Models
import SwiftUI
import Utils
public struct FeedCard: View {
let viewer: Viewer?
let tapHandler: () -> Void
@ObservedObject var item: LinkedItem
public init(item: LinkedItem, viewer: Viewer?, tapHandler: @escaping () -> Void = {}) {
self.item = item
self.viewer = viewer
self.tapHandler = tapHandler
}
public var body: some View {
VStack {
HStack(alignment: .top, spacing: 10) {
VStack(alignment: .leading, spacing: 1) {
Text(item.unwrappedTitle)
.font(.appCallout)
.lineSpacing(1.25)
.foregroundColor(.appGrayTextContrast)
.fixedSize(horizontal: false, vertical: true)
.padding(EdgeInsets(top: 0, leading: 0, bottom: 2, trailing: 0))
if let author = item.author {
Text("By \(author)")
.font(.appCaption)
.foregroundColor(.appGrayText)
.lineLimit(1)
}
if let publisherDisplayName = item.publisherDisplayName {
Text(publisherDisplayName)
.font(.appCaption)
.foregroundColor(.appGrayText)
.lineLimit(1)
}
}
.frame(
minWidth: 0,
maxWidth: .infinity,
minHeight: 0,
maxHeight: .infinity,
alignment: .topLeading
)
.multilineTextAlignment(.leading)
.padding(0)
Group {
if let imageURL = item.imageURL {
AsyncImage(url: imageURL) { phase in
if let image = phase.image {
image
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 80, height: 80)
.cornerRadius(6)
} else {
Color.systemBackground
.frame(width: 80, height: 80)
.cornerRadius(6)
}
}
}
}
}
if item.hasLabels {
// Category Labels
ScrollView(.horizontal, showsIndicators: false) {
HStack {
ForEach(item.sortedLabels, id: \.self) {
TextChip(feedItemLabel: $0)
}
Spacer()
}
}.introspectScrollView { scrollView in
#if os(iOS)
scrollView.bounces = false
#endif
}
.padding(.top, 0)
#if os(macOS)
.onTapGesture {
tapHandler()
}
#endif
}
let recs = Recommendation.notViewers(viewer: viewer, item.recommendations)
if recs.count > 0 {
let byStr = Recommendation.byline(recs)
let inStr = Recommendation.groupsLine(recs)
HStack {
Image(systemName: "sparkles")
Text("Recommended by \(byStr) in \(inStr)")
.font(.appCaption)
.frame(alignment: .leading)
Spacer()
}
}
}
.padding(.top, 0)
.padding(.bottom, 8)
.frame(
minWidth: nil,
idealWidth: nil,
maxWidth: nil,
minHeight: 70,
idealHeight: nil,
maxHeight: nil,
alignment: .topLeading
)
}
}

View File

@ -47,6 +47,7 @@ public extension View {
public struct LibraryItemCard: View {
let viewer: Viewer?
@ObservedObject var item: LinkedItem
@State var noteLineLimit: Int? = 3
public init(item: LinkedItem, viewer: Viewer?) {
self.item = item
@ -64,6 +65,30 @@ public struct LibraryItemCard: View {
if item.hasLabels {
labels
}
if let note = item.noteText {
HStack(alignment: .top, spacing: 10) {
avatarImage
.frame(width: 20, height: 20)
.padding(.vertical, 10)
.padding(.leading, 10)
Text(note)
.font(Font.system(size: 12))
.multilineTextAlignment(.leading)
.lineLimit(noteLineLimit)
.padding(.vertical, 10)
.padding(.trailing, 10)
}
.frame(maxWidth: .infinity)
.frame(alignment: .topLeading)
.background(Color.noteContainer)
.cornerRadius(5)
.allowsHitTesting(noteLineLimit != nil)
.onTapGesture {
noteLineLimit = nil
}
}
}
.padding(5)
.padding(.top, 10)
@ -79,6 +104,16 @@ public struct LibraryItemCard: View {
Int(item.readingProgress) > 0
}
var avatarImage: some View {
ZStack(alignment: .center) {
Circle()
.foregroundColor(Color.appCtaYellow)
Text((viewer?.name ?? "O").prefix(1))
.font(Font.system(size: 10))
.foregroundColor(Color.black)
}
}
var readIndicator: some View {
HStack {
Circle()