Updated the Sample app and Widget targets in the Xcode project to make the app works for visionOS.
This commit is contained in:
@@ -11,7 +11,7 @@
|
|||||||
02870A292FF7FF530079EA3A /* Features in Frameworks */ = {isa = PBXBuildFile; productRef = 02870A282FF7FF530079EA3A /* Features */; };
|
02870A292FF7FF530079EA3A /* Features in Frameworks */ = {isa = PBXBuildFile; productRef = 02870A282FF7FF530079EA3A /* Features */; };
|
||||||
0296F7F02FFAB1B600D2C5FC /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0296F7EF2FFAB1B600D2C5FC /* WidgetKit.framework */; };
|
0296F7F02FFAB1B600D2C5FC /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0296F7EF2FFAB1B600D2C5FC /* WidgetKit.framework */; };
|
||||||
0296F7F22FFAB1B600D2C5FC /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0296F7F12FFAB1B600D2C5FC /* SwiftUI.framework */; };
|
0296F7F22FFAB1B600D2C5FC /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0296F7F12FFAB1B600D2C5FC /* SwiftUI.framework */; };
|
||||||
0296F7FF2FFAB1B600D2C5FC /* AttendiWidgetExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 0296F7EE2FFAB1B600D2C5FC /* AttendiWidgetExtension.appex */; platformFilters = (ios, xros, ); settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
0296F7FF2FFAB1B600D2C5FC /* AttendiWidgetExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 0296F7EE2FFAB1B600D2C5FC /* AttendiWidgetExtension.appex */; platformFilter = ios; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||||
02D46AFE2FFAE77500266643 /* Features in Frameworks */ = {isa = PBXBuildFile; productRef = 02D46AFD2FFAE77500266643 /* Features */; };
|
02D46AFE2FFAE77500266643 /* Features in Frameworks */ = {isa = PBXBuildFile; productRef = 02D46AFD2FFAE77500266643 /* Features */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
@@ -342,10 +342,7 @@
|
|||||||
};
|
};
|
||||||
0296F7FE2FFAB1B600D2C5FC /* PBXTargetDependency */ = {
|
0296F7FE2FFAB1B600D2C5FC /* PBXTargetDependency */ = {
|
||||||
isa = PBXTargetDependency;
|
isa = PBXTargetDependency;
|
||||||
platformFilters = (
|
platformFilter = ios;
|
||||||
ios,
|
|
||||||
xros,
|
|
||||||
);
|
|
||||||
target = 0296F7ED2FFAB1B600D2C5FC /* AttendiWidgetExtension */;
|
target = 0296F7ED2FFAB1B600D2C5FC /* AttendiWidgetExtension */;
|
||||||
targetProxy = 0296F7FD2FFAB1B600D2C5FC /* PBXContainerItemProxy */;
|
targetProxy = 0296F7FD2FFAB1B600D2C5FC /* PBXContainerItemProxy */;
|
||||||
};
|
};
|
||||||
@@ -833,7 +830,7 @@
|
|||||||
SDKROOT = auto;
|
SDKROOT = auto;
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator watchos watchsimulator xros xrsimulator";
|
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||||
SUPPORTS_MACCATALYST = NO;
|
SUPPORTS_MACCATALYST = NO;
|
||||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
|
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
|
||||||
SWIFT_APPROACHABLE_CONCURRENCY = YES;
|
SWIFT_APPROACHABLE_CONCURRENCY = YES;
|
||||||
@@ -841,7 +838,7 @@
|
|||||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
||||||
SWIFT_VERSION = 6.0;
|
SWIFT_VERSION = 6.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2,4,7";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
WATCHOS_DEPLOYMENT_TARGET = 26.0;
|
WATCHOS_DEPLOYMENT_TARGET = 26.0;
|
||||||
XROS_DEPLOYMENT_TARGET = 26.0;
|
XROS_DEPLOYMENT_TARGET = 26.0;
|
||||||
};
|
};
|
||||||
@@ -925,14 +922,14 @@
|
|||||||
SDKROOT = auto;
|
SDKROOT = auto;
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator watchos watchsimulator xros xrsimulator";
|
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||||
SUPPORTS_MACCATALYST = NO;
|
SUPPORTS_MACCATALYST = NO;
|
||||||
SWIFT_APPROACHABLE_CONCURRENCY = YES;
|
SWIFT_APPROACHABLE_CONCURRENCY = YES;
|
||||||
SWIFT_COMPILATION_MODE = wholemodule;
|
SWIFT_COMPILATION_MODE = wholemodule;
|
||||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
||||||
SWIFT_VERSION = 6.0;
|
SWIFT_VERSION = 6.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2,4,7";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
WATCHOS_DEPLOYMENT_TARGET = 26.0;
|
WATCHOS_DEPLOYMENT_TARGET = 26.0;
|
||||||
XROS_DEPLOYMENT_TARGET = 26.0;
|
XROS_DEPLOYMENT_TARGET = 26.0;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -45,10 +45,14 @@ public struct NotificationLabelStyle: LabelStyle {
|
|||||||
}
|
}
|
||||||
.padding(.vertical, Constant.Padding.vertical)
|
.padding(.vertical, Constant.Padding.vertical)
|
||||||
.padding(.horizontal, Constant.Padding.horizontal)
|
.padding(.horizontal, Constant.Padding.horizontal)
|
||||||
|
#if os(visionOS)
|
||||||
|
.glassBackgroundEffect(in: .capsule)
|
||||||
|
#else
|
||||||
.glassEffect(
|
.glassEffect(
|
||||||
.regular,
|
.regular,
|
||||||
in: .capsule
|
in: .capsule
|
||||||
)
|
)
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,8 @@ import SwiftUI
|
|||||||
/// The button style for the controls of a ``RecordingView``.
|
/// The button style for the controls of a ``RecordingView``.
|
||||||
///
|
///
|
||||||
/// The style renders the button's label in the primary foreground color over a padded, circular Liquid Glass background — tinted by
|
/// The style renders the button's label in the primary foreground color over a padded, circular Liquid Glass background — tinted by
|
||||||
/// the color given at initialization — that reacts fluidly to presses. The whole button dims while disabled, and both the label and its
|
/// the color given at initialization — that reacts fluidly to presses. On visionOS, where Liquid Glass is unavailable, the background is
|
||||||
|
/// the platform's own glass material overlaid with the tint color. The whole button dims while disabled, and both the label and its
|
||||||
/// padding scale relative to the current dynamic type size.
|
/// padding scale relative to the current dynamic type size.
|
||||||
struct RecordingButtonStyle: ButtonStyle {
|
struct RecordingButtonStyle: ButtonStyle {
|
||||||
|
|
||||||
@@ -52,6 +53,14 @@ struct RecordingButtonStyle: ButtonStyle {
|
|||||||
.padding(padding)
|
.padding(padding)
|
||||||
.scaledToFit()
|
.scaledToFit()
|
||||||
.foregroundStyle(.primary.opacity(opacity))
|
.foregroundStyle(.primary.opacity(opacity))
|
||||||
|
#if os(visionOS)
|
||||||
|
.background(
|
||||||
|
tintColor.opacity(Constant.Opacity.tint),
|
||||||
|
in: .circle
|
||||||
|
)
|
||||||
|
.glassBackgroundEffect(in: .circle)
|
||||||
|
.opacity(opacity)
|
||||||
|
#else
|
||||||
.glassEffect(
|
.glassEffect(
|
||||||
.regular
|
.regular
|
||||||
.tint(tintColor)
|
.tint(tintColor)
|
||||||
@@ -59,6 +68,7 @@ struct RecordingButtonStyle: ButtonStyle {
|
|||||||
in: .circle
|
in: .circle
|
||||||
)
|
)
|
||||||
.opacity(opacity)
|
.opacity(opacity)
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -108,6 +118,8 @@ private enum Constant {
|
|||||||
static let disabled: Double = 0.5
|
static let disabled: Double = 0.5
|
||||||
/// The opacity of an enabled button.
|
/// The opacity of an enabled button.
|
||||||
static let enabled: Double = 1
|
static let enabled: Double = 1
|
||||||
|
/// The opacity of the tint color laid over the glass background on visionOS.
|
||||||
|
static let tint: Double = 0.5
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The padding constants.
|
/// The padding constants.
|
||||||
|
|||||||
@@ -81,54 +81,13 @@ public struct RecordingView: View {
|
|||||||
.accessibilityValue(model.textTimerAccessible)
|
.accessibilityValue(model.textTimerAccessible)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if os(visionOS)
|
||||||
|
controls
|
||||||
|
#else
|
||||||
GlassEffectContainer {
|
GlassEffectContainer {
|
||||||
HStack(
|
controls
|
||||||
spacing: Constant.Spacing.stack
|
|
||||||
) {
|
|
||||||
if model.shouldShowActions {
|
|
||||||
Button {
|
|
||||||
model.pressedDiscard()
|
|
||||||
} label: {
|
|
||||||
Image.Icon.discard
|
|
||||||
.resizable()
|
|
||||||
}
|
|
||||||
.buttonStyle(.recording(
|
|
||||||
tintColor: .red
|
|
||||||
))
|
|
||||||
.accessibilityLabel(.viewRecordingButtonDiscardLabel)
|
|
||||||
}
|
|
||||||
|
|
||||||
Button {
|
|
||||||
model.pressedMain()
|
|
||||||
} label: {
|
|
||||||
Image(model.iconMain)
|
|
||||||
.resizable()
|
|
||||||
}
|
|
||||||
.buttonStyle(.recording(
|
|
||||||
tintColor: .yellow
|
|
||||||
))
|
|
||||||
.disabled(model.shouldDisableMain)
|
|
||||||
.accessibilityLabel(model.labelMain)
|
|
||||||
|
|
||||||
if model.shouldShowActions {
|
|
||||||
Button {
|
|
||||||
model.pressedSend()
|
|
||||||
} label: {
|
|
||||||
if let icon = model.iconSend {
|
|
||||||
Image(icon)
|
|
||||||
.resizable()
|
|
||||||
} else {
|
|
||||||
ProgressView()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.buttonStyle(.recording(
|
|
||||||
tintColor: .green
|
|
||||||
))
|
|
||||||
.disabled(model.isProcessing)
|
|
||||||
.accessibilityLabel(model.labelSend)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
.animation(
|
.animation(
|
||||||
.easeInOut,
|
.easeInOut,
|
||||||
@@ -174,6 +133,64 @@ public struct RecordingView: View {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - Subviews
|
||||||
|
|
||||||
|
private extension RecordingView {
|
||||||
|
|
||||||
|
// MARK: Computed
|
||||||
|
|
||||||
|
/// The main, discard, and send buttons controlling the recording flow, laid out in a horizontal stack.
|
||||||
|
var controls: some View {
|
||||||
|
HStack(
|
||||||
|
spacing: Constant.Spacing.stack
|
||||||
|
) {
|
||||||
|
if model.shouldShowActions {
|
||||||
|
Button {
|
||||||
|
model.pressedDiscard()
|
||||||
|
} label: {
|
||||||
|
Image.Icon.discard
|
||||||
|
.resizable()
|
||||||
|
}
|
||||||
|
.buttonStyle(.recording(
|
||||||
|
tintColor: .red
|
||||||
|
))
|
||||||
|
.accessibilityLabel(.viewRecordingButtonDiscardLabel)
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
model.pressedMain()
|
||||||
|
} label: {
|
||||||
|
Image(model.iconMain)
|
||||||
|
.resizable()
|
||||||
|
}
|
||||||
|
.buttonStyle(.recording(
|
||||||
|
tintColor: .yellow
|
||||||
|
))
|
||||||
|
.disabled(model.shouldDisableMain)
|
||||||
|
.accessibilityLabel(model.labelMain)
|
||||||
|
|
||||||
|
if model.shouldShowActions {
|
||||||
|
Button {
|
||||||
|
model.pressedSend()
|
||||||
|
} label: {
|
||||||
|
if let icon = model.iconSend {
|
||||||
|
Image(icon)
|
||||||
|
.resizable()
|
||||||
|
} else {
|
||||||
|
ProgressView()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.buttonStyle(.recording(
|
||||||
|
tintColor: .green
|
||||||
|
))
|
||||||
|
.disabled(model.isProcessing)
|
||||||
|
.accessibilityLabel(model.labelSend)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - Constants
|
// MARK: - Constants
|
||||||
|
|
||||||
/// The constant values used across the view.
|
/// The constant values used across the view.
|
||||||
|
|||||||
Reference in New Issue
Block a user