Add support for macOS and backport to older OS versions
This commit is contained in:
@@ -8,3 +8,7 @@ org.gradle.caching=true
|
|||||||
#Android
|
#Android
|
||||||
android.nonTransitiveRClass=true
|
android.nonTransitiveRClass=true
|
||||||
android.useAndroidX=true
|
android.useAndroidX=true
|
||||||
|
#Compose Multiplatform
|
||||||
|
org.jetbrains.compose.experimental.macos.enabled=true
|
||||||
|
#Kotlin/Native
|
||||||
|
kotlin.native.ignoreDisabledTargets=true
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 6.4 KiB |
@@ -11,7 +11,7 @@
|
|||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
|
/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
|
||||||
D262C3356B38E7E13FFE64E4 /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = {
|
D262C3356B38E7E13FFE64E4 /* Exceptions for "iosApp" folder in "iosApp" target */ = {
|
||||||
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
|
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
|
||||||
membershipExceptions = (
|
membershipExceptions = (
|
||||||
Info.plist,
|
Info.plist,
|
||||||
@@ -23,21 +23,13 @@
|
|||||||
/* Begin PBXFileSystemSynchronizedRootGroup section */
|
/* Begin PBXFileSystemSynchronizedRootGroup section */
|
||||||
24D66E9CCFCEB2D844328B79 /* Configuration */ = {
|
24D66E9CCFCEB2D844328B79 /* Configuration */ = {
|
||||||
isa = PBXFileSystemSynchronizedRootGroup;
|
isa = PBXFileSystemSynchronizedRootGroup;
|
||||||
explicitFileTypes = {
|
|
||||||
};
|
|
||||||
explicitFolders = (
|
|
||||||
);
|
|
||||||
path = Configuration;
|
path = Configuration;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
55D8B06C58654F251C5B3381 /* iosApp */ = {
|
55D8B06C58654F251C5B3381 /* iosApp */ = {
|
||||||
isa = PBXFileSystemSynchronizedRootGroup;
|
isa = PBXFileSystemSynchronizedRootGroup;
|
||||||
exceptions = (
|
exceptions = (
|
||||||
D262C3356B38E7E13FFE64E4 /* PBXFileSystemSynchronizedBuildFileExceptionSet */,
|
D262C3356B38E7E13FFE64E4 /* Exceptions for "iosApp" folder in "iosApp" target */,
|
||||||
);
|
|
||||||
explicitFileTypes = {
|
|
||||||
};
|
|
||||||
explicitFolders = (
|
|
||||||
);
|
);
|
||||||
path = iosApp;
|
path = iosApp;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -84,6 +76,7 @@
|
|||||||
5BCD356C334571BCAA0967CA /* Sources */,
|
5BCD356C334571BCAA0967CA /* Sources */,
|
||||||
C2B5A146484C5EC128AEFD65 /* Frameworks */,
|
C2B5A146484C5EC128AEFD65 /* Frameworks */,
|
||||||
96EB3DBC5DECE4CD4D246992 /* Resources */,
|
96EB3DBC5DECE4CD4D246992 /* Resources */,
|
||||||
|
1DADA2DD199949A498015FFD /* Sanitize Moko Resource Bundle Names */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
@@ -181,6 +174,24 @@
|
|||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "\"$SRCROOT/../gradlew\" -p \"$SRCROOT/../\" :shared:copyFrameworkResourcesToApp \\\n -Pmoko.resources.PLATFORM_NAME=\"$PLATFORM_NAME\" \\\n -Pmoko.resources.CONFIGURATION=\"$CONFIGURATION\" \\\n -Pmoko.resources.ARCHS=\"$ARCHS\" \\\n -Pmoko.resources.BUILT_PRODUCTS_DIR=\"$BUILT_PRODUCTS_DIR\" \\\n -Pmoko.resources.CONTENTS_FOLDER_PATH=\"$CONTENTS_FOLDER_PATH\" \n";
|
shellScript = "\"$SRCROOT/../gradlew\" -p \"$SRCROOT/../\" :shared:copyFrameworkResourcesToApp \\\n -Pmoko.resources.PLATFORM_NAME=\"$PLATFORM_NAME\" \\\n -Pmoko.resources.CONFIGURATION=\"$CONFIGURATION\" \\\n -Pmoko.resources.ARCHS=\"$ARCHS\" \\\n -Pmoko.resources.BUILT_PRODUCTS_DIR=\"$BUILT_PRODUCTS_DIR\" \\\n -Pmoko.resources.CONTENTS_FOLDER_PATH=\"$CONTENTS_FOLDER_PATH\" \n";
|
||||||
};
|
};
|
||||||
|
1DADA2DD199949A498015FFD /* Sanitize Moko Resource Bundle Names */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
);
|
||||||
|
name = "Sanitize Moko Resource Bundle Names";
|
||||||
|
outputFileListPaths = (
|
||||||
|
);
|
||||||
|
outputPaths = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "if [ \"$PLATFORM_NAME\" != \"macosx\" ]; then\n exit 0\nfi\n# moko-resources names its resource bundle after the Kotlin klib unique_name (group:module),\n# e.g. SatsPrice:shared.bundle, and drops it directly under Contents/. Colons break\n# codesign, and a loose bundle outside Contents/Resources isn't recognized as a proper\n# nested bundle either, so the final app-level CodeSign phase fails with \"code object is\n# not signed at all\" unless we rename and relocate it. NSBundle resolves this bundle by\n# directory identity, not by name/path, so moko-resources/localization lookups still work.\nfind \"$CODESIGNING_FOLDER_PATH\" -type d -name \"*:*.bundle\" | while IFS= read -r bundle; do\n safe_name=$(basename \"$bundle\" | tr ':' '_')\n mkdir -p \"$CODESIGNING_FOLDER_PATH/Contents/Resources\"\n dest=\"$CODESIGNING_FOLDER_PATH/Contents/Resources/$safe_name\"\n rm -rf \"$dest\"\n mv \"$bundle\" \"$dest\"\ndone\n";
|
||||||
|
};
|
||||||
/* End PBXShellScriptBuildPhase section */
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXSourcesBuildPhase section */
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
@@ -200,18 +211,21 @@
|
|||||||
ARCHS = arm64;
|
ARCHS = arm64;
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
|
"CODE_SIGN_ENTITLEMENTS[sdk=macosx*]" = iosApp/macOS.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
|
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
DEVELOPMENT_ASSET_PATHS = "\"iosApp/Preview Content\"";
|
DEVELOPMENT_ASSET_PATHS = "\"iosApp/Preview Content\"";
|
||||||
DEVELOPMENT_TEAM = "${TEAM_ID}";
|
DEVELOPMENT_TEAM = S99A5B637C;
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_FILE = iosApp/Info.plist;
|
INFOPLIST_FILE = iosApp/Info.plist;
|
||||||
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
|
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
|
||||||
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphone*]" = YES;
|
||||||
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
"INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphone*]" = YES;
|
||||||
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
"INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphone*]" = YES;
|
||||||
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
"INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad[sdk=iphone*]" = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
||||||
|
"INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone[sdk=iphone*]" = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
@@ -270,11 +284,13 @@
|
|||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 18.2;
|
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
|
||||||
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||||
|
MACOSX_DEPLOYMENT_TARGET = 13.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = auto;
|
||||||
|
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx";
|
||||||
SWIFT_COMPILATION_MODE = wholemodule;
|
SWIFT_COMPILATION_MODE = wholemodule;
|
||||||
VALIDATE_PRODUCT = YES;
|
VALIDATE_PRODUCT = YES;
|
||||||
};
|
};
|
||||||
@@ -334,12 +350,14 @@
|
|||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 18.2;
|
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
|
||||||
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||||
|
MACOSX_DEPLOYMENT_TARGET = 13.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = auto;
|
||||||
|
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx";
|
||||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
|
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
};
|
};
|
||||||
@@ -351,18 +369,21 @@
|
|||||||
ARCHS = arm64;
|
ARCHS = arm64;
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
|
"CODE_SIGN_ENTITLEMENTS[sdk=macosx*]" = iosApp/macOS.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
|
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
DEVELOPMENT_ASSET_PATHS = "\"iosApp/Preview Content\"";
|
DEVELOPMENT_ASSET_PATHS = "\"iosApp/Preview Content\"";
|
||||||
DEVELOPMENT_TEAM = "${TEAM_ID}";
|
DEVELOPMENT_TEAM = S99A5B637C;
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_FILE = iosApp/Info.plist;
|
INFOPLIST_FILE = iosApp/Info.plist;
|
||||||
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
|
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
|
||||||
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphone*]" = YES;
|
||||||
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
"INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphone*]" = YES;
|
||||||
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
"INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphone*]" = YES;
|
||||||
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
"INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad[sdk=iphone*]" = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
||||||
|
"INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone[sdk=iphone*]" = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ struct ContentView: View {
|
|||||||
@State private var showCurrencyPicker = false
|
@State private var showCurrencyPicker = false
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
NavigationView {
|
NavigationStack {
|
||||||
Group {
|
Group {
|
||||||
if let state = viewModel.state {
|
if let state = viewModel.state {
|
||||||
form(for: state)
|
form(for: state)
|
||||||
@@ -121,13 +121,18 @@ struct ContentView: View {
|
|||||||
onChange: { viewModel.onFiatAmountChanged(code: row.code, value: $0) }
|
onChange: { viewModel.onFiatAmountChanged(code: row.code, value: $0) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
#if os(iOS)
|
||||||
.onDelete { indexSet in
|
.onDelete { indexSet in
|
||||||
for index in indexSet {
|
for index in indexSet {
|
||||||
viewModel.onFiatCurrencyToggled(state.fiatRows[index].code)
|
viewModel.onFiatCurrencyToggled(state.fiatRows[index].code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if os(macOS)
|
||||||
|
.formStyle(.grouped)
|
||||||
|
#endif
|
||||||
.sheet(isPresented: $showCurrencyPicker) {
|
.sheet(isPresented: $showCurrencyPicker) {
|
||||||
CurrencyPickerSheet(
|
CurrencyPickerSheet(
|
||||||
currencies: state.availableCurrencies,
|
currencies: state.availableCurrencies,
|
||||||
@@ -142,7 +147,7 @@ struct ContentView: View {
|
|||||||
private func amountRow(
|
private func amountRow(
|
||||||
label: String,
|
label: String,
|
||||||
value: String,
|
value: String,
|
||||||
keyboardType: UIKeyboardType,
|
keyboardType: NumericFieldKeyboard,
|
||||||
sanitize: @escaping (String) -> String,
|
sanitize: @escaping (String) -> String,
|
||||||
onChange: @escaping (String) -> Void
|
onChange: @escaping (String) -> Void
|
||||||
) -> some View {
|
) -> some View {
|
||||||
@@ -150,7 +155,7 @@ struct ContentView: View {
|
|||||||
Text(label)
|
Text(label)
|
||||||
Spacer()
|
Spacer()
|
||||||
NumericField(
|
NumericField(
|
||||||
placeholder: label,
|
placeholder: "",
|
||||||
value: value,
|
value: value,
|
||||||
keyboardType: keyboardType,
|
keyboardType: keyboardType,
|
||||||
sanitize: sanitize,
|
sanitize: sanitize,
|
||||||
@@ -170,7 +175,7 @@ struct ContentView: View {
|
|||||||
private struct NumericField: View {
|
private struct NumericField: View {
|
||||||
let placeholder: String
|
let placeholder: String
|
||||||
let value: String
|
let value: String
|
||||||
let keyboardType: UIKeyboardType
|
let keyboardType: NumericFieldKeyboard
|
||||||
let sanitize: (String) -> String
|
let sanitize: (String) -> String
|
||||||
let onChange: (String) -> Void
|
let onChange: (String) -> Void
|
||||||
var alignment: TextAlignment = .leading
|
var alignment: TextAlignment = .leading
|
||||||
@@ -179,10 +184,15 @@ private struct NumericField: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
TextField(placeholder, text: $text)
|
TextField(placeholder, text: $text)
|
||||||
.keyboardType(keyboardType)
|
#if os(iOS)
|
||||||
|
.keyboardType(keyboardType.uiKeyboardType)
|
||||||
|
#endif
|
||||||
.multilineTextAlignment(alignment)
|
.multilineTextAlignment(alignment)
|
||||||
|
#if os(macOS)
|
||||||
|
.frame(maxWidth: 140)
|
||||||
|
#endif
|
||||||
.onAppear { text = value }
|
.onAppear { text = value }
|
||||||
.onChange(of: text) { _, newValue in
|
.onChange(of: text) { newValue in
|
||||||
let sanitized = sanitize(newValue)
|
let sanitized = sanitize(newValue)
|
||||||
if sanitized != newValue {
|
if sanitized != newValue {
|
||||||
text = sanitized
|
text = sanitized
|
||||||
@@ -191,7 +201,7 @@ private struct NumericField: View {
|
|||||||
onChange(sanitized)
|
onChange(sanitized)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.onChange(of: value) { _, newValue in
|
.onChange(of: value) { newValue in
|
||||||
if newValue != text {
|
if newValue != text {
|
||||||
text = newValue
|
text = newValue
|
||||||
}
|
}
|
||||||
@@ -216,3 +226,21 @@ private func sanitizeDecimalInput(_ raw: String) -> String {
|
|||||||
private func sanitizeIntegerInput(_ raw: String) -> String {
|
private func sanitizeIntegerInput(_ raw: String) -> String {
|
||||||
raw.filter { $0.isNumber }
|
raw.filter { $0.isNumber }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// `UIKeyboardType` doesn't exist on macOS (no on-screen keyboard), so this stands in for it
|
||||||
|
/// across both platforms; only iOS actually applies it, via `uiKeyboardType` below.
|
||||||
|
private enum NumericFieldKeyboard {
|
||||||
|
case decimalPad
|
||||||
|
case numberPad
|
||||||
|
}
|
||||||
|
|
||||||
|
#if os(iOS)
|
||||||
|
private extension NumericFieldKeyboard {
|
||||||
|
var uiKeyboardType: UIKeyboardType {
|
||||||
|
switch self {
|
||||||
|
case .decimalPad: return .decimalPad
|
||||||
|
case .numberPad: return .numberPad
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ struct CurrencyPickerSheet: View {
|
|||||||
@Environment(\.dismiss) private var dismiss
|
@Environment(\.dismiss) private var dismiss
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
NavigationView {
|
NavigationStack {
|
||||||
List(currencies, id: \.code) { info in
|
List(currencies, id: \.code) { info in
|
||||||
Button {
|
Button {
|
||||||
onToggle(info.code)
|
onToggle(info.code)
|
||||||
@@ -27,13 +27,21 @@ struct CurrencyPickerSheet: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.navigationTitle(IosLocalizationKt.localizedString(resource: MR.strings.shared.currencies_section_title))
|
.navigationTitle(IosLocalizationKt.localizedString(resource: MR.strings.shared.currencies_section_title))
|
||||||
|
#if os(iOS)
|
||||||
.navigationBarTitleDisplayMode(.inline)
|
.navigationBarTitleDisplayMode(.inline)
|
||||||
|
#endif
|
||||||
.toolbar {
|
.toolbar {
|
||||||
ToolbarItem(placement: .confirmationAction) {
|
ToolbarItem(placement: .confirmationAction) {
|
||||||
Button(IosLocalizationKt.localizedString(resource: MR.strings.shared.done)) { dismiss() }
|
Button(IosLocalizationKt.localizedString(resource: MR.strings.shared.done)) { dismiss() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if os(macOS)
|
||||||
|
// macOS sizes a .sheet() to its content's ideal size rather than the parent window's
|
||||||
|
// size (unlike iOS, which presents modally full-size); without an explicit frame here,
|
||||||
|
// the List has no size to lay out rows in and renders empty.
|
||||||
|
.frame(minWidth: 420, minHeight: 480)
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
private func currencyLabel(for info: CurrencyInfo) -> String {
|
private func currencyLabel(for info: CurrencyInfo) -> String {
|
||||||
|
|||||||
@@ -5,6 +5,9 @@ struct iOSApp: App {
|
|||||||
var body: some Scene {
|
var body: some Scene {
|
||||||
WindowGroup {
|
WindowGroup {
|
||||||
ContentView()
|
ContentView()
|
||||||
|
#if os(macOS)
|
||||||
|
.frame(minWidth: 420, minHeight: 500)
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>com.apple.security.app-sandbox</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.network.client</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@@ -13,9 +13,10 @@ plugins {
|
|||||||
kotlin {
|
kotlin {
|
||||||
listOf(
|
listOf(
|
||||||
iosArm64(),
|
iosArm64(),
|
||||||
iosSimulatorArm64()
|
iosSimulatorArm64(),
|
||||||
).forEach { iosTarget ->
|
macosArm64()
|
||||||
iosTarget.binaries.framework {
|
).forEach { appleTarget ->
|
||||||
|
appleTarget.binaries.framework {
|
||||||
baseName = "Shared"
|
baseName = "Shared"
|
||||||
isStatic = true
|
isStatic = true
|
||||||
export(libs.moko.resources)
|
export(libs.moko.resources)
|
||||||
@@ -87,7 +88,7 @@ kotlin {
|
|||||||
implementation(libs.kotlinx.coroutinesTest)
|
implementation(libs.kotlinx.coroutinesTest)
|
||||||
implementation(libs.ktor.client.mock)
|
implementation(libs.ktor.client.mock)
|
||||||
}
|
}
|
||||||
iosMain.dependencies {
|
appleMain.dependencies {
|
||||||
implementation(libs.ktor.client.darwin)
|
implementation(libs.ktor.client.darwin)
|
||||||
}
|
}
|
||||||
jvmMain.dependencies {
|
jvmMain.dependencies {
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package xyz.tyiu.satsprice
|
||||||
|
|
||||||
|
import platform.Foundation.NSProcessInfo
|
||||||
|
|
||||||
|
class MacOSPlatform : Platform {
|
||||||
|
override val name: String = "macOS " + NSProcessInfo.processInfo.operatingSystemVersionString
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun getPlatform(): Platform = MacOSPlatform()
|
||||||
Reference in New Issue
Block a user