Skip to content

Commit 7f455d7

Browse files
committed
ios add
1 parent 1332ac4 commit 7f455d7

File tree

18 files changed

+670
-0
lines changed

18 files changed

+670
-0
lines changed

composeApp/build.gradle.kts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,17 @@ kotlin {
3535

3636
jvm("desktop")
3737

38+
listOf(
39+
iosX64(),
40+
iosArm64(),
41+
iosSimulatorArm64()
42+
).forEach { iosTarget ->
43+
iosTarget.binaries.framework {
44+
baseName = "ComposeApp"
45+
isStatic = true
46+
}
47+
}
48+
3849
sourceSets {
3950
val desktopMain by getting
4051

@@ -126,6 +137,19 @@ kotlin {
126137
// kstore
127138
implementation(libs.kstore.file)
128139
}
140+
iosMain.dependencies {
141+
// sqlite
142+
implementation(libs.sqldelight.native.driver)
143+
144+
// ktor
145+
implementation(libs.ktor.client.darwin)
146+
147+
// file picker
148+
implementation(libs.mpfilepicker)
149+
150+
// kstore
151+
implementation(libs.kstore.file)
152+
}
129153

130154
jsMain.dependencies {
131155
implementation(compose.html.core)

composeApp/src/commonMain/kotlin/utils/Constant.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ const val GEMINI_PRO = "gemini-pro"
55
const val GEMINI_PRO_VISION = "gemini-pro-vision"
66
enum class TYPE{
77
MOBILE,
8+
IOS,
89
DESKTOP,
910
WEB,
1011
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import androidx.compose.ui.window.ComposeUIViewController
2+
import org.koin.mp.KoinPlatform
3+
import presentation.screens.mainscreen.MainViewModel
4+
5+
fun MainViewController() = ComposeUIViewController {
6+
val mainViewModel: MainViewModel = KoinPlatform.getKoin().get()
7+
App(mainViewModel)
8+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package di
2+
3+
import app.cash.sqldelight.async.coroutines.synchronous
4+
import app.cash.sqldelight.db.SqlDriver
5+
import app.cash.sqldelight.driver.native.NativeSqliteDriver
6+
import com.coding.meet.gaminiaikmp.GeminiApiChatDB
7+
8+
actual class DatabaseDriverFactory {
9+
actual suspend fun createDriver(): SqlDriver {
10+
return NativeSqliteDriver(GeminiApiChatDB.Schema.synchronous(), "GeminiApiChatDB.db")
11+
}
12+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package di
2+
3+
import androidx.compose.runtime.Composable
4+
import androidx.compose.runtime.rememberCoroutineScope
5+
import androidx.compose.ui.graphics.ImageBitmap
6+
import androidx.compose.ui.graphics.toComposeImageBitmap
7+
import androidx.compose.ui.platform.ClipboardManager
8+
import androidx.compose.ui.text.AnnotatedString
9+
import com.darkrockstudios.libraries.mpfilepicker.FilePicker
10+
import domain.model.ChatMessage
11+
import domain.model.Group
12+
import io.github.xxfast.kstore.KStore
13+
import kotlinx.coroutines.CoroutineDispatcher
14+
import kotlinx.coroutines.Dispatchers
15+
import kotlinx.coroutines.IO
16+
import kotlinx.coroutines.launch
17+
import org.jetbrains.skia.Image
18+
import platform.Foundation.NSURL
19+
import platform.Foundation.NSURL
20+
import platform.Foundation.NSURLRequest
21+
import platform.Foundation.sendSynchronousRequest
22+
import platform.Foundation.NSError
23+
import platform.Foundation.NSErrorDomain
24+
import platform.Foundation.NSURLConnection
25+
import presentation.components.CommonTextComposable
26+
import utils.AppCoroutineDispatchers
27+
import utils.TYPE
28+
29+
30+
actual fun getPlatform(): TYPE = TYPE.IOS
31+
32+
actual suspend fun clipData(clipboardManager: ClipboardManager): String? {
33+
return clipboardManager.getText()?.text.toString().trim()
34+
}
35+
actual suspend fun setClipData(clipboardManager: ClipboardManager,message:String) {
36+
return clipboardManager.setText(AnnotatedString(message))
37+
}
38+
actual class AppCoroutineDispatchersImpl actual constructor() : AppCoroutineDispatchers {
39+
override val io: CoroutineDispatcher
40+
get() = Dispatchers.IO
41+
override val default: CoroutineDispatcher
42+
get() = Dispatchers.Default
43+
override val main: CoroutineDispatcher
44+
get() = Dispatchers.Main
45+
}
46+
47+
@Composable
48+
actual fun ImagePicker(showFilePicker: Boolean, onResult: (ByteArray?) -> Unit) {
49+
val scope = rememberCoroutineScope()
50+
val fileType = listOf("jpg", "png")
51+
FilePicker(show = showFilePicker, fileExtensions = fileType) { file ->
52+
scope.launch {
53+
file?.getFileByteArray()?.let { onResult(it) }
54+
}
55+
56+
}
57+
}
58+
59+
actual fun ByteArray.toComposeImageBitmap(): ImageBitmap {
60+
return Image.makeFromEncoded(this).toComposeImageBitmap()
61+
}
62+
@Composable
63+
actual fun TextComposable(message:String,isGEMINIMessage:Boolean) {
64+
CommonTextComposable(message,isGEMINIMessage)
65+
}
66+
67+
actual fun isNetworkAvailable(): Boolean {
68+
val url = NSURL.URLWithString("https://www.google.com")
69+
val request = NSURLRequest.requestWithURL(url)
70+
71+
val response: AutoreleasingUnsafeMutablePointer<NSURLResponse?> = null
72+
val error: AutoreleasingUnsafeMutablePointer<NSError?> = null
73+
74+
val data = NSURLConnection.sendSynchronousRequest(request, response, error)
75+
76+
if (data != null && (response != null && response.pointed !is NSHTTPURLResponse)) {
77+
return true
78+
} else {
79+
val nsError = error?.pointed
80+
if (nsError != null && nsError.domain == NSErrorDomain.NSURLErrorDomain) {
81+
return nsError.code != -1009
82+
}
83+
}
84+
85+
return false
86+
}
87+
actual suspend fun readGroupKStore(readFun :suspend (KStore<List<Group>>) -> Unit) {
88+
}
89+
actual suspend fun readChatMessageKStore(readFun :suspend (KStore<List<ChatMessage>>) -> Unit) {
90+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package di
2+
3+
import org.koin.core.module.Module
4+
import org.koin.dsl.module
5+
6+
7+
actual fun platformModule(): Module = module {
8+
single { DatabaseDriverFactory() }
9+
}

gradle.properties

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@ android.useAndroidX=true
1212
org.jetbrains.compose.experimental.wasm.enabled=true
1313
org.jetbrains.compose.experimental.uikit.enabled=true
1414
org.jetbrains.compose.experimental.jscanvas.enabled=true
15+
1516
#MPP
1617
kotlin.mpp.androidSourceSetLayoutVersion=2
18+
kotlin.mpp.enableCInteropCommonization=true
1719

1820
#Development
1921
development=true

gradle/libs.versions.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ androidx-core-i18n = { group = "androidx.core", name = "core-i18n", version.ref
6262

6363
kotlinx-coroutines = {module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref="coroutines"}
6464

65+
ktor-client-darwin = { module = "io.ktor:ktor-client-darwin", version.ref = "ktor" }
6566
ktor-client-okhttp = {module = "io.ktor:ktor-client-android", version.ref = "ktor"}
6667
ktor-client-core = {module = "io.ktor:ktor-client-core", version.ref = "ktor"}
6768
ktor-client-content-negotiation = {module = "io.ktor:ktor-client-content-negotiation", version.ref = "ktor"}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
TEAM_ID=
2+
BUNDLE_ID=com.coding.meet.gaminiaikmp.Gemini-AI-KMP-App
3+
APP_NAME=Gemini-AI-KMP-App

0 commit comments

Comments
 (0)