Skip to content

Commit

Permalink
Merge branch 'main' into user/alboswel/AddListItemToPodspec
Browse files Browse the repository at this point in the history
  • Loading branch information
alexanderboswell authored Jun 17, 2024
2 parents f1bd6d5 + 96fa7ee commit 091b700
Show file tree
Hide file tree
Showing 149 changed files with 4,066 additions and 4,159 deletions.
1 change: 1 addition & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
### Platforms Impacted
- [ ] iOS
- [ ] visionOS
- [ ] macOS

### Description of changes
Expand Down
5 changes: 3 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ on:

jobs:
validation:
runs-on: macos-13
runs-on: macos-14
strategy:
fail-fast: true
steps:
Expand All @@ -24,7 +24,7 @@ jobs:
- name: validation
run: scripts/validation.sh
xcodebuild:
runs-on: macos-13
runs-on: macos-14
strategy:
fail-fast: false
matrix:
Expand All @@ -33,6 +33,7 @@ jobs:
'macos_build FluentUITestApp-macOS Debug build -resultBundlePath TestResultsMac test -destination "platform=macOS,arch=x86_64"',
'ios_simulator_build Demo.Development Debug build test -resultBundlePath TestResultsiOS -destination "platform=iOS Simulator,name=iPhone 14 Pro"',
'ios_device_build Demo.Development Release build',
'visionos_simulator_build Demo.Development Debug build',
]

steps:
Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/localize.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ jobs:
Localize:
runs-on: ubuntu-latest
environment: localization
permissions:
actions: read
contents: read
deployments: read
packages: read
pull-requests: write

steps:
- uses: actions/checkout@v3
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/podPublish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:
- 0.2.[0-9]+_main_0.2
jobs:
Pod-Publish:
runs-on: macos-13
runs-on: macos-14

steps:
- uses: actions/checkout@v3
Expand Down
4 changes: 2 additions & 2 deletions MicrosoftFluentUI.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'MicrosoftFluentUI'
s.version = '0.24.0'
s.version = '0.28.0'
s.summary = 'Fluent UI is a set of reusable UI controls and tools'
s.homepage = "https://www.microsoft.com/design/fluent/#/"
s.license = { :type => 'MIT', :file => 'LICENSE' }
Expand All @@ -12,7 +12,7 @@ Pod::Spec.new do |s|

# iOS

s.ios.deployment_target = "15.0"
s.ios.deployment_target = "16.0"

