Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 0 additions & 32 deletions .vscode/mcp.json

This file was deleted.

17 changes: 17 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,23 @@ The project uses **swift-testing framework** (not XCTest):
- Use `@Test` attribute for test functions
- Use `#expect()` for assertions instead of XCTest assertions
- No comments in test case bodies - keep tests clean and self-explanatory
- For floating-point comparisons, use `isApproximatelyEqual` instead of `==` to handle precision issues:
```swift
#expect(value.isApproximatelyEqual(to: expectedValue))
```

### Compatibility Tests

When writing tests in `OpenSwiftUICompatibilityTests`:
- **DO NOT add conditional imports** - imports are handled in `Export.swift`
- **NEVER use module-qualified types** (e.g., `SwiftUI.PeriodicTimelineSchedule`)
- Write test code that works identically with both SwiftUI and OpenSwiftUI
- Simply use types directly without any module prefixes:
```swift
// No conditional imports needed - Export.swift handles this
let schedule = PeriodicTimelineSchedule(from: startDate, by: interval)
let entries = schedule.entries(from: queryDate, mode: .normal)
```

### Code Style (from .github/copilot-instructions.md)

Expand Down
79 changes: 26 additions & 53 deletions Example/Example.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,28 @@
objects = {

/* Begin PBXBuildFile section */
27186AE02D538A6B009E05F9 /* RenderBox.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27E6C4D42D2842810010502F /* RenderBox.xcframework */; };
27186AE32D538A76009E05F9 /* AttributeGraph.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27E6C4D12D2842740010502F /* AttributeGraph.xcframework */; };
278EF52D2E2272F2009C32EB /* Equatable in Frameworks */ = {isa = PBXBuildFile; productRef = 278EF52C2E2272F2009C32EB /* Equatable */; };
278EF52F2E227304009C32EB /* Equatable in Frameworks */ = {isa = PBXBuildFile; productRef = 278EF52E2E227304009C32EB /* Equatable */; };
279284972DFF136E00234D64 /* AttributeGraph.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27E6C4D12D2842740010502F /* AttributeGraph.xcframework */; };
279284982DFF136E00234D64 /* AttributeGraph.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 27E6C4D12D2842740010502F /* AttributeGraph.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
279284992DFF136E00234D64 /* CoreUI.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27EE91722DD0C753006C85FD /* CoreUI.xcframework */; };
2792849A2DFF136E00234D64 /* CoreUI.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 27EE91722DD0C753006C85FD /* CoreUI.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
2792849B2DFF136E00234D64 /* RenderBox.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27E6C4D42D2842810010502F /* RenderBox.xcframework */; };
2792849C2DFF136E00234D64 /* RenderBox.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 27E6C4D42D2842810010502F /* RenderBox.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
2792849F2DFF137400234D64 /* SnapshotTesting in Frameworks */ = {isa = PBXBuildFile; productRef = 2792849E2DFF137400234D64 /* SnapshotTesting */; };
279FED052DF4566D00320390 /* AttributeGraph.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27E6C4D12D2842740010502F /* AttributeGraph.xcframework */; };
279FED062DF4566D00320390 /* AttributeGraph.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 27E6C4D12D2842740010502F /* AttributeGraph.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
279FED082DF4567000320390 /* CoreUI.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27EE91722DD0C753006C85FD /* CoreUI.xcframework */; };
279FED092DF4567000320390 /* CoreUI.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 27EE91722DD0C753006C85FD /* CoreUI.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
279FED0A2DF4567400320390 /* RenderBox.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27E6C4D42D2842810010502F /* RenderBox.xcframework */; };
279FED0B2DF4567400320390 /* RenderBox.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 27E6C4D42D2842810010502F /* RenderBox.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
279FED0D2DF4567B00320390 /* OpenSwiftUI in Frameworks */ = {isa = PBXBuildFile; productRef = 279FED0C2DF4567B00320390 /* OpenSwiftUI */; };
27AF22B22E758F2900D534AB /* CoreUI.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27EE91722DD0C753006C85FD /* CoreUI.xcframework */; };
27AF22B32E758F2900D534AB /* CoreUI.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27EE91722DD0C753006C85FD /* CoreUI.xcframework */; };
27AF22B42E758F2900D534AB /* CoreUI.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27EE91722DD0C753006C85FD /* CoreUI.xcframework */; };
27AF22B52E758F2900D534AB /* CoreUI.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27EE91722DD0C753006C85FD /* CoreUI.xcframework */; };
27AF22B62E758F2E00D534AB /* BacklightServices.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27AF22B12E758F0F00D534AB /* BacklightServices.xcframework */; platformFilters = (ios, xros, ); };
27AF22B72E758F2E00D534AB /* BacklightServices.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27AF22B12E758F0F00D534AB /* BacklightServices.xcframework */; platformFilters = (ios, xros, ); };
27AF22B82E758F2E00D534AB /* BacklightServices.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27AF22B12E758F0F00D534AB /* BacklightServices.xcframework */; platformFilters = (ios, xros, ); };
27AF22B92E758F2E00D534AB /* BacklightServices.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27AF22B12E758F0F00D534AB /* BacklightServices.xcframework */; platformFilters = (ios, xros, ); };
27AF22BA2E758F3700D534AB /* RenderBox.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27E6C4D42D2842810010502F /* RenderBox.xcframework */; };
27AF22BB2E758F3700D534AB /* RenderBox.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27E6C4D42D2842810010502F /* RenderBox.xcframework */; };
27AF22BC2E758F3700D534AB /* RenderBox.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27E6C4D42D2842810010502F /* RenderBox.xcframework */; };
27AF22BD2E758F3700D534AB /* RenderBox.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27E6C4D42D2842810010502F /* RenderBox.xcframework */; };
27CD0B5F2AFC8DA7003665EB /* OpenSwiftUI in Frameworks */ = {isa = PBXBuildFile; productRef = 27CD0B5E2AFC8DA7003665EB /* OpenSwiftUI */; };
27D49E0E2BA60AF600F6E2E2 /* OpenSwiftUI in Frameworks */ = {isa = PBXBuildFile; productRef = 27D49E0D2BA60AF600F6E2E2 /* OpenSwiftUI */; };
27E6C4D32D2842740010502F /* AttributeGraph.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27E6C4D12D2842740010502F /* AttributeGraph.xcframework */; };
27E6C4D62D2842810010502F /* RenderBox.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27E6C4D42D2842810010502F /* RenderBox.xcframework */; };
27EE91732DD0C753006C85FD /* CoreUI.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27EE91722DD0C753006C85FD /* CoreUI.xcframework */; };
27EE91762DD0C77E006C85FD /* CoreUI.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27EE91722DD0C753006C85FD /* CoreUI.xcframework */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand All @@ -50,39 +48,11 @@
};
/* End PBXContainerItemProxy section */

