Skip to content

Commit 9a15a02

Browse files
committed
-iOS App Enhancement Impl
1 parent e6188fb commit 9a15a02

File tree

10 files changed

+80
-105
lines changed

10 files changed

+80
-105
lines changed

composeApp/build.gradle.kts

+1-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ kotlin {
8585
implementation("io.github.jan-tennert.supabase:gotrue-kt:2.3.1")
8686
implementation("io.github.jan-tennert.supabase:compose-auth:2.3.1")
8787
implementation("io.github.jan-tennert.supabase:compose-auth-ui:2.3.1")
88-
implementation(libs.alert.kmp)
88+
//implementation(libs.alert.kmp)
8989
}
9090

9191
commonTest.dependencies {

composeApp/src/androidMain/kotlin/org/flexi/app/App.android.kt

-7
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import androidx.activity.compose.setContent
1010
import androidx.activity.enableEdgeToEdge
1111
import app.cash.sqldelight.db.SqlDriver
1212
import app.cash.sqldelight.driver.android.AndroidSqliteDriver
13-
import org.flexi.app.db.MyDatabase
1413
import org.flexi.app.di.appModule
1514
import org.flexi.app.domain.model.version.Platform
1615
import org.flexi.app.presentation.ui.screens.payment.model.Order
@@ -52,12 +51,6 @@ actual fun getPlatform(): Platform {
5251
return Platform.Android
5352
}
5453

55-
actual class DriverFactory actual constructor() {
56-
private var context: Context = AndroidApp.INSTANCE.applicationContext
57-
actual fun createDriver(): SqlDriver {
58-
return AndroidSqliteDriver(MyDatabase.Schema, context, "MyDatabase.db")
59-
}
60-
}
6154

6255
actual fun generateInvoicePdf(order: Order): ByteArray {
6356
val pdfDocument = android.graphics.pdf.PdfDocument()

composeApp/src/commonMain/kotlin/org/flexi/app/App.kt

-4
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ import androidx.compose.ui.draw.clip
4343
import androidx.compose.ui.graphics.Color
4444
import androidx.compose.ui.unit.dp
4545
import androidx.compose.ui.unit.sp
46-
import app.cash.sqldelight.db.SqlDriver
4746
import cafe.adriel.voyager.navigator.Navigator
4847
import cafe.adriel.voyager.navigator.tab.LocalTabNavigator
4948
import cafe.adriel.voyager.navigator.tab.Tab
@@ -238,9 +237,6 @@ fun RowScope.TabItem(tab: Tab) {
238237

239238
internal expect fun openUrl(url: String?)
240239
expect fun getPlatform(): Platform
241-
expect class DriverFactory() {
242-
fun createDriver(): SqlDriver
243-
}
244240

245241
expect fun generateInvoicePdf(order: Order): ByteArray
246242
expect fun saveInvoiceToFile(data: ByteArray, fileName: String)

composeApp/src/commonMain/kotlin/org/flexi/app/presentation/ui/screens/setting/account/AccountScreen.kt

-6
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ import androidx.compose.material3.Text
3434
import androidx.compose.material3.TextFieldDefaults
3535
import androidx.compose.material3.TopAppBarDefaults
3636
import androidx.compose.runtime.Composable
37-
import androidx.compose.runtime.LaunchedEffect
3837
import androidx.compose.runtime.collectAsState
3938
import androidx.compose.runtime.getValue
4039
import androidx.compose.runtime.mutableStateOf
@@ -49,11 +48,8 @@ import androidx.compose.ui.unit.dp
4948
import androidx.compose.ui.unit.sp
5049
import cafe.adriel.voyager.core.screen.Screen
5150
import cafe.adriel.voyager.navigator.LocalNavigator
52-
import createNotification
5351
import org.flexi.app.domain.model.user.User
5452
import org.flexi.app.domain.usecase.ResultState
55-
import org.flexi.app.presentation.ui.components.ErrorBox
56-
import org.flexi.app.presentation.ui.components.LoadingBox
5753
import org.flexi.app.presentation.viewmodels.MainViewModel
5854
import org.koin.compose.koinInject
5955

@@ -76,7 +72,6 @@ class AccountScreen(
7672
var editedCountry by remember { mutableStateOf(user.country) }
7773
var editedPostalCode by remember { mutableStateOf(user.postalCode) }
7874
var editedPhoneNumber by remember { mutableStateOf(user.phoneNumber) }
79-
val notification = createNotification(type = NotificationType.TOAST)
8075

8176
val usersState by viewModel.updateUsersDetails.collectAsState()
8277
when(usersState){
@@ -90,7 +85,6 @@ class AccountScreen(
9085
is ResultState.Success -> {
9186
val response = (usersState as ResultState.Success).response
9287
isUpdated = response
93-
notification.show(response.toString())
9488
}
9589
}
9690
Scaffold(
Original file line numberDiff line numberDiff line change
@@ -1,83 +1,101 @@
11
package org.flexi.app
22

3-
import app.cash.sqldelight.db.SqlDriver
4-
import app.cash.sqldelight.driver.native.NativeSqliteDriver
5-
import org.flexi.app.db.MyDatabase
3+
import kotlinx.cinterop.ByteVar
4+
import kotlinx.cinterop.ExperimentalForeignApi
5+
import kotlinx.cinterop.addressOf
6+
import kotlinx.cinterop.readBytes
7+
import kotlinx.cinterop.reinterpret
8+
import kotlinx.cinterop.usePinned
69
import org.flexi.app.domain.model.version.Platform
710
import org.flexi.app.presentation.ui.screens.payment.model.Order
8-
import platform.Foundation.*
9-
import platform.UIKit.*
11+
import platform.CoreGraphics.CGRectMake
12+
import platform.Foundation.NSData
13+
import platform.Foundation.NSDocumentDirectory
14+
import platform.Foundation.NSFileManager
15+
import platform.Foundation.NSMutableData
1016
import platform.Foundation.NSURL
17+
import platform.Foundation.NSUserDomainMask
18+
import platform.Foundation.create
19+
import platform.Foundation.writeToFile
20+
import platform.UIKit.NSFontAttributeName
21+
import platform.UIKit.NSMutableParagraphStyle
22+
import platform.UIKit.NSParagraphStyleAttributeName
23+
import platform.UIKit.NSTextAlignmentLeft
1124
import platform.UIKit.UIApplication
25+
import platform.UIKit.UIFont
26+
import platform.UIKit.UIGraphicsBeginPDFContextToData
27+
import platform.UIKit.UIGraphicsBeginPDFPageWithInfo
28+
import platform.UIKit.UIGraphicsEndPDFContext
29+
import platform.UIKit.UIGraphicsGetCurrentContext
30+
import platform.posix.memcpy
1231

1332
internal actual fun openUrl(url: String?) {
1433
val nsUrl = url?.let { NSURL.URLWithString(it) } ?: return
1534
UIApplication.sharedApplication.openURL(nsUrl)
1635
}
17-
@objc class PDFGenerator: NSObject {
18-
@objc static func generateInvoice(orderId: Int, userId: Int, orderDate: String, deliveryDate: String, productIds: [Int], totalQuantity: Int, totalPrice: Double) -> Data {
19-
let pdfData = NSMutableData()
20-
UIGraphicsBeginPDFContextToData(pdfData, CGRect.zero, nil)
21-
UIGraphicsBeginPDFPage()
22-
let context = UIGraphicsGetCurrentContext()
23-
context?.setFillColor(UIColor.black.cgColor)
2436

25-
let text = """
26-
Invoice
27-
Order #\(orderId)
28-
Customer ID: #\(userId)
29-
Order Date: \(orderDate)
30-
Delivery Date: \(deliveryDate)
31-
Product: \(productIds)
32-
Quantity: \(totalQuantity)
33-
Price: \(totalPrice)
34-
Total: \(totalPrice)
35-
"""
36-
37-
let paragraphStyle = NSMutableParagraphStyle()
38-
paragraphStyle.alignment = .left
39-
let attributes = [
40-
NSAttributedString.Key.font: UIFont.systemFont(ofSize: 12),
41-
NSAttributedString.Key.paragraphStyle: paragraphStyle
42-
]
43-
44-
text.draw(in: CGRect(x: 100, y: 50, width: 400, height: 700), withAttributes: attributes)
4537

46-
UIGraphicsEndPDFContext()
47-
return pdfData as Data
48-
}
49-
}
5038
actual fun getPlatform(): Platform {
5139
return Platform.IOS
5240
}
53-
54-
actual class DriverFactory actual constructor() {
55-
actual fun createDriver(): SqlDriver {
56-
return NativeSqliteDriver(MyDatabase.Schema,"YouTubeDatabase.db")
57-
}
58-
}
41+
@OptIn(ExperimentalForeignApi::class)
5942
actual fun generateInvoicePdf(order: Order): ByteArray {
60-
val data = PDFGenerator.generateInvoice(
61-
orderId = order.id,
62-
userId = order.userId,
63-
orderDate = order.orderDate,
64-
deliveryDate = order.deliveryDate,
65-
productIds = order.productIds.toIntArray(),
66-
totalQuantity = order.totalQuantity,
67-
totalPrice = order.totalPrice
43+
val pdfData = NSMutableData()
44+
val pageSize = CGRectMake(0.0, 0.0, 612.0, 792.0)
45+
46+
UIGraphicsBeginPDFContextToData(pdfData, pageSize, null)
47+
UIGraphicsBeginPDFPageWithInfo(pageSize, null)
48+
49+
val context = UIGraphicsGetCurrentContext()
50+
51+
val text = """
52+
Invoice
53+
Order #${order.id}
54+
Customer ID: #${order.userId}
55+
Order Date: ${order.orderDate}
56+
Delivery Date: ${order.deliveryDate}
57+
Products: ${order.productIds}
58+
Quantity: ${order.totalQuantity}
59+
Total Price: ${order.totalPrice}
60+
""".trimIndent()
61+
62+
val paragraphStyle = NSMutableParagraphStyle().apply { NSTextAlignmentLeft }
63+
val attributes: Map<Any?, Any?> = mapOf(
64+
NSFontAttributeName to UIFont.systemFontOfSize(12.0),
65+
NSParagraphStyleAttributeName to paragraphStyle
6866
)
69-
return data.toByteArray()
70-
}
67+
UIGraphicsEndPDFContext()
7168

69+
return pdfData.bytes.let {
70+
it?.reinterpret<ByteVar>()!!.readBytes(pdfData.length.toInt())
71+
}
72+
}
73+
@OptIn(ExperimentalForeignApi::class)
7274
actual fun saveInvoiceToFile(data: ByteArray, fileName: String) {
7375
val fileManager = NSFileManager.defaultManager
74-
val documentsURL = fileManager.URLsForDirectory(NSDocumentDirectory, NSUserDomainMask).lastObject as NSURL
75-
val fileURL = documentsURL.URLByAppendingPathComponent(fileName)
76-
data.usePinned {
77-
NSData.dataWithBytes(it.addressOf(0), data.size.toULong()).writeToURL(fileURL, true)
76+
val documentsDirectory = fileManager.URLsForDirectory(NSDocumentDirectory, NSUserDomainMask).firstOrNull()
77+
78+
val documentPath = documentsDirectory
79+
80+
val nsData = data.usePinned { pinnedData ->
81+
NSData.create(bytes = pinnedData.addressOf(0), length = data.size.toULong())
7882
}
7983

80-
val documentInteractionController = UIDocumentInteractionController.interactionControllerWithURL(fileURL)
81-
documentInteractionController.delegate = object : NSObject(), UIDocumentInteractionControllerDelegateProtocol {}
82-
documentInteractionController.presentOptionsMenuFromRect(CGRectZero, UIWindow.keyWindow, true)
84+
try {
85+
nsData.writeToFile(documentPath.toString(), true)
86+
documentPath.toString()
87+
} catch (e: Exception){
88+
"Failed to save PDF: ${e.message}"
89+
}
90+
}
91+
92+
@OptIn(ExperimentalForeignApi::class)
93+
fun NSData.toByteArray(): ByteArray {
94+
return this.bytes?.let { bytesPointer ->
95+
ByteArray(this.length.toInt()).apply {
96+
usePinned { pinned ->
97+
memcpy(pinned.addressOf(0), bytesPointer, this@toByteArray.length)
98+
}
99+
}
100+
} ?: ByteArray(0)
83101
}

composeApp/src/jsMain/kotlin/org/flexi/app/App.js.kt

-11
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
11
package org.flexi.app
22

3-
import app.cash.sqldelight.db.SqlDriver
4-
import app.cash.sqldelight.driver.worker.WebWorkerDriver
53
import io.kamel.core.utils.URL
64
import kotlinx.browser.document
75
import kotlinx.browser.window
8-
import kotlinx.datetime.internal.JsNonModule
9-
import org.flexi.app.db.MyDatabase
106
import org.flexi.app.domain.model.version.Platform
117
import org.flexi.app.presentation.ui.screens.payment.model.Order
128
import org.w3c.dom.HTMLAnchorElement
@@ -21,13 +17,6 @@ actual fun getPlatform(): Platform {
2117
return Platform.Web
2218
}
2319

24-
actual class DriverFactory actual constructor() {
25-
actual fun createDriver(): SqlDriver {
26-
val workerScriptUrl = js("import.meta.url.replace('kotlin', 'node_modules/@cashapp/sqldelight-sqljs-worker/sqljs.worker.js')")
27-
val driver = WebWorkerDriver(workerScriptUrl).also { MyDatabase.Schema.create(it) }
28-
return driver
29-
}
30-
}
3120
external class jsPDF {
3221
fun text(text: String, x: Int, y: Int)
3322
fun save(filename: String)

composeApp/src/jvmMain/kotlin/org/flexi/app/App.jvm.kt

-12
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
package org.flexi.app
22

3-
import app.cash.sqldelight.db.SqlDriver
4-
import app.cash.sqldelight.driver.jdbc.sqlite.JdbcSqliteDriver
53
import org.apache.pdfbox.pdmodel.PDDocument
64
import org.apache.pdfbox.pdmodel.PDPage
75
import org.apache.pdfbox.pdmodel.PDPageContentStream
86
import org.apache.pdfbox.pdmodel.font.PDType1Font
9-
import org.flexi.app.db.MyDatabase
107
import org.flexi.app.domain.model.version.Platform
118
import org.flexi.app.presentation.ui.screens.payment.model.Order
129
import java.awt.Desktop
@@ -23,15 +20,6 @@ actual fun getPlatform(): Platform {
2320
return Platform.Desktop
2421
}
2522

26-
actual class DriverFactory actual constructor() {
27-
actual fun createDriver(): SqlDriver {
28-
val driver = JdbcSqliteDriver(JdbcSqliteDriver.IN_MEMORY)
29-
if (!File("YouTubeDatabase.db").exists()) {
30-
MyDatabase.Schema.create(driver)
31-
}
32-
return driver
33-
}
34-
}
3523
actual fun generateInvoicePdf(order: Order): ByteArray {
3624
val document = PDDocument()
3725
val page = PDPage()

gradle/libs.versions.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ moko-mvvm = "0.16.1"
1515
ktor = "2.3.12"
1616
kotlinx-serialization = "1.7.1"
1717
kotlinx-datetime = "0.6.0"
18-
koin = "3.6.0-Beta4"
19-
koinComposeMultiplatform = "1.2.0-Beta4"
18+
koin = "3.6.0-Beta5"
19+
koinComposeMultiplatform = "1.2.0-Beta5"
2020
size = "0.5.0"
2121
kamel = "0.9.5"
2222
sqlDelight = "2.0.2"

gradlew

100644100755
File mode changed.

iosApp/iosApp/iosApp.swift

-3
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@ import ComposeApp
44
@main
55
class AppDelegate: UIResponder, UIApplicationDelegate {
66
var window: UIWindow?
7-
init(){
8-
Main_iosKt.doInitKoin()
9-
}
107
func application(
118
_ application: UIApplication,
129
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?

0 commit comments

Comments
 (0)