Make iOS application work

This commit is contained in:
Syer10
2023-12-01 22:08:05 -05:00
parent c5c83b5e51
commit 0b4e201808
7 changed files with 68 additions and 66 deletions

View File

@@ -24,6 +24,7 @@ kotlin {
binaries {
framework {
baseName = "i18n"
isStatic = true
}
}
}

View File

@@ -1,3 +1,5 @@
@file:OptIn(ExperimentalForeignApi::class, BetaInteropApi::class)
package ca.gosyer.jui.ios
import androidx.compose.animation.Crossfade
@@ -24,11 +26,13 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.window.Application
import androidx.compose.ui.window.ComposeUIViewController
import ca.gosyer.jui.ui.base.theme.AppTheme
import ca.gosyer.jui.ui.main.MainMenu
import ca.gosyer.jui.uicore.vm.ContextWrapper
import ca.gosyer.jui.uicore.vm.Length
import kotlinx.cinterop.BetaInteropApi
import kotlinx.cinterop.ExperimentalForeignApi
import kotlinx.cinterop.autoreleasepool
import kotlinx.cinterop.cstr
import kotlinx.cinterop.memScoped
@@ -37,7 +41,16 @@ import kotlinx.cinterop.useContents
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import org.lighthousegames.logging.FixedLogLevel
import org.lighthousegames.logging.KmLog
import org.lighthousegames.logging.KmLogging
import org.lighthousegames.logging.LogFactory
import org.lighthousegames.logging.LogLevel
import org.lighthousegames.logging.LogLevelController
import org.lighthousegames.logging.Logger
import org.lighthousegames.logging.TagProvider
import platform.Foundation.NSStringFromClass
import platform.Foundation.NSThread
import platform.UIKit.UIApplication
import platform.UIKit.UIApplicationDelegateProtocol
import platform.UIKit.UIApplicationDelegateProtocolMeta
@@ -45,77 +58,41 @@ import platform.UIKit.UIApplicationMain
import platform.UIKit.UIResponder
import platform.UIKit.UIResponderMeta
import platform.UIKit.UIScreen
import platform.UIKit.UIViewController
import platform.UIKit.UIWindow
import platform.UIKit.safeAreaInsets
import kotlin.time.Duration
import kotlin.time.Duration.Companion.seconds
fun main() {
val args = emptyArray<String>()
memScoped {
val argc = args.size + 1
val argv = (arrayOf("skikoApp") + args).map { it.cstr.ptr }.toCValues()
autoreleasepool {
UIApplicationMain(argc, argv, null, NSStringFromClass(SkikoAppDelegate))
fun initializeApplication(): UIViewController {
val appComponent = AppComponent.getInstance(ContextWrapper())
appComponent.migrations.runMigrations()
appComponent.appMigrations.runMigrations()
appComponent.downloadService.init()
appComponent.libraryUpdateService.init()
val uiHooks = appComponent.hooks
val context = appComponent.context
return ComposeUIViewController {
CompositionLocalProvider(*uiHooks) {
AppTheme {
Box(Modifier.fillMaxSize()) {
MainMenu()
ToastOverlay(
modifier = Modifier
.align(Alignment.BottomCenter)
.padding(bottom = 64.dp),
context = context,
)
}
}
}
}
}
class SkikoAppDelegate
@OverrideInit
constructor() : UIResponder(), UIApplicationDelegateProtocol {
companion object : UIResponderMeta(), UIApplicationDelegateProtocolMeta
private var _window: UIWindow? = null
override fun window() = _window
override fun setWindow(window: UIWindow?) {
_window = window
}
private val context = ContextWrapper()
private val appComponent = AppComponent.getInstance(context)
init {
appComponent.migrations.runMigrations()
appComponent.appMigrations.runMigrations()
appComponent.downloadService.init()
appComponent.libraryUpdateService.init()
}
val uiHooks = appComponent.hooks
override fun application(
application: UIApplication,
didFinishLaunchingWithOptions: Map<Any?, *>?,
): Boolean {
window = UIWindow(frame = UIScreen.mainScreen.bounds).apply {
val insets = safeAreaInsets.useContents {
WindowInsets(left.dp, top.dp, right.dp, bottom.dp)
}
rootViewController = Application("Tachidesk-JUI") {
CompositionLocalProvider(*uiHooks) {
AppTheme {
Box(Modifier.fillMaxSize().windowInsetsPadding(insets)) {
MainMenu()
ToastOverlay(
modifier = Modifier
.align(Alignment.BottomCenter)
.padding(bottom = 64.dp),
context = context,
)
}
}
}
}
makeKeyAndVisible()
}
return true
}
}
@Composable
fun ToastOverlay(
modifier: Modifier,

View File

@@ -17,7 +17,7 @@
058557BA273AAA24004C7B11 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
058557D8273AAEEB004C7B11 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
2152FB032600AC8F00CF470E /* iOSApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iOSApp.swift; sourceTree = "<group>"; };
7555FF7B242A565900829871 /* .app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = .app; sourceTree = BUILT_PRODUCTS_DIR; };
7555FF7B242A565900829871 /* .app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; name = .app; path = "Tachidesk-JUI.app"; sourceTree = BUILT_PRODUCTS_DIR; };
7555FF82242A565900829871 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
7555FF8C242A565B00829871 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
AB3632DC29227652001CCB65 /* Config.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Config.xcconfig; sourceTree = "<group>"; };
@@ -87,6 +87,7 @@
F36B1CEB2AD83DDC00CB74D5 /* Compile Kotlin Framework */,
7555FF77242A565900829871 /* Sources */,
7555FF79242A565900829871 /* Resources */,
899476382B1ACFC30060F0C4 /* ShellScript */,
);
buildRules = (
);
@@ -143,6 +144,23 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
899476382B1ACFC30060F0C4 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
);
outputFileListPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"$SRCROOT/../gradlew\" -p \"$SRCROOT/../\" :i18n: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";
};
F36B1CEB2AD83DDC00CB74D5 /* Compile Kotlin Framework */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;

View File

@@ -1,10 +1,10 @@
import UIKit
import SwiftUI
import ComposeApp
import ios
struct ComposeView: UIViewControllerRepresentable {
func makeUIViewController(context: Context) -> UIViewController {
MainViewControllerKt.MainViewController()
MainKt.initializeApplication()
}
func updateUIViewController(_ uiViewController: UIViewController, context: Context) {}

View File

@@ -16,6 +16,7 @@ import com.seiko.imageloader.cache.memory.maxSizePercent
import com.seiko.imageloader.component.ComponentRegistryBuilder
import com.seiko.imageloader.component.setupDefaultComponents
import com.seiko.imageloader.option.OptionsBuilder
import kotlinx.cinterop.ExperimentalForeignApi
import okio.Path.Companion.toPath
import platform.Foundation.NSCachesDirectory
import platform.Foundation.NSFileManager
@@ -39,6 +40,7 @@ actual fun DiskCacheBuilder.configure(
maxSizeBytes(1024 * 1024 * 150) // 150 MB
}
@OptIn(ExperimentalForeignApi::class)
private fun getCacheDir(): String {
return NSFileManager.defaultManager.URLForDirectory(
NSCachesDirectory,

View File

@@ -7,6 +7,7 @@
package ca.gosyer.jui.ui.base.prefs
import androidx.compose.ui.graphics.Color
import kotlinx.cinterop.ExperimentalForeignApi
import kotlinx.cinterop.alloc
import kotlinx.cinterop.memScoped
import kotlinx.cinterop.ptr
@@ -16,6 +17,7 @@ import platform.UIKit.UIColor
fun Color.toUIColor() = UIColor(red = red.toDouble(), green = green.toDouble(), blue = blue.toDouble(), alpha = 1.0)
@OptIn(ExperimentalForeignApi::class)
internal actual fun Color.toHsv(): FloatArray =
memScoped {
val uiColor = toUIColor()

View File

@@ -15,6 +15,7 @@ import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.graphics.toComposeImageBitmap
import androidx.compose.ui.graphics.vector.rememberVectorPainter
import dev.icerock.moko.resources.ImageResource
import kotlinx.cinterop.ExperimentalForeignApi
import kotlinx.cinterop.get
import org.jetbrains.skia.ColorAlphaType
import org.jetbrains.skia.ColorType
@@ -42,6 +43,7 @@ actual fun ImageResource.toPainter(): Painter {
// Taken from https://github.com/touchlab/DroidconKotlin/blob/main/shared-ui/src/iosMain/kotlin/co/touchlab/droidcon/ui/util/ToSkiaImage.kt
// TODO: Add support for remaining color spaces when the Skia library supports them.
@OptIn(ExperimentalForeignApi::class)
private fun UIImage.toSkiaImage(): Image? {
val imageRef = CGImageCreateCopyWithColorSpace(this.CGImage, CGColorSpaceCreateDeviceRGB()) ?: return null