diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml
new file mode 100644
index 0000000..931c4b7
--- /dev/null
+++ b/.idea/deploymentTargetDropDown.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 0ad17cb..8978d23 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,4 +1,3 @@
-
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 7d5eea7..f717f1e 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -60,16 +60,22 @@ dependencies {
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2")
// UI
- implementation("androidx.activity:activity-compose:1.8.0")
+ implementation("androidx.activity:activity-compose:1.8.1")
implementation(platform("androidx.compose:compose-bom:2023.10.01"))
- implementation("androidx.navigation:navigation-compose:2.7.4")
- implementation("androidx.compose.ui:ui:1.6.0-alpha08")
- implementation("androidx.compose.ui:ui-graphics:1.6.0-alpha08")
- implementation("androidx.compose.ui:ui-tooling-preview:1.6.0-alpha08")
- implementation("androidx.compose.material3:material3:1.2.0-alpha10")
+ implementation("androidx.navigation:navigation-compose:2.7.5")
+ implementation("androidx.compose.ui:ui:1.6.0-beta01")
+ implementation("androidx.compose.ui:ui-graphics:1.6.0-beta01")
+ implementation("androidx.compose.ui:ui-tooling-preview:1.6.0-beta01")
+ implementation("androidx.compose.material3:material3:1.2.0-alpha11")
- implementation("io.coil-kt:coil-compose:2.4.0")
+ // Retrofit
+ implementation("com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:1.0.0")
+ implementation("com.squareup.retrofit2:retrofit:2.9.0")
+ implementation("io.coil-kt:coil-compose:2.5.0")
+ implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.1")
+ implementation("com.jcraft:jsch:0.1.55")
+
// Room
implementation("androidx.room:room-runtime:2.6.0")
annotationProcessor("androidx.room:room-compiler:2.6.0")
@@ -82,9 +88,9 @@ dependencies {
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
androidTestImplementation(platform("androidx.compose:compose-bom:2023.10.01"))
- androidTestImplementation("androidx.compose.ui:ui-test-junit4:1.6.0-alpha08")
- debugImplementation("androidx.compose.ui:ui-tooling:1.6.0-alpha08")
- debugImplementation("androidx.compose.ui:ui-test-manifest:1.6.0-alpha08")
+ androidTestImplementation("androidx.compose.ui:ui-test-junit4:1.6.0-beta01")
+ debugImplementation("androidx.compose.ui:ui-tooling:1.6.0-beta01")
+ debugImplementation("androidx.compose.ui:ui-test-manifest:1.6.0-beta01")
}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 78fcc00..7338f2b 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -4,6 +4,8 @@
+
+
-
diff --git a/app/src/main/java/com/zyzf/coffeepreorder/coffee/composeui/CoffeeList.kt b/app/src/main/java/com/zyzf/coffeepreorder/coffee/composeui/CoffeeList.kt
index d522c2b..f19ad6e 100644
--- a/app/src/main/java/com/zyzf/coffeepreorder/coffee/composeui/CoffeeList.kt
+++ b/app/src/main/java/com/zyzf/coffeepreorder/coffee/composeui/CoffeeList.kt
@@ -2,13 +2,23 @@ package com.zyzf.coffeepreorder.coffee.composeui
import android.annotation.SuppressLint
import android.content.res.Configuration
+import android.graphics.Bitmap.CompressFormat
+import android.graphics.BitmapFactory
+import android.net.Uri
+import android.os.StrictMode
+import android.os.StrictMode.ThreadPolicy
+import android.util.Log
+import androidx.activity.compose.rememberLauncherForActivityResult
+import androidx.activity.result.PickVisualMediaRequest
+import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.ExperimentalFoundationApi
+import androidx.compose.foundation.border
+import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.heightIn
@@ -17,6 +27,7 @@ import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
@@ -54,17 +65,31 @@ import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
import coil.compose.AsyncImage
import coil.request.ImageRequest
+import com.jcraft.jsch.Channel
+import com.jcraft.jsch.ChannelSftp
+import com.jcraft.jsch.JSch
+import com.jcraft.jsch.JSchException
+import com.jcraft.jsch.Session
+import com.jcraft.jsch.SftpException
import com.zyzf.coffeepreorder.R
import com.zyzf.coffeepreorder.database.AppDatabase
import com.zyzf.coffeepreorder.database.model.Coffee
import com.zyzf.coffeepreorder.ui.theme.CoffeePreorderTheme
+import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
+import java.io.ByteArrayOutputStream
+import java.io.File
+import java.io.FileOutputStream
+import java.util.Properties
+
@SuppressLint("UnrememberedMutableState")
-@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
+@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class,
+ DelicateCoroutinesApi::class
+)
@Composable
fun CoffeeList(navController: NavController?) {
val openDialog = remember { mutableStateOf(false) }
@@ -72,6 +97,20 @@ fun CoffeeList(navController: NavController?) {
val coffee = remember { mutableStateOf(Coffee("", 0.0, "", null,0)) }
val context = LocalContext.current
val itemsList = remember { mutableStateListOf() }
+
+ var imageUri: Any? by remember { mutableStateOf(R.drawable.img) }
+
+ val photoPicker = rememberLauncherForActivityResult(
+ contract = ActivityResultContracts.PickVisualMedia()
+ ) {
+ if (it != null) {
+ Log.d("PhotoPicker", "Selected URI: $it")
+ imageUri = it
+ } else {
+ Log.d("PhotoPicker", "No media selected")
+ }
+ }
+
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
AppDatabase.getInstance(context).coffeeDao().getAll().collect { data ->
@@ -90,13 +129,15 @@ fun CoffeeList(navController: NavController?) {
horizontalArrangement = Arrangement.SpaceAround) {
AsyncImage(
- model = ImageRequest.Builder(context = LocalContext.current).data("http://109.197.199.134/s/zXgFRTmbR4KMxMH/download?path=%2F&files=coffee_image" + coffee.value.uid + ".png")
+ model = ImageRequest.Builder(context = LocalContext.current).data("https://zyzf.space/s/zXgFRTmbR4KMxMH/download?path=&files=coffee_image_" + currentCoffee.uid +".png")
.crossfade(true).build(),
error = painterResource(R.drawable.ic_broken_image),
placeholder = painterResource(R.drawable.loading_img),
contentDescription = "Кофе",
contentScale = ContentScale.Crop,
- modifier = Modifier.fillMaxHeight().weight(1f)
+ modifier = Modifier
+ .size(100.dp)
+ .clip(RoundedCornerShape(50.dp))
)
Column(
@@ -187,26 +228,66 @@ fun CoffeeList(navController: NavController?) {
},
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Decimal)
)
- OutlinedTextField(modifier = Modifier.fillMaxWidth(),
+ OutlinedTextField(modifier = Modifier.fillMaxWidth().padding(bottom = 10.dp),
value = ingredients, onValueChange = {ingredients = it},
label = {
Text(stringResource(id = R.string.coffee_ingredients))
},
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text)
)
+ AsyncImage(
+ modifier = Modifier
+ .size(100.dp).clip(RoundedCornerShape(50.dp)).border(2.dp, MaterialTheme.colorScheme.outline, shape = RoundedCornerShape(50.dp))
+ .clickable {
+ photoPicker.launch(
+ PickVisualMediaRequest(
+ ActivityResultContracts.PickVisualMedia.ImageOnly
+ )
+ )
+ }.border(2.dp, MaterialTheme.colorScheme.outlineVariant, shape = RoundedCornerShape(50.dp)),
+ contentDescription = "Кофе",
+ error = painterResource(R.drawable.ic_broken_image),
+ placeholder = painterResource(R.drawable.loading_img),
+ contentScale = ContentScale.Crop,
+ model = ImageRequest.Builder(LocalContext.current)
+ .data(if (coffee.value.name != "") "https://zyzf.space/s/zXgFRTmbR4KMxMH/download?path=&files=coffee_image_" + coffee.value.uid +".png" else imageUri)
+ .crossfade(enable = true)
+ .build(),
+ )
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) {
if (add.value) {
Button(onClick = {
GlobalScope.launch (Dispatchers.Main) {
- AppDatabase.getInstance(context).coffeeDao().insert(
- Coffee(name = name, cost = cost, ingredients = ingredients, cartId = null, 0)
+ val newCoffee: Long = AppDatabase.getInstance(context).coffeeDao().insert(
+ name = name, cost = cost, ingredients = ingredients
)
+
+ val inputStream = context.contentResolver.openInputStream(imageUri as Uri)
+ val bitmap = BitmapFactory.decodeStream(inputStream)
+
+ val f = File(context.cacheDir, "coffee_image_$newCoffee.png")
+ withContext(Dispatchers.IO) {
+ f.createNewFile()
+ val bos = ByteArrayOutputStream()
+ bitmap.compress(CompressFormat.PNG, 0 /*ignored for PNG*/, bos)
+ val bitmapdata = bos.toByteArray()
+ val fos = FileOutputStream(f)
+ fos.write(bitmapdata)
+ fos.flush()
+ fos.close()
+ }
+
+
+ copyFileToSftp(f, "/mnt/nextcloud/data/Zyzf/files/Images")
+
+
+
AppDatabase.getInstance(context).coffeeDao().getAll().collect { data ->
itemsList.clear()
itemsList.addAll(data)
}
}
- }) {
+ }, modifier = Modifier.padding(0.dp, 10.dp, 0.dp, 30.dp)) {
Text("Добавить")
}
} else {
@@ -221,7 +302,7 @@ fun CoffeeList(navController: NavController?) {
}
}
- }) {
+ }, modifier = Modifier.padding(0.dp, 10.dp, 0.dp, 30.dp)) {
Text("Изменить")
}
Spacer(modifier = Modifier.padding(all = 20.dp))
@@ -236,7 +317,7 @@ fun CoffeeList(navController: NavController?) {
}
}
- }) {
+ }, modifier = Modifier.padding(0.dp, 10.dp, 0.dp, 30.dp)) {
Text("Удалить")
}
}
@@ -246,6 +327,48 @@ fun CoffeeList(navController: NavController?) {
}
}
+val REMOTE_HOST = "109.197.199.134"
+val USERNAME = "zyzf"
+val PASSWORD = "250303Zyzf-d-grad"
+val REMOTE_PORT = 2223
+
+fun copyFileToSftp(srcFile: File, ftpPath: String): Boolean {
+
+ var jschSession: Session? = null
+
+ try {
+ val jsch = JSch()
+ jsch.setKnownHosts("/home/mkyong/.ssh/known_hosts")
+ jschSession = jsch.getSession(USERNAME, REMOTE_HOST, REMOTE_PORT)
+ jschSession.setPassword(PASSWORD)
+
+ val config = Properties()
+ config["StrictHostKeyChecking"] = "no"
+ jschSession.setConfig(config)
+
+ val policy = ThreadPolicy.Builder().permitAll().build()
+ StrictMode.setThreadPolicy(policy)
+ jschSession.connect(10000)
+ val sftp: Channel = jschSession.openChannel("sftp")
+
+ sftp.connect(5000)
+ val channelSftp: ChannelSftp = sftp as ChannelSftp
+
+ channelSftp.put(srcFile.absolutePath, ftpPath)
+ channelSftp.exit()
+
+ } catch (e: JSchException) {
+ e.printStackTrace()
+ return false
+ } catch (e: SftpException) {
+ e.printStackTrace()
+ return false
+ } finally {
+ jschSession?.disconnect()
+ }
+ return true
+}
+
@Preview(name = "Light Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_NO)
@Preview(name = "Dark Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
diff --git a/app/src/main/java/com/zyzf/coffeepreorder/composeui/Login.kt b/app/src/main/java/com/zyzf/coffeepreorder/composeui/Login.kt
index 6d05c4d..50383be 100644
--- a/app/src/main/java/com/zyzf/coffeepreorder/composeui/Login.kt
+++ b/app/src/main/java/com/zyzf/coffeepreorder/composeui/Login.kt
@@ -42,11 +42,13 @@ import com.zyzf.coffeepreorder.composeui.navigation.Screen
import com.zyzf.coffeepreorder.database.AppDatabase
import com.zyzf.coffeepreorder.database.model.User
import com.zyzf.coffeepreorder.ui.theme.CoffeePreorderTheme
+import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
+@OptIn(DelicateCoroutinesApi::class)
@Composable
fun Login(navController: NavController?) {
val context = LocalContext.current
@@ -59,14 +61,15 @@ fun Login(navController: NavController?) {
}
Column(Modifier.padding(all = 10.dp), horizontalAlignment = Alignment.CenterHorizontally) {
AsyncImage(
- model = ImageRequest.Builder(context = LocalContext.current).data("http://109.197.199.134/s/zXgFRTmbR4KMxMH/download?path=%2F&files=coffee_image.png")
+ model = ImageRequest.Builder(context = LocalContext.current).data("https://zyzf.space/s/YsHjPo3NDmoptSk/download/coffee_image.png")
.crossfade(true).build(),
error = painterResource(R.drawable.ic_broken_image),
placeholder = painterResource(R.drawable.loading_img),
contentDescription = "Кофе",
contentScale = ContentScale.Crop,
- modifier = Modifier
+ modifier = Modifier.size(100.dp)
)
+
Spacer(modifier = Modifier.padding(all = 20.dp))
OutlinedTextField(modifier = Modifier.fillMaxWidth(),
value = login, onValueChange = {login = it},
diff --git a/app/src/main/java/com/zyzf/coffeepreorder/database/AppDatabase.kt b/app/src/main/java/com/zyzf/coffeepreorder/database/AppDatabase.kt
index 5c6094d..9ee6171 100644
--- a/app/src/main/java/com/zyzf/coffeepreorder/database/AppDatabase.kt
+++ b/app/src/main/java/com/zyzf/coffeepreorder/database/AppDatabase.kt
@@ -47,17 +47,17 @@ abstract class AppDatabase : RoomDatabase() {
val coffee9 = Coffee("Coffee9", 200.0, "Ing1", null, 0)
val coffee10 = Coffee("Coffee10", 900.0, "Ing1", null, 0)
val coffee11 = Coffee("Coffee11", 200.0, "Ing1", null, 0)
- coffeeDao.insert(coffee1)
- coffeeDao.insert(coffee2)
- coffeeDao.insert(coffee3)
- coffeeDao.insert(coffee4)
- coffeeDao.insert(coffee5)
- coffeeDao.insert(coffee6)
- coffeeDao.insert(coffee7)
- coffeeDao.insert(coffee8)
- coffeeDao.insert(coffee9)
- coffeeDao.insert(coffee10)
- coffeeDao.insert(coffee11)
+ coffeeDao.insert(coffee1.name, coffee1.cost, coffee1.ingredients)
+ coffeeDao.insert(coffee2.name, coffee2.cost, coffee2.ingredients)
+ coffeeDao.insert(coffee3.name, coffee3.cost, coffee3.ingredients)
+ coffeeDao.insert(coffee4.name, coffee4.cost, coffee4.ingredients)
+ coffeeDao.insert(coffee5.name, coffee5.cost, coffee5.ingredients)
+ coffeeDao.insert(coffee6.name, coffee6.cost, coffee6.ingredients)
+ coffeeDao.insert(coffee7.name, coffee7.cost, coffee7.ingredients)
+ coffeeDao.insert(coffee8.name, coffee8.cost, coffee8.ingredients)
+ coffeeDao.insert(coffee9.name, coffee9.cost, coffee9.ingredients)
+ coffeeDao.insert(coffee10.name, coffee10.cost, coffee10.ingredients)
+ coffeeDao.insert(coffee11.name, coffee11.cost, coffee11.ingredients)
// Cart
val cartDao = database.cartDao()
val cart = Cart()
diff --git a/app/src/main/java/com/zyzf/coffeepreorder/database/dao/CoffeeDao.kt b/app/src/main/java/com/zyzf/coffeepreorder/database/dao/CoffeeDao.kt
index d739d78..fd7fd74 100644
--- a/app/src/main/java/com/zyzf/coffeepreorder/database/dao/CoffeeDao.kt
+++ b/app/src/main/java/com/zyzf/coffeepreorder/database/dao/CoffeeDao.kt
@@ -2,7 +2,6 @@ package com.zyzf.coffeepreorder.database.dao
import androidx.room.Dao
import androidx.room.Delete
-import androidx.room.Insert
import androidx.room.Query
import androidx.room.Update
import com.zyzf.coffeepreorder.database.model.Coffee
@@ -17,8 +16,8 @@ interface CoffeeDao {
@Query("select coffee.uid, name, cost, ingredients, cart_id, count, cart.uid as cart_uid from coffee left join cart on coffee.cart_id = cart.uid where coffee.uid = :uid")
suspend fun getByUid(uid: Int): CoffeeWithCart
- @Insert
- suspend fun insert(coffee: Coffee)
+ @Query("insert into coffee (name, cost, ingredients, count) values (:name, :cost, :ingredients, 0)")
+ suspend fun insert(name: String, cost: Double, ingredients: String): Long
@Update
suspend fun update(coffee: Coffee)
diff --git a/app/src/main/res/drawable/img.xml b/app/src/main/res/drawable/img.xml
new file mode 100644
index 0000000..a8b409b
--- /dev/null
+++ b/app/src/main/res/drawable/img.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/build.gradle.kts b/build.gradle.kts
index 05aec1c..fc2b935 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,6 +1,6 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
- id("com.android.application") version "8.1.2" apply false
+ id("com.android.application") version "8.1.3" apply false
id("org.jetbrains.kotlin.android") version "1.9.10" apply false
id("com.google.devtools.ksp") version "1.9.10-1.0.13" apply false
}
\ No newline at end of file
diff --git a/settings.gradle.kts b/settings.gradle.kts
index c5472bc..93fbf89 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -10,6 +10,7 @@ dependencyResolutionManagement {
repositories {
google()
mavenCentral()
+ maven { setUrl("https://jitpack.io") }
}
}