s.subspec 'Avatar_ios' do |avatar_ios|
avatar_ios.platform = :ios
Expand Down
5 changes: 3 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ let package = Package(
name: "FluentUI",
defaultLocalization: "en",
platforms: [
.iOS(.v15),
.iOS(.v16),
.macOS(.v12),
.visionOS(.v1),
],
products: [
.library(
Expand All @@ -22,7 +23,7 @@ let package = Package(
.target(
name: "FluentUI",
dependencies: [
.target(name: "FluentUI_ios", condition: .when(platforms: [.iOS])),
.target(name: "FluentUI_ios", condition: .when(platforms: [.iOS, .visionOS, .macCatalyst])),
.target(name: "FluentUI_macos", condition: .when(platforms: [.macOS]))
],
path: "public"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Fluent UI Apple contains native UIKit and AppKit controls aligned with [Microsof
#### Requirements

- iOS 15+ or macOS 12+
- Xcode 15.0.1+
- Xcode 15.3+
- Swift 5.9+

#### Using Swift Package Manager
Expand Down
2 changes: 1 addition & 1 deletion SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).

If you believe you have found a security vulnerability in any Microsoft-owned repository that meets Microsoft's [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)) of a security vulnerability, please report it to us as described below.
If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)), please report it to us as described below.

## Reporting Security Issues

Expand Down
76 changes: 56 additions & 20 deletions ios/FluentUI.Demo/FluentUI.Demo.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

14 changes: 8 additions & 6 deletions ios/FluentUI.Demo/FluentUI.Demo/BrandedSwitch.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,15 @@ class BrandedSwitch: UISwitch {
override init(frame: CGRect) {
super.init(frame: frame)

NotificationCenter.default.addObserver(forName: .didChangeTheme,
object: nil,
queue: nil) { [weak self] notification in
notificationObserver = NotificationCenter.default.addObserver(forName: .didChangeTheme,
object: nil,
queue: nil) { [weak self] notification in
guard let strongSelf = self,
let themeView = notification.object as? UIView,
strongSelf.isDescendant(of: themeView)
FluentTheme.isApplicableThemeChange(notification, for: strongSelf)
else {
return
}
strongSelf.onTintColor = themeView.fluentTheme.color(.brandForeground1)
strongSelf.onTintColor = strongSelf.fluentTheme.color(.brandForeground1)
}
}

Expand All @@ -34,4 +33,7 @@ class BrandedSwitch: UISwitch {
}
onTintColor = newWindow.fluentTheme.color(.brandForeground1)
}

/// Stores the notification handler for .didChangeTheme notifications.
private var notificationObserver: NSObjectProtocol?
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class ColoredPillBackgroundView: UIView {
}

@objc func themeDidChange(_ notification: Notification) {
guard let themeView = notification.object as? UIView, self.isDescendant(of: themeView) else {
guard FluentTheme.isApplicableThemeChange(notification, for: self) else {
return
}
updateBackgroundColor()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import FluentUI
import SwiftUI
import UIKit

/// Callbacks for changes to a `DemoAppearanceView` via the `DemoAppearanceController`. This delegate should
/// Callbacks for changes to a `DemoAppearanceMenu` via the `DemoAppearanceControlView`. This delegate should
/// ensure that the appropriate token overrides are set when these callbacks are received.
@objc(MSFDemoAppearanceDelegate)
protocol DemoAppearanceDelegate: NSObjectProtocol {
Expand All @@ -34,38 +34,20 @@ protocol DemoAppearanceDelegate: NSObjectProtocol {
@objc func isThemeWideOverrideApplied() -> Bool
}

@objc(MSFDemoAppearanceControllerWrapper)
class DemoAppearanceControllerWrapper: NSObject {
/// Convenience wrapper to allow creation of a `DemoAppearanceController` from Objective-C.
///
/// The class itself cannot be represented via `@objc` because it inherits from `UIHostingController`, which is a Swift-only class.
/// This workaround allows us to create one anyway, though it will be type-erased to `UIViewController` in the process.
///
/// - Parameter delegate: An optional `DemoAppearanceDelegate` for the created `DemoAppearanceController`.
///
/// - Returns: A new `DemoAppearanceController`, type-erased to `UIViewController`.
@available(swift, obsoleted: 1.0, message: "This method exists for Objective-C backwards compatibility and should not be invoked from Swift. Please create a `DemoAppearanceController` instance directly.")
@objc static func createDemoAppearanceController(delegate: DemoAppearanceDelegate?) -> UIViewController {
return DemoAppearanceController(delegate: delegate)
}
}

/// Wrapper class to allow presenting of `DemoAppearanceView` from a UIKit host.
class DemoAppearanceController: UIHostingController<DemoAppearanceView>, ObservableObject {
/// Wrapper class to allow presenting of `DemoAppearanceMenu` from a UIKit host.
@objc(MSFDemoAppearanceControlView)
class DemoAppearanceControlView: FluentUI.ControlHostingView, ObservableObject {
@objc(initWithDelegate:)
init(delegate: DemoAppearanceDelegate?) {
let configuration = DemoAppearanceView.Configuration(delegate: delegate)
let configuration = DemoAppearanceMenu.Configuration(delegate: delegate)
self.configuration = configuration

super.init(rootView: DemoAppearanceView(configuration: configuration))
super.init(AnyView(DemoAppearanceMenu(configuration: configuration)))

configuration.onWindowThemeChanged = self.onWindowThemeChanged(_:)
configuration.onAppWideThemeChanged = self.onAppWideThemeChanged(_:)
configuration.onUserInterfaceStyleChanged = self.onUserInterfaceStyleChanged(_:)

self.modalPresentationStyle = .popover
self.preferredContentSize.height = 400
self.popoverPresentationController?.permittedArrowDirections = .up

// Different themes can have different overrides, so update our state when we detect a theme change.
self.themeObserver = NotificationCenter.default.addObserver(forName: .didChangeTheme, object: nil, queue: nil) { [weak self] _ in
DispatchQueue.main.async {
Expand All @@ -78,23 +60,20 @@ class DemoAppearanceController: UIHostingController<DemoAppearanceView>, Observa
preconditionFailure("init(coder:) has not been implemented")
}

override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
updateToggleConfiguration()
configuration.isConfigured = true
@MainActor required dynamic init(rootView: AnyView) {
preconditionFailure("init(rootView:) has not been implemented")
}

override func willMove(toParent parent: UIViewController?) {
guard let parent,
let window = parent.view.window else {
return
}

rootView.fluentTheme = window.fluentTheme
override func didMoveToWindow() {
super.didMoveToWindow()
updateToggleConfiguration()
}

private func updateToggleConfiguration() {
configuration.userInterfaceStyle = view.window?.overrideUserInterfaceStyle ?? .unspecified
guard let window else {
return
}
configuration.userInterfaceStyle = window.overrideUserInterfaceStyle
configuration.windowTheme = currentDemoListViewController?.theme ?? .default
configuration.appWideTheme = DemoColorTheme.currentAppWideTheme
if let isThemeOverrideEnabled = configuration.themeOverridePreviouslyApplied {
Expand All @@ -106,12 +85,10 @@ class DemoAppearanceController: UIHostingController<DemoAppearanceView>, Observa
/// Callback for handling per-window theme changes.
private func onWindowThemeChanged(_ theme: DemoColorTheme) {
guard let currentDemoListViewController = currentDemoListViewController,
let window = view.window else {
return
}
let window else {
return
}
currentDemoListViewController.updateColorProviderFor(window: window, theme: theme)

rootView.fluentTheme = window.fluentTheme
}

/// Callback for handling app-wide theme changes
Expand All @@ -121,23 +98,23 @@ class DemoAppearanceController: UIHostingController<DemoAppearanceView>, Observa

/// Callback for handling color scheme changes.
private func onUserInterfaceStyleChanged(_ userInterfaceStyle: UIUserInterfaceStyle) {
view.window?.overrideUserInterfaceStyle = userInterfaceStyle
window?.overrideUserInterfaceStyle = userInterfaceStyle
}

private var currentDemoListViewController: DemoListViewController? {
guard let navigationController = view.window?.rootViewController as? UINavigationController,
guard let navigationController = window?.rootViewController as? UINavigationController,
let currentDemoListViewController = navigationController.viewControllers.first as? DemoListViewController else {
return nil
}
return currentDemoListViewController
}

private var configuration: DemoAppearanceView.Configuration
private var configuration: DemoAppearanceMenu.Configuration
private var themeObserver: NSObjectProtocol?
}

extension DemoAppearanceView.Configuration {
/// Allows `DemoAppearanceView.Configuration` to be initialized with an optional instance of `DemoAppearanceDelegate`.
extension DemoAppearanceMenu.Configuration {
/// Allows `DemoAppearanceMenu.Configuration` to be initialized with an optional instance of `DemoAppearanceDelegate`.
convenience init(delegate: DemoAppearanceDelegate?) {
self.init()

Expand All @@ -150,7 +127,7 @@ extension DemoAppearanceView.Configuration {
self.onThemeWideOverrideChanged = { [weak delegate] isOverrideEnabled in
delegate?.themeWideOverrideDidChange(isOverrideEnabled: isOverrideEnabled)
}
self.onPerControlOverrideChanged = { [weak delegate]isOverrideEnabled in
self.onPerControlOverrideChanged = { [weak delegate] isOverrideEnabled in
delegate?.perControlOverrideDidChange(isOverrideEnabled: isOverrideEnabled)
}
self.themeOverridePreviouslyApplied = { [weak delegate] in
Expand Down
Loading

0 comments on commit 091b700

Please sign in to comment.