Skip to content

Commit

Permalink
feat: 🎸 [JIRA:HCPSDKFIORIUIKIT-2880] ActivityItemModel Refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
hengyi-zhang committed Dec 9, 2024
1 parent 1f463ad commit c3a8927
Show file tree
Hide file tree
Showing 30 changed files with 464 additions and 70 deletions.
12 changes: 12 additions & 0 deletions Apps/Examples/Examples.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
6D10F8A02C7DB3F50071DD3E /* BannerMultiMessageExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D10F89F2C7DB3F50071DD3E /* BannerMultiMessageExample.swift */; };
6D14F05E2C9290F20053BA98 /* BannerMultiMessageCustomInitExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D14F05D2C9290F20053BA98 /* BannerMultiMessageCustomInitExample.swift */; };
6D3A3DE92CDB5F1E004D4597 /* ObjectCellEnhancementExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D3A3DE82CDB5F1E004D4597 /* ObjectCellEnhancementExample.swift */; };
6D66D7F12D02FC7B00F7A97D /* ActivityItemExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D66D7EF2D02FC7B00F7A97D /* ActivityItemExample.swift */; };
6D6E86252C50D42000EDB6F4 /* FioriButtonInListExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D6E86242C50D42000EDB6F4 /* FioriButtonInListExample.swift */; };
6D6E86292C50E5F900EDB6F4 /* FioriButtonInListMultipleLineExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D6E86282C50E5F900EDB6F4 /* FioriButtonInListMultipleLineExample.swift */; };
6D6E86672C50FDBE00EDB6F4 /* FioriButtonInCollectionExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D6E86662C50FDBE00EDB6F4 /* FioriButtonInCollectionExample.swift */; };
Expand Down Expand Up @@ -262,6 +263,7 @@
6D10F89F2C7DB3F50071DD3E /* BannerMultiMessageExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BannerMultiMessageExample.swift; sourceTree = "<group>"; };
6D14F05D2C9290F20053BA98 /* BannerMultiMessageCustomInitExample.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BannerMultiMessageCustomInitExample.swift; sourceTree = "<group>"; };
6D3A3DE82CDB5F1E004D4597 /* ObjectCellEnhancementExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObjectCellEnhancementExample.swift; sourceTree = "<group>"; };
6D66D7EF2D02FC7B00F7A97D /* ActivityItemExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityItemExample.swift; sourceTree = "<group>"; };
6D6E86242C50D42000EDB6F4 /* FioriButtonInListExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FioriButtonInListExample.swift; sourceTree = "<group>"; };
6D6E86282C50E5F900EDB6F4 /* FioriButtonInListMultipleLineExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FioriButtonInListMultipleLineExample.swift; sourceTree = "<group>"; };
6D6E86662C50FDBE00EDB6F4 /* FioriButtonInCollectionExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FioriButtonInCollectionExample.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -569,6 +571,14 @@
path = SideBar;
sourceTree = "<group>";
};
6D66D7F02D02FC7B00F7A97D /* ActivityItem */ = {
isa = PBXGroup;
children = (
6D66D7EF2D02FC7B00F7A97D /* ActivityItemExample.swift */,
);
path = ActivityItem;
sourceTree = "<group>";
};
8732C2C32C35092D002110E9 /* Timeline */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -662,6 +672,7 @@
8A5579C824C1293C0098003A /* FioriSwiftUICore */ = {
isa = PBXGroup;
children = (
6D66D7F02D02FC7B00F7A97D /* ActivityItem */,
87F14B192CD86F65004A69A0 /* DocumentScannerView */,
3CD71F272CDB625000B037EB /* CheckoutIndicator */,
3CC870942CB6F4E20081909C /* ToastMessage */,
Expand Down Expand Up @@ -1197,6 +1208,7 @@
B846F94A26815DF30085044B /* ContactItemCompactExamples.swift in Sources */,
C106AD442B33710800FE8B35 /* SearchWithScope.swift in Sources */,
6D14F05E2C9290F20053BA98 /* BannerMultiMessageCustomInitExample.swift in Sources */,
6D66D7F12D02FC7B00F7A97D /* ActivityItemExample.swift in Sources */,
6DEC32042C4E49C70084DD20 /* CardFixedWidthButtonsExample.swift in Sources */,
B1C7DC8129FBB13F00DC5EEB /* SPIModelExample.swift in Sources */,
C106AD462B338D1300FE8B35 /* SearchWithToken.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import FioriSwiftUICore
import SwiftUI

struct ActivityItemExample: View {
var body: some View {
List {
Section {
ActivityItem(icon: Image(systemName: "phone"), subtitle: AttributedString("phone"))
ActivityItem(icon: Image(systemName: "envelope"), subtitle: AttributedString("envelope"))
ActivityItem(icon: Image(systemName: "message"), subtitle: AttributedString("message"))
ActivityItem(icon: Image(systemName: "video"), subtitle: AttributedString("video"))
} header: {
Text("Normal-Vertical")
}

Section {
ActivityItem(icon: Image(systemName: "phone"), subtitle: AttributedString("phone"), layout: .horizontal)
ActivityItem(icon: Image(systemName: "envelope"), subtitle: AttributedString("envelope"), layout: .horizontal)
ActivityItem(icon: Image(systemName: "message"), subtitle: AttributedString("message"), layout: .horizontal)
ActivityItem(icon: Image(systemName: "video"), subtitle: AttributedString("video"), layout: .horizontal)
} header: {
Text("Normal-Horizontal")
}

Section {
ActivityItem(icon: Image(systemName: "phone"))
ActivityItem(icon: Image(systemName: "envelope"))
ActivityItem(icon: Image(systemName: "message"))
ActivityItem(icon: Image(systemName: "video"))
} header: {
Text("Only Icon")
}

Section {
ActivityItem(subtitle: AttributedString("phone"))
ActivityItem(subtitle: AttributedString("envelope"))
ActivityItem(subtitle: AttributedString("message"))
ActivityItem(subtitle: AttributedString("video"))
} header: {
Text("Only Subtitle")
}
}
.navigationTitle(Text("ActivityItemExample"))
}
}

#Preview {
ActivityItemExample()
}
6 changes: 6 additions & 0 deletions Apps/Examples/Examples/FioriSwiftUICore/CoreContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ struct CoreContentView: View {
var body: some View {
List {
Section(header: Text("Views")) {
NavigationLink {
ActivityItemExample()
} label: {
Text("ActivityItem")
}

NavigationLink(
destination: AvatarStackExample(),
label: {
Expand Down
6 changes: 5 additions & 1 deletion Sources/FioriSwiftUICore/Models/ModelDefinitions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,11 @@ public protocol ActionModel: ActionComponent {}
public protocol TextInputModel: TextInputComponent {}

// sourcery: generated_component
public protocol ActivityItemModel: IconComponent, SubtitleComponent {}
public protocol _ActivityItemModel: IconComponent, SubtitleComponent {}

/// Deprecated ActivityItemModel
@available(*, unavailable, renamed: "_ActivityItemModel", message: "Will be removed in the future release. Please create ActivityItemModel with other initializers instead.")
public protocol ActivityItemModel {}

// sourcery: generated_component_not_configurable
public protocol ActivityItemsModel: ActionItemsComponent {}
Expand Down
4 changes: 2 additions & 2 deletions Sources/FioriSwiftUICore/Views/ActivityItem+View.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import SwiftUI
// FIXME: - Implement Fiori style definitions

extension Fiori {
enum ActivityItem {
enum _ActivityItem {
typealias Icon = EmptyModifier
typealias Subtitle = EmptyModifier
typealias IconCumulative = EmptyModifier
Expand All @@ -30,7 +30,7 @@ extension Fiori {

// FIXME: - Implement ActivityItem View body

extension ActivityItem: View {
extension _ActivityItem: View {
public var body: some View {
VStack {
icon
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import Foundation
import SwiftUI

// swiftlint:disable file_length

/// A view that displays information of an object.
// sourcery: CompositeComponent
protocol _ObjectItemComponent: _TitleComponent, _SubtitleComponent, _FootnoteComponent, _DescriptionComponent, _StatusComponent, _SubstatusComponent, _DetailImageComponent, _IconsComponent, _AvatarsComponent, _FootnoteIconsComponent, _FootnoteIconsTextComponent, _TagsComponent, _ActionComponent {
Expand Down Expand Up @@ -726,3 +728,10 @@ protocol _ProgressIndicatorComponent: _ProgressIndicatorProtocol {}
/// ```
// sourcery: CompositeComponent
protocol _ProcessingIndicatorComponent: _OptionalTitleComponent {}

// sourcery: CompositeComponent
protocol _ActivityItemComponent: _IconComponent, _SubtitleComponent {
/// Activity item layout. The default is .vertical
// sourcery: defaultValue = .vertical
var layout: ActivityItemLayout { get }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import FioriThemeManager
import Foundation
import SwiftUI

/// Activity item layout
public enum ActivityItemLayout {
/// Vertical layout for ActivityItem.
case vertical
/// Horizontal layout for ActivityItem.
case horizontal
}

// Base Layout style
public struct ActivityItemBaseStyle: ActivityItemStyle {
public func makeBody(_ configuration: ActivityItemConfiguration) -> some View {
// Add default layout here
switch configuration.layout {
case .vertical:
VStack {
configuration.icon
configuration.subtitle
}
.typeErased
case .horizontal:
HStack {
configuration.icon
configuration.subtitle
}
.typeErased
}
}
}

// Default fiori styles
extension ActivityItemFioriStyle {
struct ContentFioriStyle: ActivityItemStyle {
func makeBody(_ configuration: ActivityItemConfiguration) -> some View {
ActivityItem(configuration)
}
}

struct IconFioriStyle: IconStyle {
let activityItemConfiguration: ActivityItemConfiguration

func makeBody(_ configuration: IconConfiguration) -> some View {
Icon(configuration)
}
}

struct SubtitleFioriStyle: SubtitleStyle {
let activityItemConfiguration: ActivityItemConfiguration

func makeBody(_ configuration: SubtitleConfiguration) -> some View {
Subtitle(configuration)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// Generated using Sourcery 2.1.7 — https://github.com/krzysztofzablocki/Sourcery
// DO NOT EDIT
import Foundation
import SwiftUI

public struct ActivityItem {
let icon: any View
let subtitle: any View
/// Activity item layout. The default is .vertical
let layout: ActivityItemLayout

@Environment(\.activityItemStyle) var style

fileprivate var _shouldApplyDefaultStyle = true

public init(@ViewBuilder icon: () -> any View = { EmptyView() },
@ViewBuilder subtitle: () -> any View = { EmptyView() },
layout: ActivityItemLayout = .vertical)
{
self.icon = Icon(icon: icon)
self.subtitle = Subtitle(subtitle: subtitle)
self.layout = layout
}
}

public extension ActivityItem {
init(icon: Image? = nil,
subtitle: AttributedString? = nil,
layout: ActivityItemLayout = .vertical)
{
self.init(icon: { icon }, subtitle: { OptionalText(subtitle) }, layout: layout)
}
}

public extension ActivityItem {
init(_ configuration: ActivityItemConfiguration) {
self.init(configuration, shouldApplyDefaultStyle: false)
}

internal init(_ configuration: ActivityItemConfiguration, shouldApplyDefaultStyle: Bool) {
self.icon = configuration.icon
self.subtitle = configuration.subtitle
self.layout = configuration.layout
self._shouldApplyDefaultStyle = shouldApplyDefaultStyle
}
}

extension ActivityItem: View {
public var body: some View {
if self._shouldApplyDefaultStyle {
self.defaultStyle()
} else {
self.style.resolve(configuration: .init(icon: .init(self.icon), subtitle: .init(self.subtitle), layout: self.layout)).typeErased
.transformEnvironment(\.activityItemStyleStack) { stack in
if !stack.isEmpty {
stack.removeLast()
}
}
}
}
}

private extension ActivityItem {
func shouldApplyDefaultStyle(_ bool: Bool) -> some View {
var s = self
s._shouldApplyDefaultStyle = bool
return s
}

func defaultStyle() -> some View {
ActivityItem(.init(icon: .init(self.icon), subtitle: .init(self.subtitle), layout: self.layout))
.shouldApplyDefaultStyle(false)
.activityItemStyle(ActivityItemFioriStyle.ContentFioriStyle())
.typeErased
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Generated using Sourcery 2.1.7 — https://github.com/krzysztofzablocki/Sourcery
// DO NOT EDIT
import Foundation
import SwiftUI

public protocol ActivityItemStyle: DynamicProperty {
associatedtype Body: View

func makeBody(_ configuration: ActivityItemConfiguration) -> Body
}

struct AnyActivityItemStyle: ActivityItemStyle {
let content: (ActivityItemConfiguration) -> any View

init(@ViewBuilder _ content: @escaping (ActivityItemConfiguration) -> any View) {
self.content = content
}

public func makeBody(_ configuration: ActivityItemConfiguration) -> some View {
self.content(configuration).typeErased
}
}

public struct ActivityItemConfiguration {
public let icon: Icon
public let subtitle: Subtitle
public let layout: ActivityItemLayout

public typealias Icon = ConfigurationViewWrapper
public typealias Subtitle = ConfigurationViewWrapper
}

public struct ActivityItemFioriStyle: ActivityItemStyle {
public func makeBody(_ configuration: ActivityItemConfiguration) -> some View {
ActivityItem(configuration)
.iconStyle(IconFioriStyle(activityItemConfiguration: configuration))
.subtitleStyle(SubtitleFioriStyle(activityItemConfiguration: configuration))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public struct ObjectItem {
let footnoteIconsText: any View
let tags: any View
let action: any View
/// For accessory enhancement
let objectItemButton: any View

@Environment(\.objectItemStyle) var style
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
import Foundation
import SwiftUI

/// `ValuePicker` provides a title and value label with Fiori styling and a wheel-style`Picker`.
///
/// `ValuePicker` provides a title and value label with Fiori styling and a wheel-style `Picker`.
/// ## Usage
/// ```swift
/// let valueOptions :[AttributedString] = ["1", "20", "300"]
Expand All @@ -13,24 +12,20 @@ import SwiftUI
/// @State var stateIndex: Int = 0
/// @State var isTrackingLiveChanges = true
/// @State var showsErrorMessage = false
///
/// ValuePicker(title: "Picker Title(Default Style)", isRequired: self.isRequired, options: self.valueOptions, selectedIndex: self.$selectedIndex, isTrackingLiveChanges: self.isTrackingLiveChanges)
/// .informationView(isPresented: self.$showsErrorMessage, description: AttributedString("Please choose one available data"))
/// .informationViewStyle(.informational)
/// ```
public struct ValuePicker {
let title: any View
let valueLabel: any View
let mandatoryFieldIndicator: any View
let isRequired: Bool
let options: [AttributedString]
/// The selected value index of the Value Picker
/// The index for the selected value in the valueOptions.
@Binding var selectedIndex: Int
/// When `isTrackingLiveChanges` is true, the value will be shown every time a selection is made. If it is set to false, the value will only be displayed when the value picker is collapsed. The default setting is true.
var isTrackingLiveChanges: Bool
/// This property indicates whether the picker is to always be displayed. The default is false.
var alwaysShowPicker: Bool
/// The `ControlState` of the view. The default is `normal`
/// The `ControlState` of the view. Currently, `.disabled`, `.normal` and `.readOnly` are supported. The default is `normal`.
let controlState: ControlState

@Environment(\.valuePickerStyle) var style
Expand Down
Loading

0 comments on commit c3a8927

Please sign in to comment.