mirror of
https://github.com/Suwayomi/TachideskJUI.git
synced 2025-12-10 06:42:05 +01:00
Make iOS application work
This commit is contained in:
@@ -24,6 +24,7 @@ kotlin {
|
|||||||
binaries {
|
binaries {
|
||||||
framework {
|
framework {
|
||||||
baseName = "i18n"
|
baseName = "i18n"
|
||||||
|
isStatic = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
@file:OptIn(ExperimentalForeignApi::class, BetaInteropApi::class)
|
||||||
|
|
||||||
package ca.gosyer.jui.ios
|
package ca.gosyer.jui.ios
|
||||||
|
|
||||||
import androidx.compose.animation.Crossfade
|
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.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
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.base.theme.AppTheme
|
||||||
import ca.gosyer.jui.ui.main.MainMenu
|
import ca.gosyer.jui.ui.main.MainMenu
|
||||||
import ca.gosyer.jui.uicore.vm.ContextWrapper
|
import ca.gosyer.jui.uicore.vm.ContextWrapper
|
||||||
import ca.gosyer.jui.uicore.vm.Length
|
import ca.gosyer.jui.uicore.vm.Length
|
||||||
|
import kotlinx.cinterop.BetaInteropApi
|
||||||
|
import kotlinx.cinterop.ExperimentalForeignApi
|
||||||
import kotlinx.cinterop.autoreleasepool
|
import kotlinx.cinterop.autoreleasepool
|
||||||
import kotlinx.cinterop.cstr
|
import kotlinx.cinterop.cstr
|
||||||
import kotlinx.cinterop.memScoped
|
import kotlinx.cinterop.memScoped
|
||||||
@@ -37,7 +41,16 @@ import kotlinx.cinterop.useContents
|
|||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
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.NSStringFromClass
|
||||||
|
import platform.Foundation.NSThread
|
||||||
import platform.UIKit.UIApplication
|
import platform.UIKit.UIApplication
|
||||||
import platform.UIKit.UIApplicationDelegateProtocol
|
import platform.UIKit.UIApplicationDelegateProtocol
|
||||||
import platform.UIKit.UIApplicationDelegateProtocolMeta
|
import platform.UIKit.UIApplicationDelegateProtocolMeta
|
||||||
@@ -45,77 +58,41 @@ import platform.UIKit.UIApplicationMain
|
|||||||
import platform.UIKit.UIResponder
|
import platform.UIKit.UIResponder
|
||||||
import platform.UIKit.UIResponderMeta
|
import platform.UIKit.UIResponderMeta
|
||||||
import platform.UIKit.UIScreen
|
import platform.UIKit.UIScreen
|
||||||
|
import platform.UIKit.UIViewController
|
||||||
import platform.UIKit.UIWindow
|
import platform.UIKit.UIWindow
|
||||||
import platform.UIKit.safeAreaInsets
|
import platform.UIKit.safeAreaInsets
|
||||||
import kotlin.time.Duration
|
import kotlin.time.Duration
|
||||||
import kotlin.time.Duration.Companion.seconds
|
import kotlin.time.Duration.Companion.seconds
|
||||||
|
|
||||||
fun main() {
|
fun initializeApplication(): UIViewController {
|
||||||
val args = emptyArray<String>()
|
val appComponent = AppComponent.getInstance(ContextWrapper())
|
||||||
memScoped {
|
|
||||||
val argc = args.size + 1
|
appComponent.migrations.runMigrations()
|
||||||
val argv = (arrayOf("skikoApp") + args).map { it.cstr.ptr }.toCValues()
|
appComponent.appMigrations.runMigrations()
|
||||||
autoreleasepool {
|
|
||||||
UIApplicationMain(argc, argv, null, NSStringFromClass(SkikoAppDelegate))
|
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
|
@Composable
|
||||||
fun ToastOverlay(
|
fun ToastOverlay(
|
||||||
modifier: Modifier,
|
modifier: Modifier,
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
058557BA273AAA24004C7B11 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
AB3632DC29227652001CCB65 /* Config.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Config.xcconfig; sourceTree = "<group>"; };
|
||||||
@@ -87,6 +87,7 @@
|
|||||||
F36B1CEB2AD83DDC00CB74D5 /* Compile Kotlin Framework */,
|
F36B1CEB2AD83DDC00CB74D5 /* Compile Kotlin Framework */,
|
||||||
7555FF77242A565900829871 /* Sources */,
|
7555FF77242A565900829871 /* Sources */,
|
||||||
7555FF79242A565900829871 /* Resources */,
|
7555FF79242A565900829871 /* Resources */,
|
||||||
|
899476382B1ACFC30060F0C4 /* ShellScript */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
@@ -143,6 +144,23 @@
|
|||||||
/* End PBXResourcesBuildPhase section */
|
/* End PBXResourcesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXShellScriptBuildPhase 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 */ = {
|
F36B1CEB2AD83DDC00CB74D5 /* Compile Kotlin Framework */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import UIKit
|
import UIKit
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
import ComposeApp
|
import ios
|
||||||
|
|
||||||
struct ComposeView: UIViewControllerRepresentable {
|
struct ComposeView: UIViewControllerRepresentable {
|
||||||
func makeUIViewController(context: Context) -> UIViewController {
|
func makeUIViewController(context: Context) -> UIViewController {
|
||||||
MainViewControllerKt.MainViewController()
|
MainKt.initializeApplication()
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateUIViewController(_ uiViewController: UIViewController, context: Context) {}
|
func updateUIViewController(_ uiViewController: UIViewController, context: Context) {}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import com.seiko.imageloader.cache.memory.maxSizePercent
|
|||||||
import com.seiko.imageloader.component.ComponentRegistryBuilder
|
import com.seiko.imageloader.component.ComponentRegistryBuilder
|
||||||
import com.seiko.imageloader.component.setupDefaultComponents
|
import com.seiko.imageloader.component.setupDefaultComponents
|
||||||
import com.seiko.imageloader.option.OptionsBuilder
|
import com.seiko.imageloader.option.OptionsBuilder
|
||||||
|
import kotlinx.cinterop.ExperimentalForeignApi
|
||||||
import okio.Path.Companion.toPath
|
import okio.Path.Companion.toPath
|
||||||
import platform.Foundation.NSCachesDirectory
|
import platform.Foundation.NSCachesDirectory
|
||||||
import platform.Foundation.NSFileManager
|
import platform.Foundation.NSFileManager
|
||||||
@@ -39,6 +40,7 @@ actual fun DiskCacheBuilder.configure(
|
|||||||
maxSizeBytes(1024 * 1024 * 150) // 150 MB
|
maxSizeBytes(1024 * 1024 * 150) // 150 MB
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalForeignApi::class)
|
||||||
private fun getCacheDir(): String {
|
private fun getCacheDir(): String {
|
||||||
return NSFileManager.defaultManager.URLForDirectory(
|
return NSFileManager.defaultManager.URLForDirectory(
|
||||||
NSCachesDirectory,
|
NSCachesDirectory,
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
package ca.gosyer.jui.ui.base.prefs
|
package ca.gosyer.jui.ui.base.prefs
|
||||||
|
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import kotlinx.cinterop.ExperimentalForeignApi
|
||||||
import kotlinx.cinterop.alloc
|
import kotlinx.cinterop.alloc
|
||||||
import kotlinx.cinterop.memScoped
|
import kotlinx.cinterop.memScoped
|
||||||
import kotlinx.cinterop.ptr
|
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)
|
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 =
|
internal actual fun Color.toHsv(): FloatArray =
|
||||||
memScoped {
|
memScoped {
|
||||||
val uiColor = toUIColor()
|
val uiColor = toUIColor()
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import androidx.compose.ui.graphics.painter.Painter
|
|||||||
import androidx.compose.ui.graphics.toComposeImageBitmap
|
import androidx.compose.ui.graphics.toComposeImageBitmap
|
||||||
import androidx.compose.ui.graphics.vector.rememberVectorPainter
|
import androidx.compose.ui.graphics.vector.rememberVectorPainter
|
||||||
import dev.icerock.moko.resources.ImageResource
|
import dev.icerock.moko.resources.ImageResource
|
||||||
|
import kotlinx.cinterop.ExperimentalForeignApi
|
||||||
import kotlinx.cinterop.get
|
import kotlinx.cinterop.get
|
||||||
import org.jetbrains.skia.ColorAlphaType
|
import org.jetbrains.skia.ColorAlphaType
|
||||||
import org.jetbrains.skia.ColorType
|
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
|
// 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.
|
// TODO: Add support for remaining color spaces when the Skia library supports them.
|
||||||
|
@OptIn(ExperimentalForeignApi::class)
|
||||||
private fun UIImage.toSkiaImage(): Image? {
|
private fun UIImage.toSkiaImage(): Image? {
|
||||||
val imageRef = CGImageCreateCopyWithColorSpace(this.CGImage, CGColorSpaceCreateDeviceRGB()) ?: return null
|
val imageRef = CGImageCreateCopyWithColorSpace(this.CGImage, CGColorSpaceCreateDeviceRGB()) ?: return null
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user