1
1
package org.flexi.app
2
2
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
6
9
import org.flexi.app.domain.model.version.Platform
7
10
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
10
16
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
11
24
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
12
31
13
32
internal actual fun openUrl (url : String? ) {
14
33
val nsUrl = url?.let { NSURL .URLWithString (it) } ? : return
15
34
UIApplication .sharedApplication.openURL(nsUrl)
16
35
}
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)
24
36
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)
45
37
46
- UIGraphicsEndPDFContext ()
47
- return pdfData as Data
48
- }
49
- }
50
38
actual fun getPlatform (): Platform {
51
39
return Platform .IOS
52
40
}
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 )
59
42
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
68
66
)
69
- return data.toByteArray()
70
- }
67
+ UIGraphicsEndPDFContext ()
71
68
69
+ return pdfData.bytes.let {
70
+ it?.reinterpret<ByteVar >()!! .readBytes(pdfData.length.toInt())
71
+ }
72
+ }
73
+ @OptIn(ExperimentalForeignApi ::class )
72
74
actual fun saveInvoiceToFile (data : ByteArray , fileName : String ) {
73
75
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())
78
82
}
79
83
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 )
83
101
}
0 commit comments