/* Begin PBXCopyFilesBuildPhase section */
2792849D2DFF136E00234D64 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
2792849A2DFF136E00234D64 /* CoreUI.xcframework in Embed Frameworks */,
279284982DFF136E00234D64 /* AttributeGraph.xcframework in Embed Frameworks */,
2792849C2DFF136E00234D64 /* RenderBox.xcframework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
279FED072DF4566D00320390 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
279FED092DF4567000320390 /* CoreUI.xcframework in Embed Frameworks */,
279FED062DF4566D00320390 /* AttributeGraph.xcframework in Embed Frameworks */,
279FED0B2DF4567400320390 /* RenderBox.xcframework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
271D81642BB1E8E300A6D543 /* OpenAttributeGraph */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = OpenAttributeGraph; path = ../../OpenAttributeGraph; sourceTree = "<group>"; };
275751E32DEE1441003E467C /* TestingHost.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TestingHost.app; sourceTree = BUILT_PRODUCTS_DIR; };
279283B92DFF11CE00234D64 /* OpenSwiftUIUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OpenSwiftUIUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
27AF22B12E758F0F00D534AB /* BacklightServices.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = BacklightServices.xcframework; path = ../../DarwinPrivateFrameworks/BLS/2024/BacklightServices.xcframework; sourceTree = "<group>"; };
27B7FC802BB31FF500272BA5 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
27CD0B492AFC8D37003665EB /* Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Example.app; sourceTree = BUILT_PRODUCTS_DIR; };
27CD0B612AFC8E0E003665EB /* OpenSwiftUI */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = OpenSwiftUI; path = ..; sourceTree = "<group>"; };
Expand Down Expand Up @@ -133,44 +103,48 @@
buildActionMask = 2147483647;
files = (
279FED0D2DF4567B00320390 /* OpenSwiftUI in Frameworks */,
279FED082DF4567000320390 /* CoreUI.xcframework in Frameworks */,
27AF22B82E758F2E00D534AB /* BacklightServices.xcframework in Frameworks */,
27AF22B42E758F2900D534AB /* CoreUI.xcframework in Frameworks */,
27AF22BC2E758F3700D534AB /* RenderBox.xcframework in Frameworks */,
279FED052DF4566D00320390 /* AttributeGraph.xcframework in Frameworks */,
279FED0A2DF4567400320390 /* RenderBox.xcframework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
279283B62DFF11CE00234D64 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
279284992DFF136E00234D64 /* CoreUI.xcframework in Frameworks */,
2792849F2DFF137400234D64 /* SnapshotTesting in Frameworks */,
27AF22B92E758F2E00D534AB /* BacklightServices.xcframework in Frameworks */,
27AF22B52E758F2900D534AB /* CoreUI.xcframework in Frameworks */,
27AF22BD2E758F3700D534AB /* RenderBox.xcframework in Frameworks */,
279284972DFF136E00234D64 /* AttributeGraph.xcframework in Frameworks */,
2792849B2DFF136E00234D64 /* RenderBox.xcframework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
27CD0B462AFC8D37003665EB /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
27AF22B22E758F2900D534AB /* CoreUI.xcframework in Frameworks */,
27AF22B62E758F2E00D534AB /* BacklightServices.xcframework in Frameworks */,
27CD0B5F2AFC8DA7003665EB /* OpenSwiftUI in Frameworks */,
27E6C4D62D2842810010502F /* RenderBox.xcframework in Frameworks */,
278EF52F2E227304009C32EB /* Equatable in Frameworks */,
27EE91762DD0C77E006C85FD /* CoreUI.xcframework in Frameworks */,
27E6C4D32D2842740010502F /* AttributeGraph.xcframework in Frameworks */,
27AF22BA2E758F3700D534AB /* RenderBox.xcframework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
27D49DF52BA604FB00F6E2E2 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
27AF22B32E758F2900D534AB /* CoreUI.xcframework in Frameworks */,
27AF22B72E758F2E00D534AB /* BacklightServices.xcframework in Frameworks */,
27D49E0E2BA60AF600F6E2E2 /* OpenSwiftUI in Frameworks */,
27EE91732DD0C753006C85FD /* CoreUI.xcframework in Frameworks */,
278EF52D2E2272F2009C32EB /* Equatable in Frameworks */,
27186AE02D538A6B009E05F9 /* RenderBox.xcframework in Frameworks */,
27186AE32D538A76009E05F9 /* AttributeGraph.xcframework in Frameworks */,
27AF22BB2E758F3700D534AB /* RenderBox.xcframework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -211,6 +185,7 @@
27D49E0C2BA60AF600F6E2E2 /* Frameworks */ = {
isa = PBXGroup;
children = (
27AF22B12E758F0F00D534AB /* BacklightServices.xcframework */,
27EE91722DD0C753006C85FD /* CoreUI.xcframework */,
27E6C4D42D2842810010502F /* RenderBox.xcframework */,
27E6C4D12D2842740010502F /* AttributeGraph.xcframework */,
Expand All @@ -228,7 +203,6 @@
275751DF2DEE1441003E467C /* Sources */,
275751E02DEE1441003E467C /* Frameworks */,
275751E12DEE1441003E467C /* Resources */,
279FED072DF4566D00320390 /* Embed Frameworks */,
);
buildRules = (
);
Expand All @@ -252,7 +226,6 @@
279283B52DFF11CE00234D64 /* Sources */,
279283B62DFF11CE00234D64 /* Frameworks */,
279283B72DFF11CE00234D64 /* Resources */,
2792849D2DFF136E00234D64 /* Embed Frameworks */,
);
buildRules = (
);
Expand Down
2 changes: 1 addition & 1 deletion Example/HostingExample/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,6 @@ class ViewController: NSViewController {

struct ContentView: View {
var body: some View {
ObservationExample()
AnimatedColorTimelineView()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
//
// AnimatedColorTimelineView.swift
// SharedExample
//
// Created by Kyle on 2025/9/15.
//

#if OPENSWIFTUI
import OpenSwiftUI
#else
import SwiftUI
#endif

#if OPENSWIFTUI
// FIXME: Missing LinearGradient, Shape, Text and safeArea.
// We use a simplified version for OpenSwiftUI now.
struct AnimatedColorTimelineView: View {
var body: some View {
TimelineView(.animation) { context in
let time = context.date.timeIntervalSince1970

ZStack {
// Animated background color
Color(
hue: (sin(time * 0.5) + 1) / 2,
saturation: 0.8,
brightness: 0.9
)
// .ignoresSafeArea()

VStack(spacing: 30) {
// Text("Animated Colors")
// .font(.largeTitle)
// .fontWeight(.bold)
// .foregroundColor(.white)

// Pulsing circle that changes color
// Circle()
// .fill(
Color(
hue: (cos(time * 2) + 1) / 2,
saturation: 1.0,
brightness: 1.0
)
// )
.frame(
width: 100 + sin(time * 3) * 20,
height: 100 + sin(time * 3) * 20
)

// Display current color values
let currentHue = (sin(time * 0.5) + 1) / 2
let _ = print(currentHue)
// Text("Background Hue: \(currentHue, specifier: "%.2f")")
// .font(.headline)
// .foregroundColor(.white)
// .padding()
// .background(Color.black.opacity(0.3))
// .cornerRadius(10)
}
}
}
}
}
#else
struct AnimatedColorTimelineView: View {
var body: some View {
TimelineView(.animation) { timeline in
let time = timeline.date.timeIntervalSince1970

ZStack {
// Animated gradient background
LinearGradient(
colors: [
Color(
hue: (sin(time * 0.5) + 1) / 2,
saturation: 0.8,
brightness: 0.9
),
Color(
hue: (cos(time * 0.3) + 1) / 2,
saturation: 0.6,
brightness: 0.7
),
Color(
hue: (sin(time * 0.7 + .pi) + 1) / 2,
saturation: 0.9,
brightness: 0.8
)
],
startPoint: .topLeading,
endPoint: .bottomTrailing
)
.ignoresSafeArea()

// Content overlay
VStack(spacing: 30) {
Text("Animated Colors")
.font(.largeTitle)
.fontWeight(.bold)
.foregroundColor(.white)
.shadow(radius: 5)

// Pulsing circle
Circle()
.fill(
Color(
hue: (sin(time * 2) + 1) / 2,
saturation: 1.0,
brightness: 1.0
)
)
.frame(
width: 100 + sin(time * 3) * 20,
height: 100 + sin(time * 3) * 20
)
.shadow(radius: 10)

// Color info
let currentHue = (sin(time * 0.5) + 1) / 2
Text("Hue: \(currentHue, specifier: "%.2f")")
.font(.headline)
.foregroundColor(.white)
.padding()
.background(.ultraThinMaterial)
.cornerRadius(10)
}
}
}
}
}
#endif
Loading