Skip to content

Commit fcbf54f

Browse files
dyongxuMarcoEidingerbillzhou0223xiaoyu0722hengyi-zhang
authored
merge: from main to rel-4.1 to get the latest translation package and other fixes (#776)
* chore(release): 4.1.2 * fix: 🐛 [IOSSDKBUG-291] set line limit for MenuSelectionItem (#769) * fix: 🐛 [JIRA: IOSSDKBUG-306] toolbar layout issue (#771) * feat: 🎸 [JIRA:HCPSDKFIORIUIKIT-2686] Button update (#753) Co-authored-by: Bill Zhou <[email protected]> * fix: 🐛 step progress indicator styles (#775) * Translation Delivery (#774) * [INTERNAL] Translation delivery: commit by LX Lab Change-Id: I111a249ae01afea6ba8029630027e1807e471499 * [INTERNAL] Translation delivery: commit by LX Lab Change-Id: I00c59b0e7a3bcd6346b6fddb8a51787bc132ace4 --------- Co-authored-by: dyongxu <[email protected]> --------- Co-authored-by: Marco Eidinger <[email protected]> Co-authored-by: Bill Zhou <[email protected]> Co-authored-by: Xiaoyu Liu <[email protected]> Co-authored-by: hengyi-zhang <[email protected]> Co-authored-by: SAP LX Lab Service Account <[email protected]>
1 parent ca3eaf5 commit fcbf54f

32 files changed

+2174
-101
lines changed

Diff for: Apps/Examples/Examples.xcodeproj/project.pbxproj

+56
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
import FioriSwiftUICore
2+
import FioriThemeManager
3+
import SwiftUI
4+
5+
struct CardFixedWidthButtonsExample: View {
6+
@State private var buttonTitle = "Check in"
7+
8+
@Environment(\.dismiss) private var dismiss
9+
10+
@State private var _dataSource: [CardFullWidthSingleButtonItem] = [
11+
CardFullWidthSingleButtonItem(title: "1", loadingState: .unspecified, id: UUID()),
12+
CardFullWidthSingleButtonItem(title: "2", loadingState: .unspecified, id: UUID()),
13+
CardFullWidthSingleButtonItem(title: "3", loadingState: .unspecified, id: UUID()),
14+
CardFullWidthSingleButtonItem(title: "4", loadingState: .unspecified, id: UUID()),
15+
CardFullWidthSingleButtonItem(title: "5", loadingState: .unspecified, id: UUID())
16+
]
17+
18+
private var profileHeader: some View {
19+
ProfileHeader(detailImage: {
20+
Image("rw").resizable()
21+
}, title: {
22+
Text("Harry Ford")
23+
}, subtitle: {
24+
Text("The boy wizard, the boy wizard")
25+
}, description: {
26+
Text("This is a description.")
27+
}) {
28+
HStack {
29+
Spacer()
30+
Button {
31+
print("tap message")
32+
} label: {
33+
FioriIcon.callout.discussion
34+
.imageScale(.large)
35+
.fontWeight(.light)
36+
}
37+
Spacer()
38+
39+
Button {
40+
print("tap email")
41+
} label: {
42+
FioriIcon.actions.email
43+
.imageScale(.large)
44+
.fontWeight(.light)
45+
}
46+
Spacer()
47+
48+
Button {
49+
print("tap call")
50+
} label: {
51+
FioriIcon.actions.call
52+
.imageScale(.large)
53+
.fontWeight(.light)
54+
}
55+
Spacer()
56+
57+
Button {
58+
print("tap video")
59+
} label: {
60+
FioriIcon.actions.video
61+
.imageScale(.large)
62+
.fontWeight(.light)
63+
}
64+
Spacer()
65+
66+
Button {
67+
print("tap hint")
68+
} label: {
69+
FioriIcon.actions.hint
70+
.imageScale(.large)
71+
.fontWeight(.light)
72+
}
73+
Spacer()
74+
}
75+
}
76+
}
77+
78+
var body: some View {
79+
List {
80+
Section {
81+
Divider()
82+
.padding(EdgeInsets(top: 0, leading: 10, bottom: 0, trailing: 0))
83+
84+
HStack {
85+
Text("My Schedule")
86+
.font(.fiori(forTextStyle: .subheadline))
87+
.foregroundStyle(Color.preferredColor(.secondaryLabel))
88+
Spacer()
89+
Button {
90+
print("see all")
91+
} label: {
92+
Text("See all (\(self._dataSource.count))")
93+
.font(.fiori(forTextStyle: .body))
94+
.foregroundStyle(Color.preferredColor(.tintColor))
95+
}
96+
}
97+
.padding(EdgeInsets(top: 5, leading: 20, bottom: 5, trailing: 20))
98+
99+
ScrollView(.horizontal) {
100+
HStack(spacing: 8, content: {
101+
ForEach(0 ..< self._dataSource.count, id: \.self) { index in
102+
let item = self._dataSource[index]
103+
HStack {
104+
Card {
105+
Text("Schedule\(item.title)")
106+
} subtitle: {
107+
Text("Subtitle")
108+
} detailImage: {
109+
Image("ProfilePic")
110+
.resizable()
111+
.frame(width: 45, height: 45)
112+
.clipShape(RoundedRectangle(cornerRadius: 10))
113+
} headerAction: {
114+
FioriIcon.shopping.cart
115+
} row1: {
116+
Text("Body text could be really long description that requires wrapping, with suggested 2 lines from Fiori Design Guideline perspective to make the UI concise. SDK default setting of numberOfLines for body is 6. Application Developer can override it with : cell.body.numOfLines = preferredNumberOfLines.")
117+
.lineLimit(2)
118+
} action: {
119+
FioriButton(isSelectionPersistent: false, action: { _ in
120+
self.updateDataSource(id: item.id)
121+
}, label: { _ in
122+
self.primaryActionLabel(item.loadingState)
123+
}, image: { _ in
124+
EmptyView()
125+
}, imagePosition: .leading, imageTitleSpacing: 8.0)
126+
.fioriButtonStyle(FioriPrimaryButtonStyle(118, loadingState: item.loadingState))
127+
.disabled(item.loadingState != .unspecified)
128+
} secondaryAction: {
129+
FioriButton(isSelectionPersistent: false, title: "Decline", action: { _ in
130+
print("tap Decline")
131+
})
132+
.fioriButtonStyle(FioriSecondaryButtonStyle(colorStyle: .negative, maxWidth: 118))
133+
}
134+
.frame(width: 300, height: 192)
135+
.background(Color.white)
136+
}
137+
.clipShape(RoundedRectangle(cornerRadius: 16))
138+
.shadow(color: .preferredColor(.cardShadow), radius: 16) //
139+
.padding(EdgeInsets(top: 8, leading: 8, bottom: 8, trailing: 8))
140+
}
141+
})
142+
.padding(EdgeInsets(top: 0, leading: 10, bottom: 0, trailing: 10))
143+
}
144+
Spacer()
145+
} header: {
146+
self.profileHeader
147+
.frame(maxWidth: .infinity)
148+
.padding()
149+
.background(Color.preferredColor(.secondaryGroupedBackground))
150+
}
151+
.listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
152+
.listRowSeparator(.hidden)
153+
}
154+
.listStyle(.grouped)
155+
.navigationTitle("Object Card - Full Width Single Button")
156+
.navigationBarTitleDisplayMode(.inline)
157+
}
158+
159+
@ViewBuilder
160+
func primaryActionLabel(_ loadingState: FioriButtonLoadingState) -> any View {
161+
loadingState != .unspecified ? AnyView(EmptyView()) : AnyView(Text("Check in"))
162+
}
163+
164+
func updateDataSource(id: UUID) {
165+
for i in 0 ..< self._dataSource.count {
166+
let item = self._dataSource[i]
167+
if item.id == id {
168+
var timeInterval = 0.0
169+
if item.loadingState == .unspecified {
170+
item.loadingState = .processing
171+
self._dataSource[i] = item
172+
timeInterval = 2.0
173+
} else if item.loadingState == .processing {
174+
item.loadingState = .success
175+
self._dataSource[i] = item
176+
timeInterval = 1.0
177+
} else {
178+
self._dataSource.remove(at: i)
179+
if self._dataSource.isEmpty {
180+
self.dismiss()
181+
}
182+
return
183+
}
184+
185+
_ = Timer.scheduledTimer(withTimeInterval: timeInterval, repeats: false, block: { _ in
186+
self.updateDataSource(id: id)
187+
})
188+
break
189+
}
190+
}
191+
}
192+
}
193+
194+
#Preview {
195+
CardFixedWidthButtonsExample()
196+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
import FioriSwiftUICore
2+
import FioriThemeManager
3+
import SwiftUI
4+
5+
class CardFullWidthSingleButtonItem: Identifiable, ObservableObject {
6+
@Published var title: String
7+
@Published var loadingState: FioriButtonLoadingState
8+
@Published var id: UUID
9+
10+
init(title: String, loadingState: FioriButtonLoadingState, id: UUID) {
11+
self.title = title
12+
self.loadingState = loadingState
13+
self.id = id
14+
}
15+
}
16+
17+
struct CardFullWidthSingleButtonExample: View {
18+
@State private var buttonTitle = "Check in"
19+
@Environment(\.dismiss) private var dismiss
20+
21+
@State private var _dataSource: [CardFullWidthSingleButtonItem] = [
22+
CardFullWidthSingleButtonItem(title: "1", loadingState: .unspecified, id: UUID()),
23+
CardFullWidthSingleButtonItem(title: "2", loadingState: .unspecified, id: UUID()),
24+
CardFullWidthSingleButtonItem(title: "3", loadingState: .unspecified, id: UUID()),
25+
CardFullWidthSingleButtonItem(title: "4", loadingState: .unspecified, id: UUID()),
26+
CardFullWidthSingleButtonItem(title: "5", loadingState: .unspecified, id: UUID())
27+
]
28+
29+
var profileHeader: some View {
30+
ProfileHeader(detailImage: {
31+
Image("rw").resizable()
32+
}, title: {
33+
Text("Harry Ford")
34+
}, subtitle: {
35+
Text("The boy wizard, the boy wizard")
36+
}, description: {
37+
Text("This is a description.")
38+
}) {
39+
HStack {
40+
Spacer()
41+
Button {
42+
print("tap message")
43+
} label: {
44+
FioriIcon.callout.discussion
45+
.imageScale(.large)
46+
.fontWeight(.light)
47+
}
48+
Spacer()
49+
50+
Button {
51+
print("tap email")
52+
} label: {
53+
FioriIcon.actions.email
54+
.imageScale(.large)
55+
.fontWeight(.light)
56+
}
57+
Spacer()
58+
59+
Button {
60+
print("tap call")
61+
} label: {
62+
FioriIcon.actions.call
63+
.imageScale(.large)
64+
.fontWeight(.light)
65+
}
66+
Spacer()
67+
68+
Button {
69+
print("tap video")
70+
} label: {
71+
FioriIcon.actions.video
72+
.imageScale(.large)
73+
.fontWeight(.light)
74+
}
75+
Spacer()
76+
77+
Button {
78+
print("tap hint")
79+
} label: {
80+
FioriIcon.actions.hint
81+
.imageScale(.large)
82+
.fontWeight(.light)
83+
}
84+
Spacer()
85+
}
86+
}
87+
}
88+
89+
var body: some View {
90+
Section {
91+
Divider()
92+
HStack {
93+
Text("My Schedule")
94+
.font(.fiori(forTextStyle: .subheadline))
95+
.foregroundStyle(Color.preferredColor(.secondaryLabel))
96+
Spacer()
97+
Button {
98+
print("see all")
99+
} label: {
100+
Text("See all (\(self._dataSource.count))")
101+
.font(.fiori(forTextStyle: .body))
102+
.foregroundStyle(Color.preferredColor(.tintColor))
103+
}
104+
}
105+
.padding(EdgeInsets(top: 5, leading: 20, bottom: 5, trailing: 20))
106+
107+
ScrollView(.horizontal) {
108+
HStack(spacing: 8, content: {
109+
ForEach(0 ..< self._dataSource.count, id: \.self) { index in
110+
let item = self._dataSource[index]
111+
HStack {
112+
Card {
113+
Text("Schedule\(item.title)")
114+
} subtitle: {
115+
Text("Subtitle")
116+
} detailImage: {
117+
Image("ProfilePic")
118+
.resizable()
119+
.frame(width: 45, height: 45)
120+
.clipShape(RoundedRectangle(cornerRadius: 10))
121+
} headerAction: {
122+
FioriIcon.shopping.cart
123+
} row1: {
124+
Text("Body text could be really long description that requires wrapping, with suggested 2 lines from Fiori Design Guideline perspective to make the UI concise. SDK default setting of numberOfLines for body is 6. Application Developer can override it with : cell.body.numOfLines = preferredNumberOfLines.")
125+
.lineLimit(2)
126+
} action: {
127+
FioriButton(action: { _ in
128+
self.updateDataSource(id: item.id)
129+
}, label: { _ in
130+
Text(self.titleStr(item.loadingState))
131+
})
132+
.fioriButtonStyle(FioriPrimaryButtonStyle(.infinity, loadingState: item.loadingState))
133+
.disabled(item.loadingState != .unspecified)
134+
}
135+
.frame(width: 300, height: 192)
136+
.background(Color.white)
137+
}
138+
.clipShape(RoundedRectangle(cornerRadius: 16))
139+
.shadow(color: .preferredColor(.cardShadow), radius: 16) //
140+
.padding(EdgeInsets(top: 8, leading: 8, bottom: 8, trailing: 8))
141+
}
142+
})
143+
.padding(EdgeInsets(top: 0, leading: 10, bottom: 0, trailing: 10))
144+
}
145+
Spacer()
146+
} header: {
147+
self.profileHeader
148+
.frame(maxWidth: .infinity)
149+
.padding()
150+
.background(Color.preferredColor(.secondaryGroupedBackground))
151+
}
152+
.navigationTitle("Object Card - Full Width Single Button")
153+
.navigationBarTitleDisplayMode(.inline)
154+
}
155+
156+
func updateDataSource(id: UUID) {
157+
for i in 0 ..< self._dataSource.count {
158+
let item = self._dataSource[i]
159+
if item.id == id {
160+
var timeInterval = 0.0
161+
if item.loadingState == .unspecified {
162+
item.loadingState = .processing
163+
self._dataSource[i] = item
164+
timeInterval = 2.0
165+
} else if item.loadingState == .processing {
166+
item.loadingState = .success
167+
self._dataSource[i] = item
168+
timeInterval = 1.0
169+
} else {
170+
self._dataSource.remove(at: i)
171+
if self._dataSource.isEmpty {
172+
self.dismiss()
173+
}
174+
return
175+
}
176+
177+
_ = Timer.scheduledTimer(withTimeInterval: timeInterval, repeats: false, block: { _ in
178+
self.updateDataSource(id: id)
179+
})
180+
break
181+
}
182+
}
183+
}
184+
185+
func titleStr(_ loadingState: FioriButtonLoadingState) -> AttributedString {
186+
switch loadingState {
187+
case .unspecified:
188+
"Check in"
189+
case .processing:
190+
"Checking in"
191+
case .success:
192+
"Checked in"
193+
}
194+
}
195+
}
196+
197+
#Preview {
198+
CardFullWidthSingleButtonExample()
199+
}

0 commit comments

Comments
 (0)