Skip to content

Commit

Permalink
Merge branch 'visionOS'
Browse files Browse the repository at this point in the history
  • Loading branch information
davxu committed Dec 15, 2023
2 parents ba03a23 + f0510a4 commit 1c12ede
Show file tree
Hide file tree
Showing 17 changed files with 305 additions and 76 deletions.
15 changes: 12 additions & 3 deletions Apps/Examples/Examples.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
1F60179929A8439A00DBDCDE /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F60179829A8439A00DBDCDE /* ContentView.swift */; };
1F60179B29A8439C00DBDCDE /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1F60179A29A8439C00DBDCDE /* Assets.xcassets */; };
1F60179E29A8439C00DBDCDE /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1F60179D29A8439C00DBDCDE /* Preview Assets.xcassets */; };
1F6017A129A8439C00DBDCDE /* WatchExamples Watch App.app in Embed Watch Content */ = {isa = PBXBuildFile; fileRef = 1F60179429A8439A00DBDCDE /* WatchExamples Watch App.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
1F6017A129A8439C00DBDCDE /* WatchExamples Watch App.app in Embed Watch Content */ = {isa = PBXBuildFile; fileRef = 1F60179429A8439A00DBDCDE /* WatchExamples Watch App.app */; platformFilter = ios; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
1F6017A729A8450E00DBDCDE /* FioriThemeManager in Frameworks */ = {isa = PBXBuildFile; productRef = 1F6017A629A8450E00DBDCDE /* FioriThemeManager */; };
1F6017A829A8450E00DBDCDE /* FioriThemeManager in Embed Frameworks */ = {isa = PBXBuildFile; productRef = 1F6017A629A8450E00DBDCDE /* FioriThemeManager */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
1F6017AD29A8481A00DBDCDE /* Colors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A6DE30A28DD27F9003222E3 /* Colors.swift */; };
Expand Down Expand Up @@ -852,6 +852,7 @@
/* Begin PBXTargetDependency section */
1F6017A029A8439C00DBDCDE /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
platformFilter = ios;
target = 1F60179329A8439A00DBDCDE /* WatchExamples Watch App */;
targetProxy = 1F60179F29A8439C00DBDCDE /* PBXContainerItemProxy */;
};
Expand Down Expand Up @@ -1066,8 +1067,12 @@
);
PRODUCT_BUNDLE_IDENTIFIER = "com.sap.cloud-sdk-ios-fiori.Examples";
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator xros xrsimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TARGETED_DEVICE_FAMILY = "1,2,7";
};
name = Debug;
};
Expand All @@ -1088,8 +1093,12 @@
);
PRODUCT_BUNDLE_IDENTIFIER = "com.sap.cloud-sdk-ios-fiori.Examples";
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator xros xrsimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TARGETED_DEVICE_FAMILY = "1,2,7";
};
name = Release;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,13 @@ class ImageSaver: NSObject {
@objc func saveError(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) {}
}

