diff --git a/domain/src/main/java/com/foke/together/domain/interactor/entity/CutFrameType.kt b/domain/src/main/java/com/foke/together/domain/interactor/entity/CutFrameType.kt index 89f9b48..3622bcf 100644 --- a/domain/src/main/java/com/foke/together/domain/interactor/entity/CutFrameType.kt +++ b/domain/src/main/java/com/foke/together/domain/interactor/entity/CutFrameType.kt @@ -3,6 +3,7 @@ package com.foke.together.domain.interactor.entity import androidx.annotation.DrawableRes import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign import com.foke.together.domain.R abstract class CutFrame( @@ -47,9 +48,9 @@ sealed class DefaultCutFrameSet ( PhotoPosition(159, 106, 16, 369), ), emptyList(), - datePosition = TextStickerPosition(139,541,R.font.cascadia_mono, color = Color(34, 34, 34), fontWeight = FontWeight.ExtraBold, fontSize = 6), - copyrightPosition = TextStickerPosition(122,547,R.font.cascadia_mono, color = Color(34, 34, 34), fontWeight = FontWeight.ExtraBold, fontSize = 6), - qrCodePosition = QrStickerPosition(25,16,530) + datePosition = TextStickerPosition(80, 10, 91,541,R.font.cascadia_mono, color = Color(34, 34, 34), fontWeight = FontWeight.ExtraBold, fontSize = 6, textAlign = TextAlign.End), + copyrightPosition = TextStickerPosition(80, 10, 91,547,R.font.cascadia_mono, color = Color(34, 34, 34), fontWeight = FontWeight.ExtraBold, fontSize = 6, textAlign = TextAlign.End), + qrCodePosition = QrStickerPosition(30,16,530) ) data object FourCurDark: DefaultCutFrameSet( @@ -64,9 +65,9 @@ data object FourCurDark: DefaultCutFrameSet( PhotoPosition(159, 106, 16, 369), ), emptyList(), - datePosition = TextStickerPosition(139,541,R.font.cascadia_mono, color = Color(170, 170, 170), fontWeight = FontWeight.ExtraBold, fontSize = 6), - copyrightPosition = TextStickerPosition(122,547,R.font.cascadia_mono, color = Color(170, 170, 170), fontWeight = FontWeight.ExtraBold, fontSize = 6), - qrCodePosition = QrStickerPosition(25,16,530) + datePosition = TextStickerPosition(80, 10, 91,541,R.font.cascadia_mono, color = Color(170, 170, 170), fontWeight = FontWeight.ExtraBold, fontSize = 6, textAlign = TextAlign.End), + copyrightPosition = TextStickerPosition(80, 10, 91,547,R.font.cascadia_mono, color = Color(170, 170, 170), fontWeight = FontWeight.ExtraBold, fontSize = 6, textAlign = TextAlign.End), + qrCodePosition = QrStickerPosition(30,16,530) ) data object MakerFaire: DefaultCutFrameSet( @@ -81,9 +82,9 @@ data object FourCurDark: DefaultCutFrameSet( PhotoPosition(159, 106, 16, 369), ), emptyList(), - datePosition = TextStickerPosition(139,541,R.font.cascadia_mono, color = Color(238, 238, 238), fontWeight = FontWeight.ExtraBold, fontSize = 6), - copyrightPosition = TextStickerPosition(122,547,R.font.cascadia_mono, color = Color(238, 238, 238), fontWeight = FontWeight.ExtraBold, fontSize = 6), - qrCodePosition = QrStickerPosition(25,16,530) + datePosition = TextStickerPosition(80, 10, 91,541,R.font.cascadia_mono, color = Color(238, 238, 238), fontWeight = FontWeight.ExtraBold, fontSize = 6, textAlign = TextAlign.End), + copyrightPosition = TextStickerPosition(80, 10, 91,547,R.font.cascadia_mono, color = Color(238, 238, 238), fontWeight = FontWeight.ExtraBold, fontSize = 6, textAlign = TextAlign.End), + qrCodePosition = QrStickerPosition(30,16,530) ) data object MakerFaire25_1: DefaultCutFrameSet( @@ -100,9 +101,9 @@ data object FourCurDark: DefaultCutFrameSet( listOf( R.drawable.maker_faire_frame_25_1 ), - datePosition = TextStickerPosition(139,541,R.font.cascadia_mono, color = Color(34, 34, 34), fontWeight = FontWeight.ExtraBold, fontSize = 6), - copyrightPosition = TextStickerPosition(122,547,R.font.cascadia_mono, color = Color(34, 34, 34), fontWeight = FontWeight.ExtraBold, fontSize = 6), - qrCodePosition = QrStickerPosition(25,149,517) + datePosition = TextStickerPosition(80, 10, 92,546,R.font.cascadia_mono, color = Color(34, 34, 34), fontWeight = FontWeight.ExtraBold, fontSize = 6, textAlign = TextAlign.End), + copyrightPosition = TextStickerPosition(80, 10, 92,551,R.font.cascadia_mono, color = Color(34, 34, 34), fontWeight = FontWeight.ExtraBold, fontSize = 6, textAlign = TextAlign.End), + qrCodePosition = QrStickerPosition(30,145,515) ) data object MakerFaire25_2: DefaultCutFrameSet( @@ -119,9 +120,9 @@ data object FourCurDark: DefaultCutFrameSet( listOf( R.drawable.maker_faire_frame_25_2 ), - datePosition = TextStickerPosition(139,541,R.font.cascadia_mono, color = Color(34, 34, 34), fontWeight = FontWeight.ExtraBold, fontSize = 6), - copyrightPosition = TextStickerPosition(122,547,R.font.cascadia_mono, color = Color(34, 34, 34), fontWeight = FontWeight.ExtraBold, fontSize = 6), - qrCodePosition = QrStickerPosition(25,149,517) + datePosition = TextStickerPosition(80, 10, 92,546,R.font.cascadia_mono, color = Color(34, 34, 34), fontWeight = FontWeight.ExtraBold, fontSize = 6, textAlign = TextAlign.End), + copyrightPosition = TextStickerPosition(80, 10, 92,551,R.font.cascadia_mono, color = Color(34, 34, 34), fontWeight = FontWeight.ExtraBold, fontSize = 6, textAlign = TextAlign.End), + qrCodePosition = QrStickerPosition(30,145,515) ) data object MakerFaire25_3: DefaultCutFrameSet( @@ -138,9 +139,9 @@ data object FourCurDark: DefaultCutFrameSet( listOf( R.drawable.maker_faire_frame_25_3 ), - datePosition = TextStickerPosition(139,541,R.font.cascadia_mono, color = Color(34, 34, 34), fontWeight = FontWeight.ExtraBold, fontSize = 6), - copyrightPosition = TextStickerPosition(122,547,R.font.cascadia_mono, color = Color(34, 34, 34), fontWeight = FontWeight.ExtraBold, fontSize = 6), - qrCodePosition = QrStickerPosition(25,149,517) + datePosition = TextStickerPosition(80, 10, 92,546,R.font.cascadia_mono, color = Color(34, 34, 34), fontWeight = FontWeight.ExtraBold, fontSize = 6, textAlign = TextAlign.End), + copyrightPosition = TextStickerPosition(80, 10, 92,551,R.font.cascadia_mono, color = Color(34, 34, 34), fontWeight = FontWeight.ExtraBold, fontSize = 6, textAlign = TextAlign.End), + qrCodePosition = QrStickerPosition(30,145,515) ) data object MakerFaire25_4: DefaultCutFrameSet( @@ -157,9 +158,9 @@ data object FourCurDark: DefaultCutFrameSet( listOf( R.drawable.maker_faire_frame_25_4 ), - datePosition = TextStickerPosition(139,541,R.font.cascadia_mono, color = Color(34, 34, 34), fontWeight = FontWeight.ExtraBold, fontSize = 6), - copyrightPosition = TextStickerPosition(122,547,R.font.cascadia_mono, color = Color(34, 34, 34), fontWeight = FontWeight.ExtraBold, fontSize = 6), - qrCodePosition = QrStickerPosition(25,149,517) + datePosition = TextStickerPosition(80, 10, 92,546,R.font.cascadia_mono, color = Color(34, 34, 34), fontWeight = FontWeight.ExtraBold, fontSize = 6, textAlign = TextAlign.End), + copyrightPosition = TextStickerPosition(80, 10, 92,551,R.font.cascadia_mono, color = Color(34, 34, 34), fontWeight = FontWeight.ExtraBold, fontSize = 6, textAlign = TextAlign.End), + qrCodePosition = QrStickerPosition(30,145,515) ) companion object { diff --git a/domain/src/main/java/com/foke/together/domain/interactor/entity/SessionData.kt b/domain/src/main/java/com/foke/together/domain/interactor/entity/SessionData.kt index f7ed37f..ae3db63 100644 --- a/domain/src/main/java/com/foke/together/domain/interactor/entity/SessionData.kt +++ b/domain/src/main/java/com/foke/together/domain/interactor/entity/SessionData.kt @@ -1,8 +1,11 @@ package com.foke.together.domain.interactor.entity +import android.graphics.Bitmap + data class SessionData ( val sessionId: SessionId, val cutFrame: CutFrame? = null, + val qrCodeBitmap: Bitmap? = null, val status: Status ) diff --git a/domain/src/main/java/com/foke/together/domain/interactor/entity/TextStickerPosition.kt b/domain/src/main/java/com/foke/together/domain/interactor/entity/TextStickerPosition.kt index 5e90944..53bf265 100644 --- a/domain/src/main/java/com/foke/together/domain/interactor/entity/TextStickerPosition.kt +++ b/domain/src/main/java/com/foke/together/domain/interactor/entity/TextStickerPosition.kt @@ -3,8 +3,11 @@ package com.foke.together.domain.interactor.entity import androidx.annotation.FontRes import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign data class TextStickerPosition ( + val width: Int, + val height: Int, val x: Int, val y: Int, @FontRes val font: Int, @@ -12,5 +15,6 @@ data class TextStickerPosition ( val backgroundColor: Color = Color(0,0,0,0), val fontWeight: FontWeight, val fontSize: Int, - val rotation: Float = 0f + val rotation: Float = 0f, + val textAlign: TextAlign = TextAlign.Left, ) \ No newline at end of file diff --git a/domain/src/main/java/com/foke/together/domain/interactor/session/UpdateSessionStatusUseCase.kt b/domain/src/main/java/com/foke/together/domain/interactor/session/UpdateSessionStatusUseCase.kt index 925c909..6f73aa9 100644 --- a/domain/src/main/java/com/foke/together/domain/interactor/session/UpdateSessionStatusUseCase.kt +++ b/domain/src/main/java/com/foke/together/domain/interactor/session/UpdateSessionStatusUseCase.kt @@ -1,5 +1,6 @@ package com.foke.together.domain.interactor.session +import android.graphics.Bitmap import com.foke.together.domain.interactor.entity.CutFrame import com.foke.together.domain.interactor.entity.Status import com.foke.together.domain.output.SessionRepositoryInterface @@ -15,4 +16,8 @@ class UpdateSessionStatusUseCase @Inject constructor( operator fun invoke(cutFrame: CutFrame) { sessionRepository.updateSession(cutFrame) } + + operator fun invoke(qrCodeBitmap: Bitmap) { + sessionRepository.updateSession(qrCodeBitmap) + } } \ No newline at end of file diff --git a/domain/src/main/java/com/foke/together/domain/interactor/web/RegisterUseCase.kt b/domain/src/main/java/com/foke/together/domain/interactor/web/RegisterUseCase.kt new file mode 100644 index 0000000..0e7c274 --- /dev/null +++ b/domain/src/main/java/com/foke/together/domain/interactor/web/RegisterUseCase.kt @@ -0,0 +1,19 @@ +package com.foke.together.domain.interactor.web + +import com.foke.together.domain.interactor.entity.AccountData +import com.foke.together.domain.output.RemoteRepositoryInterface +import com.foke.together.util.AppLog +import javax.inject.Inject + +class RegisterUseCase @Inject constructor( + private val remoteRepository: RemoteRepositoryInterface, +) { + suspend operator fun invoke(id: String, password: String, name: String): Result { + return remoteRepository.registerAccount(AccountData(id, password, name)) + .onSuccess { + AppLog.i("RegisterUseCase", "init", "register success: ${it}") + }.onFailure { ee -> + AppLog.e("RegisterUseCase", "init", "error: ${ee}") + } + } +} \ No newline at end of file diff --git a/domain/src/main/java/com/foke/together/domain/interactor/web/UploadFileUseCase.kt b/domain/src/main/java/com/foke/together/domain/interactor/web/UploadFileUseCase.kt index 700991e..3531579 100644 --- a/domain/src/main/java/com/foke/together/domain/interactor/web/UploadFileUseCase.kt +++ b/domain/src/main/java/com/foke/together/domain/interactor/web/UploadFileUseCase.kt @@ -15,6 +15,9 @@ class UploadFileUseCase @Inject constructor( .onSuccess { preSignedUrl -> AppLog.e(TAG, "invoke", "preSignedUrl: $preSignedUrl") remoteRepository.uploadFile(preSignedUrl, file) + .onSuccess { + return Result.success(Unit) + } .onFailure { AppLog.e(TAG, "invoke", "upload failed") return Result.failure(Exception("cannot upload file: $it")) diff --git a/domain/src/main/java/com/foke/together/domain/output/SessionRepositoryInterface.kt b/domain/src/main/java/com/foke/together/domain/output/SessionRepositoryInterface.kt index 716fe73..2d89070 100644 --- a/domain/src/main/java/com/foke/together/domain/output/SessionRepositoryInterface.kt +++ b/domain/src/main/java/com/foke/together/domain/output/SessionRepositoryInterface.kt @@ -1,5 +1,6 @@ package com.foke.together.domain.output +import android.graphics.Bitmap import com.foke.together.domain.interactor.entity.CutFrame import com.foke.together.domain.interactor.entity.SessionData import com.foke.together.domain.interactor.entity.Status @@ -12,6 +13,7 @@ interface SessionRepositoryInterface { fun updateSession(cutFrame: CutFrame) fun updateSession(status: Status) fun updateSession(cutFrame: CutFrame, status: Status) + fun updateSession(qrCodeBitmap: Bitmap) fun clearSession() } \ No newline at end of file diff --git a/domain/src/main/res/drawable/fourcut_frame_dark_25.png b/domain/src/main/res/drawable/fourcut_frame_dark_25.png index 22ffe14..bd041dd 100644 Binary files a/domain/src/main/res/drawable/fourcut_frame_dark_25.png and b/domain/src/main/res/drawable/fourcut_frame_dark_25.png differ diff --git a/domain/src/main/res/drawable/maker_faire_frame_25_1.png b/domain/src/main/res/drawable/maker_faire_frame_25_1.png index de94109..5ec82af 100644 Binary files a/domain/src/main/res/drawable/maker_faire_frame_25_1.png and b/domain/src/main/res/drawable/maker_faire_frame_25_1.png differ diff --git a/domain/src/main/res/drawable/maker_faire_frame_25_2.png b/domain/src/main/res/drawable/maker_faire_frame_25_2.png index 675b65f..8f4359e 100644 Binary files a/domain/src/main/res/drawable/maker_faire_frame_25_2.png and b/domain/src/main/res/drawable/maker_faire_frame_25_2.png differ diff --git a/domain/src/main/res/drawable/maker_faire_frame_25_3.png b/domain/src/main/res/drawable/maker_faire_frame_25_3.png index 6a4b59c..3db6ff9 100644 Binary files a/domain/src/main/res/drawable/maker_faire_frame_25_3.png and b/domain/src/main/res/drawable/maker_faire_frame_25_3.png differ diff --git a/domain/src/main/res/drawable/maker_faire_frame_25_4.png b/domain/src/main/res/drawable/maker_faire_frame_25_4.png index 599dc70..7b7af14 100644 Binary files a/domain/src/main/res/drawable/maker_faire_frame_25_4.png and b/domain/src/main/res/drawable/maker_faire_frame_25_4.png differ diff --git a/external/src/main/java/com/foke/together/external/qrcode/QRCodeGenerator.kt b/external/src/main/java/com/foke/together/external/qrcode/QRCodeGenerator.kt index bb4cee3..8dafff7 100644 --- a/external/src/main/java/com/foke/together/external/qrcode/QRCodeGenerator.kt +++ b/external/src/main/java/com/foke/together/external/qrcode/QRCodeGenerator.kt @@ -6,6 +6,7 @@ import com.foke.together.util.AppPolicy import com.foke.together.util.FileUtil import com.foke.together.util.ImageFileUtil import qrcode.QRCode +import qrcode.color.Colors import javax.inject.Inject class QRCodeGenerator @Inject constructor( @@ -18,9 +19,12 @@ class QRCodeGenerator @Inject constructor( // val roundedSquares = QRCode.ofRoundedSquares() val qrcode = squares + .withMargin(20) .withInnerSpacing(0) + // TODO: 아래 속성이 없어서 QR코드가 안보였던건데 그 전에는 왜 제대로 동작했는지? + .withColor(Colors.BLACK) + .withBackgroundColor(Colors.WHITE) // TODO: check customize qrcode -// .withColor(Colors.BLACK) // .withRadius(20) // .withSize(25) // .withLogo(logo.readBytes(), 20, 20) diff --git a/external/src/main/java/com/foke/together/external/repository/SessionRepository.kt b/external/src/main/java/com/foke/together/external/repository/SessionRepository.kt index 12088ec..3b0e6e9 100644 --- a/external/src/main/java/com/foke/together/external/repository/SessionRepository.kt +++ b/external/src/main/java/com/foke/together/external/repository/SessionRepository.kt @@ -1,5 +1,6 @@ package com.foke.together.external.repository +import android.graphics.Bitmap import com.foke.together.domain.interactor.entity.CutFrame import com.foke.together.domain.interactor.entity.SessionData import com.foke.together.domain.interactor.entity.SessionId @@ -33,7 +34,7 @@ class SessionRepository @Inject constructor(): SessionRepositoryInterface { override fun updateSession(cutFrame: CutFrame) { sessionData = sessionData?.let { - SessionData(it.sessionId, cutFrame, it.status) + SessionData(it.sessionId, cutFrame, it.qrCodeBitmap, it.status) } AppLog.i(TAG, "updateSession", "sessionData: $sessionData") @@ -42,7 +43,7 @@ class SessionRepository @Inject constructor(): SessionRepositoryInterface { override fun updateSession(status: Status) { sessionData = sessionData?.let { - SessionData(it.sessionId, it.cutFrame, status) + SessionData(it.sessionId, it.cutFrame, it.qrCodeBitmap, status) } AppLog.i(TAG, "updateSession", "sessionData: $sessionData") @@ -51,7 +52,16 @@ class SessionRepository @Inject constructor(): SessionRepositoryInterface { override fun updateSession(cutFrame: CutFrame, status: Status) { sessionData = sessionData?.let { - SessionData(it.sessionId, cutFrame, status) + SessionData(it.sessionId, cutFrame, it.qrCodeBitmap, status) + } + AppLog.i(TAG, "updateSession", "sessionData: $sessionData") + + // TODO: save session data to Pref. + } + + override fun updateSession(qrCodeBitmap: Bitmap) { + sessionData = sessionData?.let { + SessionData(it.sessionId, it.cutFrame, qrCodeBitmap, it.status) } AppLog.i(TAG, "updateSession", "sessionData: $sessionData") diff --git a/presenter/src/main/java/com/foke/together/presenter/frame/DefaultCutFrame.kt b/presenter/src/main/java/com/foke/together/presenter/frame/DefaultCutFrame.kt index 0103bf8..8c3142d 100644 --- a/presenter/src/main/java/com/foke/together/presenter/frame/DefaultCutFrame.kt +++ b/presenter/src/main/java/com/foke/together/presenter/frame/DefaultCutFrame.kt @@ -14,20 +14,15 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.rotate -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.ImageBitmap +import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.imageResource import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import coil.compose.AsyncImage import coil.request.ImageRequest -import com.foke.together.domain.R import com.foke.together.domain.interactor.entity.DefaultCutFrameSet import com.foke.together.util.TimeUtil @@ -86,48 +81,50 @@ fun DefaultCutFrame( // Copyright Text Sticker Text( modifier = Modifier - .fillMaxSize() + .width(cutFrame.copyrightPosition.width.dp) + .height(cutFrame.copyrightPosition.height.dp) .background(cutFrame.copyrightPosition.backgroundColor) .rotate(cutFrame.copyrightPosition.rotation) .offset(x = cutFrame.copyrightPosition.x.dp, y = cutFrame.copyrightPosition.y.dp), text = stringResource(com.foke.together.presenter.R.string.copyright), color = cutFrame.copyrightPosition.color, fontSize = cutFrame.copyrightPosition.fontSize.sp, - fontWeight = cutFrame.copyrightPosition.fontWeight + fontWeight = cutFrame.copyrightPosition.fontWeight, + textAlign = cutFrame.copyrightPosition.textAlign ) // Date Text Sticker if (cutFrame.isDateString) { Text( modifier = Modifier - .fillMaxSize() + .width(cutFrame.datePosition.width.dp) + .height(cutFrame.datePosition.height.dp) .rotate(cutFrame.datePosition.rotation) .offset(x = cutFrame.datePosition.x.dp, y = cutFrame.datePosition.y.dp), text = TimeUtil.getCurrentDisplayTime(), - color = Color.White, - fontSize = 9.sp, - textAlign = TextAlign.Center, - fontWeight = FontWeight.Bold + color = cutFrame.datePosition.color, + fontSize = cutFrame.datePosition.fontSize.sp, + fontWeight = cutFrame.datePosition.fontWeight, + textAlign = cutFrame.datePosition.textAlign ) } // QR Code Sticker if (cutFrame.isQrCode) { - val qrBitmap = qrImageBitmap ?: ImageBitmap.imageResource(id = R.drawable.qr_sample) - Box( - modifier = Modifier - .width(cutFrame.qrCodePosition.size.dp) - .height(cutFrame.qrCodePosition.size.dp) - .offset(x = cutFrame.qrCodePosition.x.dp, y = cutFrame.qrCodePosition.y.dp), - ) { - AsyncImage( - model = ImageRequest.Builder(LocalContext.current) - .data(qrBitmap) - .build(), - contentDescription = null, - contentScale = ContentScale.Crop, - modifier = Modifier.fillMaxSize() - ) + qrImageBitmap?.let { + Box( + modifier = Modifier + .width(cutFrame.qrCodePosition.size.dp) + .height(cutFrame.qrCodePosition.size.dp) + .offset(x = cutFrame.qrCodePosition.x.dp, y = cutFrame.qrCodePosition.y.dp), + ) { + Image( + bitmap = qrImageBitmap.asImageBitmap(), + contentDescription = null, + contentScale = ContentScale.Crop, + modifier = Modifier.fillMaxSize() + ) + } } } } diff --git a/presenter/src/main/java/com/foke/together/presenter/screen/GenerateImageScreen.kt b/presenter/src/main/java/com/foke/together/presenter/screen/GenerateImageScreen.kt index a16157c..1294a54 100644 --- a/presenter/src/main/java/com/foke/together/presenter/screen/GenerateImageScreen.kt +++ b/presenter/src/main/java/com/foke/together/presenter/screen/GenerateImageScreen.kt @@ -20,10 +20,10 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.drawWithContent +import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.layer.GraphicsLayer import androidx.compose.ui.graphics.layer.drawLayer import androidx.compose.ui.graphics.rememberGraphicsLayer -import androidx.compose.ui.res.colorResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp @@ -32,7 +32,6 @@ import androidx.lifecycle.Lifecycle import androidx.lifecycle.compose.LifecycleEventEffect import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.foke.together.domain.interactor.entity.DefaultCutFrameSet -import com.foke.together.presenter.R import com.foke.together.presenter.component.AppTopBar import com.foke.together.presenter.component.BasicScaffold import com.foke.together.presenter.frame.DefaultCutFrame @@ -40,6 +39,7 @@ import com.foke.together.presenter.theme.AppTheme import com.foke.together.presenter.theme.FourCutTogetherTheme import com.foke.together.presenter.viewmodel.GenerateImageViewModel import com.foke.together.util.AppLog +import com.foke.together.util.AppPolicy import kotlinx.coroutines.delay import kotlinx.coroutines.launch @@ -50,7 +50,7 @@ fun GenerateImageScreen( viewModel: GenerateImageViewModel = hiltViewModel() ) { val TAG = "GenerateImageScreen" - val curFrame = viewModel.cutFrame as DefaultCutFrameSet + val cutFrame = viewModel.cutFrame as DefaultCutFrameSet val graphicsLayer1 = rememberGraphicsLayer() val graphicsLayer2 = rememberGraphicsLayer() val coroutineScope = rememberCoroutineScope() @@ -62,18 +62,21 @@ fun GenerateImageScreen( coroutineScope.launch { isFirstState.value = true delay(200) // !!!!! TODO. timing issue - viewModel.generateImage(graphicsLayer1) + viewModel.generateImageForUpload(graphicsLayer1) + + viewModel.uploadImage() + viewModel.generateQrCode() isFirstState.value = false delay(200) // !!!!! TODO. timing issue - viewModel.generateImageForPrint(graphicsLayer2) + viewModel.generateImage(graphicsLayer2) delay(1000) navigateToShare() } } GenerateImageContent( - cutFrame = curFrame, + cutFrame = cutFrame, imageUri = imageUri, isFirstState = isFirstState.value, graphicsLayer1 = graphicsLayer1, @@ -88,7 +91,8 @@ fun GetDefaultFrame( imageUri: List, graphicsLayer: GraphicsLayer, isForPrint: Boolean = false, - isPaddingHorizontal: Dp = 0.dp + isPaddingHorizontal: Dp = 0.dp, + viewModel: GenerateImageViewModel = hiltViewModel() ) { Column ( modifier = Modifier @@ -99,16 +103,20 @@ fun GetDefaultFrame( drawLayer(graphicsLayer) } ) { - if (isForPrint) { WhiteBox(isPaddingHorizontal) } - Row { - if (isForPrint) { WhiteBox(isPaddingHorizontal) } - DefaultCutFrame(cutFrame, imageUri) - if (isForPrint) { - DefaultCutFrame(cutFrame, imageUri) + if (isForPrint) { + WhiteBox(isPaddingHorizontal) + Row { WhiteBox(isPaddingHorizontal) + DefaultCutFrame(cutFrame, imageUri, viewModel.qrImageBitmap) + DefaultCutFrame(cutFrame, imageUri, viewModel.qrImageBitmap) + WhiteBox(isPaddingHorizontal) + } + WhiteBox(isPaddingHorizontal) + } else { + Row { + DefaultCutFrame(cutFrame, imageUri) } } - if (isForPrint) { WhiteBox(isPaddingHorizontal) } } } @@ -162,7 +170,7 @@ fun GenerateImageContent( imageUri = imageUri, graphicsLayer = graphicsLayer2, isForPrint = isForPrint, - isPaddingHorizontal = 16.dp + isPaddingHorizontal = AppPolicy.PRINT_IMAGE_MARGIN ) } } @@ -177,7 +185,7 @@ private fun WhiteBox( modifier = Modifier .width(size) .height(size) - .background(colorResource(R.color.md_theme_background)) + .background(Color.Transparent) ) } diff --git a/presenter/src/main/java/com/foke/together/presenter/screen/ShareScreen.kt b/presenter/src/main/java/com/foke/together/presenter/screen/ShareScreen.kt index eeb50f6..7583a06 100644 --- a/presenter/src/main/java/com/foke/together/presenter/screen/ShareScreen.kt +++ b/presenter/src/main/java/com/foke/together/presenter/screen/ShareScreen.kt @@ -6,55 +6,38 @@ import android.net.Uri import android.widget.Toast 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.aspectRatio import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Download import androidx.compose.material.icons.filled.Home import androidx.compose.material.icons.filled.Print import androidx.compose.material.icons.filled.Share -import androidx.compose.material.icons.outlined.Download -import androidx.compose.material.icons.outlined.Print -import androidx.compose.material.icons.outlined.Share import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.tooling.preview.Devices import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.constraintlayout.compose.ConstraintLayout -import androidx.constraintlayout.compose.Dimension -import androidx.core.content.FileProvider -import androidx.core.net.toFile -import com.foke.together.presenter.theme.FourCutTogetherTheme +import androidx.core.graphics.createBitmap import androidx.hilt.navigation.compose.hiltViewModel import coil.compose.AsyncImage import coil.request.ImageRequest +import com.foke.together.presenter.component.AppBottomBar import com.foke.together.presenter.component.AppTopBar import com.foke.together.presenter.component.BasicScaffold import com.foke.together.presenter.theme.AppTheme +import com.foke.together.presenter.theme.FourCutTogetherTheme import com.foke.together.presenter.viewmodel.ShareViewModel -import com.foke.together.util.AppLog -import com.foke.together.util.ImageFileUtil -import androidx.core.graphics.createBitmap -import com.foke.together.presenter.component.AppBottomBar @Composable fun ShareScreen( @@ -63,7 +46,7 @@ fun ShareScreen( ) { val context = LocalContext.current val captureImageUri = viewModel.singleImageUri - val qrImageBitmap by viewModel.qrCodeBitmap.collectAsState() + val qrImageBitmap = viewModel.qrCodeBitmap DisposableEffect(Unit) { viewModel.updateSessionStatus() onDispose { } @@ -87,7 +70,7 @@ fun ShareScreen( } }, shareImage = { - viewModel.shareImage() + viewModel.shareImage(context) } ) } @@ -100,7 +83,7 @@ fun ShareContent( popBackStack: () -> Unit, downloadImage: () -> Unit, printImage: () -> Unit, - shareImage: () -> Unit + shareImage: (context: Context) -> Unit ){ BasicScaffold( modifier = Modifier.fillMaxSize(), @@ -164,7 +147,7 @@ fun ShareContent( Column( modifier = Modifier.wrapContentSize() .clickable{ - shareImage() + shareImage(context) }, verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally @@ -193,15 +176,15 @@ fun ShareContent( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceEvenly ){ - // TODO: need check to change single ImageView + // TODO: need to check to change single ImageView AsyncImage( model = ImageRequest.Builder(context) .data(captureImageUri) .build(), contentDescription = "", modifier = Modifier - .aspectRatio(0.4f) - .fillMaxHeight(0.6f) + .aspectRatio(0.7f) + .fillMaxHeight(1.0f) ) AsyncImage( diff --git a/presenter/src/main/java/com/foke/together/presenter/viewmodel/GenerateImageViewModel.kt b/presenter/src/main/java/com/foke/together/presenter/viewmodel/GenerateImageViewModel.kt index e9542f7..c438c0c 100644 --- a/presenter/src/main/java/com/foke/together/presenter/viewmodel/GenerateImageViewModel.kt +++ b/presenter/src/main/java/com/foke/together/presenter/viewmodel/GenerateImageViewModel.kt @@ -1,14 +1,23 @@ package com.foke.together.presenter.viewmodel +import android.graphics.Bitmap +import android.net.Uri import androidx.compose.ui.graphics.layer.GraphicsLayer +import androidx.core.net.toFile import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.foke.together.domain.interactor.GenerateImageFromViewUseCase import com.foke.together.domain.interactor.GeneratePhotoFrameUseCaseV1 import com.foke.together.domain.interactor.GetCameraSourceTypeUseCase +import com.foke.together.domain.interactor.GetQRCodeUseCase import com.foke.together.domain.interactor.entity.CutFrame +import com.foke.together.domain.interactor.entity.Status import com.foke.together.domain.interactor.session.GetCurrentSessionUseCase +import com.foke.together.domain.interactor.session.UpdateSessionStatusUseCase +import com.foke.together.domain.interactor.web.GetDownloadUrlUseCase +import com.foke.together.domain.interactor.web.UploadFileUseCase import com.foke.together.util.AppLog +import com.foke.together.util.AppPolicy import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.map @@ -17,12 +26,22 @@ import javax.inject.Inject @HiltViewModel class GenerateImageViewModel @Inject constructor( - private val getCameraSourceTypeUseCase : GetCameraSourceTypeUseCase, + getCameraSourceTypeUseCase : GetCameraSourceTypeUseCase, private val getCurrentSessionUseCase: GetCurrentSessionUseCase, private val generateImageFromViewUseCase: GenerateImageFromViewUseCase, private val generatePhotoFrameUseCaseV1: GeneratePhotoFrameUseCaseV1, + private val updateSessionStatusUseCase: UpdateSessionStatusUseCase, + private val getQRCodeUseCase: GetQRCodeUseCase, + private val getDownloadUrlUseCase: GetDownloadUrlUseCase, + private val uploadFileUseCase: UploadFileUseCase, ): ViewModel() { - val cutFrame: CutFrame = getCurrentSessionUseCase()?.cutFrame ?: run { throw Exception("invalid cut frame") } + + init { + updateSessionStatusUseCase(Status.GENERATE_PHOTO) + } + + var cutFrame: CutFrame = getCurrentSessionUseCase()?.cutFrame ?: run { throw Exception("invalid cut frame") } + var qrImageBitmap: Bitmap? = null val imageUri = getCameraSourceTypeUseCase().map{ sourceType -> generatePhotoFrameUseCaseV1.getCapturedImageListUri(sourceType) @@ -32,14 +51,40 @@ class GenerateImageViewModel @Inject constructor( initialValue = listOf() ) + suspend fun generateImageForUpload(graphicsLayer: GraphicsLayer) { + generateImageFromViewUseCase(graphicsLayer, isCutFrameForPrint = false) + } + suspend fun generateImage(graphicsLayer: GraphicsLayer) { val finalCachedImageUri = generateImageFromViewUseCase(graphicsLayer, isCutFrameForPrint = false) + val finalExternalImageUri = generateImageFromViewUseCase(graphicsLayer, isCutFrameForPrint = true) AppLog.d(TAG, "generateImage" ,"finalCachedImageUri: $finalCachedImageUri") + AppLog.d(TAG, "generateImageForPrint" ,"finalExternalImageUri: $finalExternalImageUri") } - suspend fun generateImageForPrint(graphicsLayer: GraphicsLayer) { - val finalExternalImageUri = generateImageFromViewUseCase(graphicsLayer, isCutFrameForPrint = true) - AppLog.d(TAG, "generateImageForPrint" ,"finalExternalImageUri: $finalExternalImageUri") + suspend fun generateQrCode() { + getCurrentSessionUseCase()?.let { session -> + val sessionKey = session.sessionId.toString() + val downloadUrl: String = getDownloadUrlUseCase(sessionKey).getOrElse { AppPolicy.WEB_SERVER_URL } + getQRCodeUseCase(sessionKey, downloadUrl).getOrNull()?.let { + updateSessionStatusUseCase(it) + qrImageBitmap = it + } + if (AppPolicy.isDebugMode) { + AppLog.e(TAG, "generateQrCode", "sessionKey: $sessionKey") + AppLog.e(TAG, "generateQrCode", "downloadUrl: $downloadUrl") + } + } + } + + suspend fun uploadImage() { + getCurrentSessionUseCase()?.let { session -> + val sessionKey = session.sessionId.toString() + + val singleImageUri: Uri = generatePhotoFrameUseCaseV1.getFinalSingleImageUri() + val result = uploadFileUseCase(sessionKey, singleImageUri.toFile()) + AppLog.d(TAG, "generateQrCode" ,"result: $result") + } } companion object { diff --git a/presenter/src/main/java/com/foke/together/presenter/viewmodel/HomeViewModel.kt b/presenter/src/main/java/com/foke/together/presenter/viewmodel/HomeViewModel.kt index 5bb70bc..734f756 100644 --- a/presenter/src/main/java/com/foke/together/presenter/viewmodel/HomeViewModel.kt +++ b/presenter/src/main/java/com/foke/together/presenter/viewmodel/HomeViewModel.kt @@ -5,6 +5,7 @@ import androidx.lifecycle.viewModelScope import com.foke.together.domain.interactor.AppInitUseCase import com.foke.together.domain.interactor.session.CreateNewSessionUseCase import com.foke.together.domain.interactor.web.GetCurrentUserInformationUseCase +import com.foke.together.domain.interactor.web.RegisterUseCase import com.foke.together.domain.interactor.web.SignInUseCase import com.foke.together.util.AppLog import com.foke.together.util.di.IODispatcher @@ -17,6 +18,7 @@ import javax.inject.Inject class HomeViewModel @Inject constructor( @IODispatcher private val ioDispatcher: CoroutineDispatcher, private val signInUseCase: SignInUseCase, + private val registerUseCase: RegisterUseCase, private val getCurrentUserInformationUseCase: GetCurrentUserInformationUseCase, private val appInitUseCase: AppInitUseCase, private val createNewSessionUseCase: CreateNewSessionUseCase @@ -25,11 +27,18 @@ class HomeViewModel @Inject constructor( viewModelScope.launch(ioDispatcher) { // init external camera ip address appInitUseCase() - // TODO: this is test code. remove later + + // TODO: add register function in Settings +// registerUseCase( +// "maker-faire-2025@test.com", +// "1234", +// "maker-faire-2025" +// ) + signInUseCase( - "test@test.com", - "1234" + "maker-faire-2025@test.com", + "1234", ) // TODO: this is test code. remove later getCurrentUserInformationUseCase() diff --git a/presenter/src/main/java/com/foke/together/presenter/viewmodel/InternelCameraViewModel.kt b/presenter/src/main/java/com/foke/together/presenter/viewmodel/InternelCameraViewModel.kt index f130b66..6f86c86 100644 --- a/presenter/src/main/java/com/foke/together/presenter/viewmodel/InternelCameraViewModel.kt +++ b/presenter/src/main/java/com/foke/together/presenter/viewmodel/InternelCameraViewModel.kt @@ -1,20 +1,15 @@ package com.foke.together.presenter.viewmodel import android.content.Context -import android.net.Uri import android.os.CountDownTimer import androidx.camera.core.CameraSelector import androidx.camera.core.ImageCapture import androidx.camera.view.PreviewView -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableFloatStateOf -import androidx.compose.runtime.mutableIntStateOf -import androidx.compose.runtime.setValue import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.foke.together.domain.interactor.GetCaptureDurationUseCase import com.foke.together.domain.interactor.GeneratePhotoFrameUseCaseV1 +import com.foke.together.domain.interactor.GetCaptureDurationUseCase import com.foke.together.domain.interactor.GetCapturedImageUriUseCase import com.foke.together.domain.interactor.GetInternalCameraCaptureModeUseCase import com.foke.together.domain.interactor.GetInternalCameraFlashModeUseCase @@ -24,31 +19,28 @@ import com.foke.together.domain.interactor.session.GetCurrentSessionUseCase import com.foke.together.presenter.screen.state.InternalCameraState import com.foke.together.util.AppLog import com.foke.together.util.AppPolicy -import com.foke.together.util.AppPolicy.CAPTURE_INTERVAL -import com.foke.together.util.AppPolicy.COUNTDOWN_INTERVAL import com.foke.together.util.SoundUtil import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch -import kotlinx.coroutines.delay import javax.inject.Inject import kotlin.time.Duration.Companion.seconds import kotlin.time.DurationUnit -import kotlin.time.toDuration @HiltViewModel class InternelCameraViewModel @Inject constructor( private val internalCameraUseCase: InternalCameraUseCase, - private val getCaptureDurationUseCase: GetCaptureDurationUseCase, - private val getInternalCameraLensFacingUseCase: GetInternalCameraLensFacingUseCase, - private val getInternalCameraFlashModeUseCase: GetInternalCameraFlashModeUseCase, - private val getInternalCameraCaptureModeUseCase: GetInternalCameraCaptureModeUseCase, - private val getCapturedImageUriUseCase: GetCapturedImageUriUseCase, - private val getSessionUseCase : GetCurrentSessionUseCase, private val generatePhotoFrameUseCaseV1: GeneratePhotoFrameUseCaseV1, + getCaptureDurationUseCase: GetCaptureDurationUseCase, + getInternalCameraLensFacingUseCase: GetInternalCameraLensFacingUseCase, + getInternalCameraFlashModeUseCase: GetInternalCameraFlashModeUseCase, + getInternalCameraCaptureModeUseCase: GetInternalCameraCaptureModeUseCase, + getCapturedImageUriUseCase: GetCapturedImageUriUseCase, + getSessionUseCase : GetCurrentSessionUseCase, ): ViewModel() { // TODO(MutableStateFlow 로 처리하기) @@ -147,7 +139,7 @@ class InternelCameraViewModel @Inject constructor( generatePhotoFrameUseCaseV1.clearCapturedImageList() } - captureTimer = object : CountDownTimer(captureDuration.value.toLong(DurationUnit.MILLISECONDS), COUNTDOWN_INTERVAL) { + captureTimer = object : CountDownTimer(captureDuration.value.toLong(DurationUnit.MILLISECONDS), AppPolicy.COUNTDOWN_INTERVAL) { override fun onTick(millisUntilFinished: Long) { countdownSeconds.value = ((millisUntilFinished / 1000) + 1).toInt() } @@ -161,14 +153,13 @@ class InternelCameraViewModel @Inject constructor( if (captureCount.value < AppPolicy.CAPTURE_COUNT) { AppLog.d(TAG, "captureCount", "${captureCount.value}") - // 촬영 후 2초 대기 - delay(5.seconds.toLong(DurationUnit.MILLISECONDS)) + delay(AppPolicy.PREVIEW_INTERVAL.seconds.toLong(DurationUnit.MILLISECONDS)) captureCount.value += 1 start() } else { AppLog.d(TAG, "captureCount", "${captureCount.value}") stopCaptureTimer() - delay(5.seconds.toLong(DurationUnit.MILLISECONDS)) + delay(AppPolicy.PREVIEW_INTERVAL.seconds.toLong(DurationUnit.MILLISECONDS)) captureCount.value = 1 nextNavigate() } diff --git a/presenter/src/main/java/com/foke/together/presenter/viewmodel/SelectFrameViewModel.kt b/presenter/src/main/java/com/foke/together/presenter/viewmodel/SelectFrameViewModel.kt index 2d494ff..06266f8 100644 --- a/presenter/src/main/java/com/foke/together/presenter/viewmodel/SelectFrameViewModel.kt +++ b/presenter/src/main/java/com/foke/together/presenter/viewmodel/SelectFrameViewModel.kt @@ -17,14 +17,21 @@ class SelectFrameViewModel @Inject constructor( private val updateSessionStatusUseCase: UpdateSessionStatusUseCase ): ViewModel() { - val isDateDisplay = MutableStateFlow(false) - val isQRDisplay = MutableStateFlow(false) + val isDateDisplay = MutableStateFlow(true) + val isQRDisplay = MutableStateFlow(true) val cutFrames = MutableStateFlow>(emptyList()) fun updateSessionStatus() { updateSessionStatusUseCase(Status.SELECT_FRAME) - cutFrames.value = DefaultCutFrameSet.entries + // TODO: 윤수야 여기 내가 하드코딩 했어 + cutFrames.value = DefaultCutFrameSet.entries.map { cutFrame -> + cutFrame.isDateString = isDateDisplay.value + cutFrame.isQrCode = isQRDisplay.value + AppLog.d(TAG, "updateDateDisplay", "isDateString : ${cutFrame.isDateString}") + AppLog.d(TAG, "updateDateDisplay", "isQrCode : ${cutFrame.isQrCode}") + cutFrame + } } fun updateDateDisplay(state: Boolean) = viewModelScope.launch{ @@ -32,6 +39,7 @@ class SelectFrameViewModel @Inject constructor( cutFrames.value = DefaultCutFrameSet.entries.map { cutFrame -> cutFrame.isDateString = state AppLog.d(TAG, "updateDateDisplay", "isDateString : ${cutFrame.isDateString}") + AppLog.d(TAG, "updateDateDisplay", "isQrCode : ${cutFrame.isQrCode}") cutFrame } } diff --git a/presenter/src/main/java/com/foke/together/presenter/viewmodel/ShareViewModel.kt b/presenter/src/main/java/com/foke/together/presenter/viewmodel/ShareViewModel.kt index 5ca5dd2..d1d0dc0 100644 --- a/presenter/src/main/java/com/foke/together/presenter/viewmodel/ShareViewModel.kt +++ b/presenter/src/main/java/com/foke/together/presenter/viewmodel/ShareViewModel.kt @@ -1,53 +1,34 @@ package com.foke.together.presenter.viewmodel import android.content.Context -import android.graphics.Bitmap import android.net.Uri -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.setValue import androidx.core.content.FileProvider import androidx.core.net.toFile import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.foke.together.domain.interactor.GeneratePhotoFrameUseCaseV1 -import com.foke.together.domain.interactor.GetQRCodeUseCase import com.foke.together.domain.interactor.entity.Status import com.foke.together.domain.interactor.session.ClearSessionUseCase import com.foke.together.domain.interactor.session.GetCurrentSessionUseCase import com.foke.together.domain.interactor.session.UpdateSessionStatusUseCase -import com.foke.together.domain.interactor.web.GetDownloadUrlUseCase -import com.foke.together.domain.interactor.web.UploadFileUseCase -import com.foke.together.util.AppLog -import com.foke.together.util.AppPolicy import com.foke.together.util.ImageFileUtil import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.qualifiers.ApplicationContext -import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel class ShareViewModel @Inject constructor( @ApplicationContext private val context: Context, - private val getQRCodeUseCase: GetQRCodeUseCase, - private val getDownloadUrlUseCase: GetDownloadUrlUseCase, - private val uploadFileUseCase: UploadFileUseCase, - private val generatePhotoFrameUseCaseV1: GeneratePhotoFrameUseCaseV1, private val getCurrentSessionUseCase: GetCurrentSessionUseCase, private val updateSessionStatusUseCase: UpdateSessionStatusUseCase, - private val clearSessionUseCase: ClearSessionUseCase + private val clearSessionUseCase: ClearSessionUseCase, + generatePhotoFrameUseCaseV1: GeneratePhotoFrameUseCaseV1 ): ViewModel() { - val qrCodeBitmap = MutableStateFlow(null) + val qrCodeBitmap = getCurrentSessionUseCase()?.qrCodeBitmap val singleImageUri: Uri = generatePhotoFrameUseCaseV1.getFinalSingleImageUri() val twoImageUri: Uri = generatePhotoFrameUseCaseV1.getFinalTwoImageUri() - init { - viewModelScope.launch { - generateQRcode() - } - } - fun downloadImage(): Result { return getCurrentSessionUseCase()?.let { session -> val imageBitmap = ImageFileUtil.getBitmapFromUri(context, singleImageUri) @@ -64,23 +45,7 @@ class ShareViewModel @Inject constructor( } } - private suspend fun generateQRcode() { - getCurrentSessionUseCase()?.let { session -> - val sessionKey = session.sessionId.toString() - - val result = uploadFileUseCase(sessionKey, singleImageUri.toFile()) - AppLog.d(TAG, "generateQRcode" ,"result: $result") - - val downloadUrl: String = getDownloadUrlUseCase(sessionKey).getOrElse { "https://foke.clon.dev" } - if (AppPolicy.isDebugMode) { - AppLog.e(TAG, "generateQRcode", "sessionKey: $sessionKey") - AppLog.e(TAG, "generateQRcode", "downloadUrl: $downloadUrl") - } - qrCodeBitmap.value = getQRCodeUseCase(sessionKey, downloadUrl).getOrNull() - } - } - - fun shareImage() { + fun shareImage(context: Context) { val contentUri = FileProvider.getUriForFile( context, "com.foke.together.fileprovider", diff --git a/util/src/main/java/com/foke/together/util/AppPolicy.kt b/util/src/main/java/com/foke/together/util/AppPolicy.kt index fbf9f03..1aa8c0c 100644 --- a/util/src/main/java/com/foke/together/util/AppPolicy.kt +++ b/util/src/main/java/com/foke/together/util/AppPolicy.kt @@ -1,5 +1,6 @@ package com.foke.together.util +import androidx.compose.ui.unit.dp import kotlin.time.Duration.Companion.seconds object AppPolicy { @@ -7,10 +8,10 @@ object AppPolicy { const val isNoCameraDebugMode = false // TODO: change to false // network - const val WEB_SERVER_URL = "https://4cuts.store/" - const val WEB_CONNECT_TIMEOUT = 10L - const val WEB_READ_TIMEOUT = 10L - const val WEB_WRITE_TIMEOUT = 10L + const val WEB_SERVER_URL = "https://4cut.us/" + const val WEB_CONNECT_TIMEOUT = 20L + const val WEB_READ_TIMEOUT = 20L + const val WEB_WRITE_TIMEOUT = 20L const val WEB_FILE_MAX_CONTENT_LENGTH = 20971520 const val EXTERNAL_CAMERA_DEFAULT_SERVER_URL = "http://0.0.0.0" @@ -19,9 +20,11 @@ object AppPolicy { const val EXTERNAL_CAMERA_WRITE_TIMEOUT = 10L // capture settings - val CAPTURE_INTERVAL = 10.seconds + val CAPTURE_INTERVAL = 7.seconds const val CAPTURE_COUNT = 4 const val COUNTDOWN_INTERVAL = 10L + const val PREVIEW_INTERVAL = 5L + val PRINT_IMAGE_MARGIN = 15.dp // file settings const val CAPTURED_FOUR_CUT_IMAGE_NAME = "capture"