-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathNewsWidget.swift
More file actions
122 lines (107 loc) · 3.54 KB
/
Copy pathNewsWidget.swift
File metadata and controls
122 lines (107 loc) · 3.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import SwiftUI
/// A widget that displays a news article.
struct NewsWidget: View {
var options: NewsWidgetOptions = .init()
var isEditing: Bool = false
var onEditingEnd: (() -> Void)?
@StateObject private var viewModel = NewsViewModel.shared
init(
options: NewsWidgetOptions = NewsWidgetOptions(),
isEditing: Bool = false,
onEditingEnd: (() -> Void)? = nil
) {
self.options = options
self.isEditing = isEditing
self.onEditingEnd = onEditingEnd
}
var body: some View {
BaseWidget(
type: .news,
isEditing: isEditing,
onEditingEnd: onEditingEnd
) {
content
.contentShape(Rectangle())
.onTapGesture {
if !isEditing, let data = viewModel.widgetData, let url = URL(string: data.link) {
UIApplication.shared.open(url)
}
}
}
.task {
viewModel.startUpdates()
}
}
@ViewBuilder
private var content: some View {
if viewModel.isLoading && viewModel.widgetData == nil {
WidgetContentBuilder.loadingView()
} else if viewModel.error != nil {
WidgetContentBuilder.errorView(t("widgets__news__error"))
} else if let data = viewModel.widgetData {
NewsWidgetWideContent(data: data, options: options)
}
}
}
// MARK: - Wide layout (in-app + 343-wide carousel page)
struct NewsWidgetWideContent: View {
let data: WidgetData
let options: NewsWidgetOptions
var body: some View {
VStack(alignment: .leading, spacing: 16) {
if options.showTitle {
TitleText(data.title)
.lineLimit(4)
.frame(maxWidth: .infinity, alignment: .leading)
}
if options.showSource || options.showDate {
HStack(alignment: .center, spacing: 8) {
if options.showSource {
BodySSBText(data.publisher, textColor: .brandAccent)
.lineLimit(1)
}
Spacer(minLength: 0)
if options.showDate {
BodySSBText(data.timeAgo, textColor: .textSecondary)
.lineLimit(1)
}
}
.frame(maxWidth: .infinity)
}
}
.frame(maxWidth: .infinity, alignment: .leading)
}
}
// MARK: - Compact layout (small carousel preview + 163×192 OS widget)
struct NewsWidgetCompactContent: View {
let data: WidgetData
let options: NewsWidgetOptions
var body: some View {
VStack(alignment: .leading, spacing: 0) {
if options.showTitle {
TitleText(data.title)
.lineLimit(4)
.frame(maxWidth: .infinity, alignment: .leading)
}
Spacer(minLength: 8)
if options.showDate {
HStack {
Spacer(minLength: 0)
BodySSBText(data.timeAgo, textColor: .textSecondary)
.lineLimit(1)
}
}
}
.padding(16)
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
.background(Color.gray6)
.cornerRadius(16)
}
}
#Preview {
NewsWidget()
.padding()
.background(.black)
.environmentObject(WalletViewModel())
.preferredColorScheme(.dark)
}