#if !os(visionOS)
public extension View {
func asUIImage() -> UIImage {
let hostingController = UIHostingController(rootView: self)

hostingController.view.frame = CGRect(x: 0, y: CGFloat(Int.max), width: 1, height: 1)
UIApplication.shared.windows.first!.rootViewController?.view.addSubview(hostingController.view)

let size = hostingController.sizeThatFits(in: UIScreen.main.bounds.size)
hostingController.view.bounds = CGRect(origin: .zero, size: size)
hostingController.view.sizeToFit()
Expand All @@ -97,3 +97,4 @@ public extension UIView {
}
}
}
#endif
75 changes: 75 additions & 0 deletions [email protected]
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// swift-tools-version:5.9
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "FioriSwiftUI",
defaultLocalization: "en",
platforms: [.iOS(.v16), .watchOS(.v7), .visionOS(.v1)],
products: [
.library(
name: "FioriSwiftUI",
type: .dynamic,
targets: ["FioriSwiftUI"]
),
.library(
name: "FioriCharts",
type: .dynamic,
targets: ["FioriCharts"]
),
.library(
name: "FioriThemeManager",
type: .dynamic,
targets: ["FioriThemeManager"]
)
],
dependencies: [
// Dependencies declare other packages that this package depends on.
],
targets: [
.target(
name: "FioriSwiftUI",
dependencies: [.target(name: "FioriSwiftUICore", condition: .when(platforms: [.iOS, .visionOS]))]
),
.target(
name: "FioriCharts",
dependencies: ["FioriThemeManager"],
exclude: ["TestCases/SF_EnergyBenchmarking.csv"]
),
.target(
name: "FioriSwiftUICore",
dependencies: [
.target(name: "FioriThemeManager", condition: .when(platforms: [.iOS, .visionOS])),
.target(name: "FioriCharts", condition: .when(platforms: [.iOS, .visionOS]))
],
resources: [.process("FioriSwiftUICore.strings")]
),
.target(
name: "FioriThemeManager",
dependencies: [],
resources: [
.process("72-Fonts/Resources"),
.process("FioriIcons/Resources/FioriIcon.xcassets")
]
),
.testTarget(
name: "FioriThemeManagerTests",
dependencies: ["FioriThemeManager"],
path: "Tests/FioriSwiftUITests/FioriThemeManager",
resources: [
.process("TestResources")
]
),
.testTarget(
name: "FioriChartsTests",
dependencies: ["FioriCharts"],
path: "Tests/FioriSwiftUITests/FioriCharts"
),
.testTarget(
name: "FioriSwiftUICoreTests",
dependencies: ["FioriSwiftUICore"],
path: "Tests/FioriSwiftUITests/FioriSwiftUICore"
)
]
)
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ This project is the SwiftUI implementation of the [SAP Fiori for iOS Design Lang
This project currently contains three modules: `FioriThemeManager`, `FioriSwiftUICore`, and `FioriCharts`.

## FioriThemeManager
![FioriThemeManager platform support: iOS and watchOS](https://img.shields.io/badge/platform-ios%20%7C%20watchos-lightgray)
![FioriThemeManager platform support: iOS, visionOS, watchOS](https://img.shields.io/badge/platform-ios%20%7C%20visionos%20%7C%20watchos-lightgray)

This module provides a [color palette](https://experience.sap.com/fiori-design-ios/article/colors/) and a new font family [SAP 72](https://experience.sap.com/72/) that conform to [Fiori Design Language](https://experience.sap.com/fiori-design-ios/). It is adopted by all the Fiori components in both this package and SAPFiori.

Expand All @@ -43,7 +43,7 @@ All Fiori Colors are dynamic colors, which means they will adjust based on iOS A
> Custom fonts need to be loaded and registered during App's runtime. Make sure you call `Font.registerFioriFonts()` inside `application(_:didFinishLaunchingWithOptions:)` of your `AppDelegate`.
## FioriSwiftUICore
![FioriSwiftUICore platform support: iOS only](https://img.shields.io/badge/platform-ios-lightgray)
![FioriSwiftUICore platform support: iOS and visionOS](https://img.shields.io/badge/platform-ios%20%7C%20visionos-lightgray)

This module contains SwiftUI implementation for those UIKit-based components existing in [SAPFiori](https://help.sap.com/doc/978e4f6c968c4cc5a30f9d324aa4b1d7/Latest/en-US/Documents/Frameworks/SAPFiori/index.html). It provides you with an easy way to migrate your UIKit project to SwiftUI while delivering the same experience as before.

Expand Down Expand Up @@ -84,7 +84,7 @@ We plan to progressively bring more Fiori UI components into this module in the
| TouchIDErrorView | :x: |

## FioriCharts
![FioriCharts platform support: iOS only](https://img.shields.io/badge/platform-ios-lightgray)
![FioriCharts platform support: iOS and visionOS](https://img.shields.io/badge/platform-ios%20%7C%20visionos-lightgray)

The FioriCharts module replaces the *RoambiChartKit* charting library which was already embedded in SAPFiori. Migrating to SwiftUI gives the ability to easily add new chart components (donut, bullet, stocks, etc.) while modernizing the existing supported charts with pinch-to-zoom, pan, and new design features.

Expand Down
2 changes: 1 addition & 1 deletion Sources/FioriCharts/Extensions/String+Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import SwiftUI

extension String {
func boundingBoxSize(with fontSize: CGFloat) -> CGSize {
#if os(iOS) || os(tvOS) || os(watchOS)
#if os(iOS) || os(tvOS) || os(watchOS) || os(visionOS)
let font = UIFont.systemFont(ofSize: fontSize)
#elseif os(macOS)
let font = NSFont.systemFont(ofSize: fontSize)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ struct CancellableResettableDialogForm<Title: View, CancelAction: View, ResetAct
components
applyAction
}
.frame(width: UIDevice.current.userInterfaceIdiom == .pad ? 375 : UIScreen.main.bounds.size.width)
.frame(width: UIDevice.current.userInterfaceIdiom == .pad ? 375 : Screen.bounds.size.width)
.padding([.top, .bottom], UIDevice.current.userInterfaceIdiom == .pad ? 13 : 16)
}
}
Expand All @@ -49,7 +49,7 @@ struct ApplyButtonStyle: PrimitiveButtonStyle {
if self.isEnabled {
configuration.label
.frame(width: UIDevice.current.userInterfaceIdiom == .pad ? 375 - 13 * 2 :
UIScreen.main.bounds.size.width - 16 * 2)
Screen.bounds.size.width - 16 * 2)
.padding([.top, .bottom], 8)
.font(.body)
.fontWeight(.bold)
Expand All @@ -62,7 +62,7 @@ struct ApplyButtonStyle: PrimitiveButtonStyle {
} else {
configuration.label
.frame(width: UIDevice.current.userInterfaceIdiom == .pad ? 375 - 13 * 2 :
UIScreen.main.bounds.size.width - 16 * 2)
Screen.bounds.size.width - 16 * 2)
.padding([.top, .bottom], 8)
.font(.body)
.fontWeight(.bold)
Expand Down
26 changes: 14 additions & 12 deletions Sources/FioriSwiftUICore/DataTable/DataTable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public struct DataTable: View {
self.layoutManager = TableLayoutManager(model: model)
}
}

/// Body of the View
public var body: some View {
GeometryReader { proxy in
Expand All @@ -75,7 +75,7 @@ public struct DataTable: View {
}
}
}

if !self.model.showListView {
ScrollAndZoomView(layoutManager: self.layoutManager, size: rect.size)
}
Expand All @@ -90,22 +90,24 @@ public struct DataTable: View {
self.layoutManager.keyboardFrame = .zero
self.layoutManager.keyboardHeight = 0
}
.onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)) { _ in
// save text changes
self.layoutManager.saveEditingTextChange()
#if !os(visionOS)
.onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)) { _ in
// save text changes
self.layoutManager.saveEditingTextChange()

if self.layoutManager.currentCell != nil {
self.layoutManager.currentCell = nil
if self.layoutManager.currentCell != nil {
self.layoutManager.currentCell = nil
}
}
}
#endif
.onChange(of: self.dynamicTypeSize) { newValue in
self.layoutManager.dynamicTypeSize = newValue
self.layoutManager.cacheLayoutDataForMeasurement = nil
self.layoutManager.layoutData = nil
}
.clipped()
.environmentObject(self.layoutManager)
.background(self.model.backgroundColor)
.environmentObject(self.layoutManager)
.background(self.model.backgroundColor)
}
}

Expand Down Expand Up @@ -153,7 +155,7 @@ public extension DataTable {
@available(*, deprecated)
func editingMode(_ value: Bool = false) -> DataTable {
self.model.isEditing = value

return self
}

Expand Down Expand Up @@ -236,7 +238,7 @@ public extension DataTable {
func sizeThatFits(_ size: CGSize) -> CGSize {
self.layoutManager.sizeThatFits(size)
}

/// Returns the rect for the specified cell with rowIndex and columnIndex
/// - Parameter rowIndex: the row index; rowIndex starts from header if it exists
/// - Parameter columnIndex: the column index
Expand Down
10 changes: 9 additions & 1 deletion Sources/FioriSwiftUICore/DataTable/InlineEditingView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ struct InlineEditingView: View {
self._editingText = State(initialValue: dataItem?.text ?? "")
self._isValid = State(initialValue: (dataItem?.isValid ?? true, ""))
}

var toolbarItemPlacement: ToolbarItemPlacement {
#if os(visionOS)
return .automatic
#else
return .keyboard
#endif
}

var body: some View {
let dataItem = self.layoutData.allDataItems[self.rowIndex][self.columnIndex]
Expand Down Expand Up @@ -109,7 +117,7 @@ struct InlineEditingView: View {
.frame(width: cellWidth, height: cellHeight)
.border(isValid.0 ? Color.preferredColor(.tintColor) : Color.preferredColor(.negativeLabel), width: 2)
.toolbar {
ToolbarItemGroup(placement: .keyboard) {
ToolbarItemGroup(placement: toolbarItemPlacement) {
Spacer()

Button {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@ struct PopoverModifier<PopView: View>: ViewModifier {
popover.dismiss()
}
}
#if !os(visionOS)
.onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)) { _ in
guard let popover = popover else { return }
popover.dismiss()
}
#endif
}
}
}
22 changes: 22 additions & 0 deletions Sources/FioriSwiftUICore/Utils/Screen.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import Foundation
import UIKit

struct Screen {
private init() {}

static var scale: CGFloat {
#if os(visionOS)
1.0
#else
UIScreen.main.scale
#endif
}

static var bounds: CGRect {
#if os(visionOS)
CGRect(x: 0, y: 0, width: 1280, height: 720) // default window size for visionOS
#else
UIScreen.main.bounds
#endif
}
}
18 changes: 12 additions & 6 deletions Sources/FioriSwiftUICore/Views/KPIHeader/KPIHeaderContent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,18 @@ extension KPIHeaderContent {
}

private var resizePublisher: AnyPublisher<Void, Never> {
let orientationPublisher = NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)
.compactMap { _ in () }
let sizeCategoryPublisher = NotificationCenter.default.publisher(for: UIContentSizeCategory.didChangeNotification)
.compactMap { _ in () }
return Publishers.Merge(orientationPublisher, sizeCategoryPublisher)
.eraseToAnyPublisher()
#if os(visionOS)
let sizeCategoryPublisher = NotificationCenter.default.publisher(for: UIContentSizeCategory.didChangeNotification)
.compactMap { _ in () }
return sizeCategoryPublisher.eraseToAnyPublisher()
#else
let orientationPublisher = NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)
.compactMap { _ in () }
let sizeCategoryPublisher = NotificationCenter.default.publisher(for: UIContentSizeCategory.didChangeNotification)
.compactMap { _ in () }
return Publishers.Merge(orientationPublisher, sizeCategoryPublisher)
.eraseToAnyPublisher()
#endif
}

private var minItemSpacing: CGFloat {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -299,10 +299,10 @@ struct DateTimeMenuItem: View {
)
.datePickerStyle(.graphical)
.labelsHidden()
.frame(width: UIDevice.current.userInterfaceIdiom == .pad ? 375 - 13 : UIScreen.main.bounds.size.width - 16)
.frame(width: UIDevice.current.userInterfaceIdiom == .pad ? 375 - 13 : Screen.bounds.size.width - 16)
.clipped()
}
.frame(width: UIDevice.current.userInterfaceIdiom == .pad ? 375 : UIScreen.main.bounds.size.width)
.frame(width: UIDevice.current.userInterfaceIdiom == .pad ? 375 : Screen.bounds.size.width)
}
.readHeight()
.onPreferenceChange(HeightPreferenceKey.self) { height in
Expand Down
Loading

0 comments on commit 1c12ede

Please sign in to comment.