From 38a5869fafed73dbd588f03013b8fed8b20b2441 Mon Sep 17 00:00:00 2001 From: DongHyeon Park Date: Sun, 2 Jul 2023 22:12:02 +0900 Subject: [PATCH 1/6] =?UTF-8?q?issue=20#161=20chore:=20LottieCompose=20?= =?UTF-8?q?=EB=B0=8F=20Text=ED=9A=A8=EA=B3=BC=20import?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/build.gradle b/app/build.gradle index 81103d2..ba1502c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -57,6 +57,7 @@ dependencies { def pagingVersion = "3.1.1" def glide_version = "4.14.2" def glide_compose_version = "1.0.0-alpha.1" + def lottieComposeVersion = "6.0.0" // Compose def composeBom = platform('androidx.compose:compose-bom:2023.04.01') @@ -76,6 +77,8 @@ dependencies { implementation 'androidx.compose.runtime:runtime-livedata' // collectAsStateWithLifecycle() implementation "androidx.lifecycle:lifecycle-runtime-compose:2.6.1" + // Compose Text Effect + implementation "me.saket.extendedspans:extendedspans:1.3.0" // Navigation implementation "androidx.navigation:navigation-fragment-ktx:$nav_version" @@ -117,6 +120,7 @@ dependencies { implementation 'com.arthenica:mobile-ffmpeg-min-gpl:4.4' // lottie implementation 'com.airbnb.android:lottie:5.0.2' + implementation "com.airbnb.android:lottie-compose:$lottieComposeVersion" // dataStore implementation("androidx.datastore:datastore-preferences:1.0.0") implementation("androidx.datastore:datastore-core:1.0.0") From f20bc8c8ee7f2f836207ba835b0df12e1361858b Mon Sep 17 00:00:00 2001 From: DongHyeon Park Date: Sun, 2 Jul 2023 22:13:37 +0900 Subject: [PATCH 2/6] =?UTF-8?q?issue=20#161=20feat:=20primaryVariant=20?= =?UTF-8?q?=EC=83=89=EC=83=81=20=EB=B3=80=EA=B2=BD=20(primary=EC=99=80=20?= =?UTF-8?q?=EC=9C=A0=EC=82=AC=ED=95=9C=20=EC=83=89=EC=9C=BC=EB=A1=9C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/boostcamp/dailyfilm/presentation/ui/theme/Color.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/boostcamp/dailyfilm/presentation/ui/theme/Color.kt b/app/src/main/java/com/boostcamp/dailyfilm/presentation/ui/theme/Color.kt index b7fa5e6..62ddebb 100644 --- a/app/src/main/java/com/boostcamp/dailyfilm/presentation/ui/theme/Color.kt +++ b/app/src/main/java/com/boostcamp/dailyfilm/presentation/ui/theme/Color.kt @@ -9,7 +9,7 @@ val lightBlack = Color(0xFF202022) val lightGray = Color(0xFFE1E1E1) val primary = lightBlack -val primaryVariant = white +val primaryVariant = blackBlur val background = white val surface = white val error = Color(0xFFB00020) From 7bbfc04174e53b47d2a03bcab5135b8dd59a974b Mon Sep 17 00:00:00 2001 From: DongHyeon Park Date: Sun, 2 Jul 2023 22:19:23 +0900 Subject: [PATCH 3/6] =?UTF-8?q?issue=20#161=20chore:=20=EC=9D=8C=EC=86=8C?= =?UTF-8?q?=EA=B1=B0Lottie=20Raw=ED=8F=B4=EB=8D=94=EC=97=90=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/res/raw/lottie_sound.json | 3464 ++++++++++++++++++++++++ 1 file changed, 3464 insertions(+) create mode 100644 app/src/main/res/raw/lottie_sound.json diff --git a/app/src/main/res/raw/lottie_sound.json b/app/src/main/res/raw/lottie_sound.json new file mode 100644 index 0000000..069506a --- /dev/null +++ b/app/src/main/res/raw/lottie_sound.json @@ -0,0 +1,3464 @@ +{ + "v": "5.1.18", + "fr": 29.9700012207031, + "ip": 0, + "op": 90.0000036657751, + "w": 20, + "h": 20, + "nm": "Mute", + "ddd": 0, + "assets": [], + "layers": [ + { + "ddd": 0, + "ind": 1, + "ty": 4, + "nm": "mask_wave_2", + "td": 1, + "sr": 1, + "ks": { + "o": { + "a": 0, + "k": 100, + "ix": 11 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "p": { + "a": 0, + "k": [ + 10, + 10, + 0 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100, + 100 + ], + "ix": 6 + } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ty": "rc", + "d": 1, + "s": { + "a": 0, + "k": [ + 9.938, + 18.313 + ], + "ix": 2 + }, + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 4 + }, + "nm": "Rectangle Path 1", + "mn": "ADBE Vector Shape - Rect", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0, + 0, + 0, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + -5.281, + 0.031 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Rectangle 1", + "np": 3, + "cix": 2, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + } + ], + "ip": 0, + "op": 91.000003706506, + "st": 0, + "bm": 0 + }, + { + "ddd": 0, + "ind": 2, + "ty": 4, + "nm": "wave_2 Outlines", + "tt": 2, + "sr": 1, + "ks": { + "o": { + "a": 0, + "k": 100, + "ix": 11 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "p": { + "a": 1, + "k": [ + { + "i": { + "x": 0.833, + "y": 0.833 + }, + "o": { + "x": 0.167, + "y": 0.167 + }, + "n": "0p833_0p833_0p167_0p167", + "t": 2, + "s": [ + 18.306, + 9.963, + 0 + ], + "e": [ + 18.118, + 9.963, + 0 + ], + "to": [ + -0.03125, + 0, + 0 + ], + "ti": [ + 1.67708337306976, + 0, + 0 + ] + }, + { + "i": { + "x": 0.833, + "y": 0.931 + }, + "o": { + "x": 0.167, + "y": 0.167 + }, + "n": "0p833_0p931_0p167_0p167", + "t": 6, + "s": [ + 18.118, + 9.963, + 0 + ], + "e": [ + 8.243, + 9.963, + 0 + ], + "to": [ + -1.67708337306976, + 0, + 0 + ], + "ti": [ + 1.64583337306976, + 0, + 0 + ] + }, + { + "i": { + "x": 0.833, + "y": 0.833 + }, + "o": { + "x": 0.167, + "y": 0.167 + }, + "n": "0p833_0p833_0p167_0p167", + "t": 11, + "s": [ + 8.243, + 9.963, + 0 + ], + "e": [ + 8.243, + 9.963, + 0 + ], + "to": [ + 0, + 0, + 0 + ], + "ti": [ + 0, + 0, + 0 + ] + }, + { + "i": { + "x": 0.833, + "y": 0.833 + }, + "o": { + "x": 0.167, + "y": 0.069 + }, + "n": "0p833_0p833_0p167_0p069", + "t": 75, + "s": [ + 8.243, + 9.963, + 0 + ], + "e": [ + 18.118, + 9.963, + 0 + ], + "to": [ + 1.64583337306976, + 0, + 0 + ], + "ti": [ + -1.67708337306976, + 0, + 0 + ] + }, + { + "i": { + "x": 0.833, + "y": 0.833 + }, + "o": { + "x": 0.167, + "y": 0.167 + }, + "n": "0p833_0p833_0p167_0p167", + "t": 80, + "s": [ + 18.118, + 9.963, + 0 + ], + "e": [ + 18.306, + 9.963, + 0 + ], + "to": [ + 1.67708337306976, + 0, + 0 + ], + "ti": [ + -0.03125, + 0, + 0 + ] + }, + { + "t": 84.0000034213901 + } + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 2.827, + 7.401, + 0 + ], + "ix": 1 + }, + "s": { + "a": 1, + "k": [ + { + "i": { + "x": [ + 0.833, + 0.833, + 0.833 + ], + "y": [ + 0.931, + 0.931, + 1.151 + ] + }, + "o": { + "x": [ + 0.167, + 0.167, + 0.167 + ], + "y": [ + 0.069, + 0.069, + -0.151 + ] + }, + "n": [ + "0p833_0p931_0p167_0p069", + "0p833_0p931_0p167_0p069", + "0p833_1p151_0p167_-0p151" + ], + "t": 6, + "s": [ + 100, + 100, + 100 + ], + "e": [ + 44.871, + 44.871, + 100 + ] + }, + { + "i": { + "x": [ + 0.833, + 0.833, + 0.833 + ], + "y": [ + 1, + 1, + 1 + ] + }, + "o": { + "x": [ + 0.167, + 0.167, + 0.167 + ], + "y": [ + -49.003, + -49.003, + -1.938 + ] + }, + "n": [ + "0p833_1_0p167_-49p003", + "0p833_1_0p167_-49p003", + "0p833_1_0p167_-1p938" + ], + "t": 11, + "s": [ + 44.871, + 44.871, + 100 + ], + "e": [ + 44.871, + 44.871, + 100 + ] + }, + { + "i": { + "x": [ + 0.833, + 0.833, + 0.833 + ], + "y": [ + 1, + 1, + 1 + ] + }, + "o": { + "x": [ + 0.167, + 0.167, + 0.167 + ], + "y": [ + 0, + 0, + 0 + ] + }, + "n": [ + "0p833_1_0p167_0", + "0p833_1_0p167_0", + "0p833_1_0p167_0" + ], + "t": 75, + "s": [ + 44.871, + 44.871, + 100 + ], + "e": [ + 100, + 100, + 100 + ] + }, + { + "t": 80.0000032584668 + } + ], + "ix": 6 + } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 0.192, + 0 + ], + [ + 0.146, + 0.147 + ], + [ + -0.293, + 0.293 + ], + [ + 3.217, + 3.217 + ], + [ + -0.293, + 0.293 + ], + [ + -0.293, + -0.293 + ], + [ + 3.801, + -3.801 + ] + ], + "o": [ + [ + -0.192, + 0 + ], + [ + -0.293, + -0.293 + ], + [ + 3.217, + -3.217 + ], + [ + -0.293, + -0.293 + ], + [ + 0.293, + -0.293 + ], + [ + 3.801, + 3.802 + ], + [ + -0.146, + 0.147 + ] + ], + "v": [ + [ + -1.406, + 7.151 + ], + [ + -1.936, + 6.931 + ], + [ + -1.936, + 5.871 + ], + [ + -1.936, + -5.797 + ], + [ + -1.936, + -6.858 + ], + [ + -0.876, + -6.858 + ], + [ + -0.876, + 6.931 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "mm", + "mm": 4, + "nm": "Merge Paths 1", + "mn": "ADBE Vector Filter - Merge", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 1, + 1, + 1, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 2.479, + 7.401 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 1", + "np": 3, + "cix": 2, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + } + ], + "ip": 0, + "op": 91.000003706506, + "st": 0, + "bm": 0 + }, + { + "ddd": 0, + "ind": 3, + "ty": 4, + "nm": "mask_wave", + "td": 1, + "sr": 1, + "ks": { + "o": { + "a": 0, + "k": 100, + "ix": 11 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "p": { + "a": 0, + "k": [ + 10, + 10, + 0 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100, + 100 + ], + "ix": 6 + } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ty": "rc", + "d": 1, + "s": { + "a": 0, + "k": [ + 9.938, + 18.313 + ], + "ix": 2 + }, + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 4 + }, + "nm": "Rectangle Path 1", + "mn": "ADBE Vector Shape - Rect", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0, + 0, + 0, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + -5.281, + 0.031 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Rectangle 1", + "np": 3, + "cix": 2, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + } + ], + "ip": 0, + "op": 91.000003706506, + "st": 0, + "bm": 0 + }, + { + "ddd": 0, + "ind": 4, + "ty": 4, + "nm": "wave_1 Outlines", + "tt": 2, + "sr": 1, + "ks": { + "o": { + "a": 0, + "k": 100, + "ix": 11 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "p": { + "a": 1, + "k": [ + { + "i": { + "x": 0.833, + "y": 0.975 + }, + "o": { + "x": 0.333, + "y": 0.052 + }, + "n": "0p833_0p975_0p333_0p052", + "t": 0, + "s": [ + 14.063, + 9.959, + 0 + ], + "e": [ + 14.813, + 9.959, + 0 + ], + "to": [ + 0.125, + 0, + 0 + ], + "ti": [ + 1.52083337306976, + 0, + 0 + ] + }, + { + "i": { + "x": 0.667, + "y": 1 + }, + "o": { + "x": 0.333, + "y": 0 + }, + "n": "0p667_1_0p333_0", + "t": 4, + "s": [ + 14.813, + 9.959, + 0 + ], + "e": [ + 4.938, + 9.959, + 0 + ], + "to": [ + -1.52083337306976, + 0, + 0 + ], + "ti": [ + 1.64583337306976, + 0, + 0 + ] + }, + { + "i": { + "x": 0.667, + "y": 0.667 + }, + "o": { + "x": 0.167, + "y": 0.167 + }, + "n": "0p667_0p667_0p167_0p167", + "t": 11, + "s": [ + 4.938, + 9.959, + 0 + ], + "e": [ + 4.938, + 9.959, + 0 + ], + "to": [ + 0, + 0, + 0 + ], + "ti": [ + 0, + 0, + 0 + ] + }, + { + "i": { + "x": 0.833, + "y": 0.992 + }, + "o": { + "x": 0.167, + "y": 0.008 + }, + "n": "0p833_0p992_0p167_0p008", + "t": 75, + "s": [ + 4.938, + 9.959, + 0 + ], + "e": [ + 14.813, + 9.959, + 0 + ], + "to": [ + 1.64583337306976, + 0, + 0 + ], + "ti": [ + -1.52083337306976, + 0, + 0 + ] + }, + { + "i": { + "x": 0.833, + "y": 0.833 + }, + "o": { + "x": 0.333, + "y": 0 + }, + "n": "0p833_0p833_0p333_0", + "t": 82, + "s": [ + 14.813, + 9.959, + 0 + ], + "e": [ + 14.063, + 9.959, + 0 + ], + "to": [ + 1.52083337306976, + 0, + 0 + ], + "ti": [ + 0.125, + 0, + 0 + ] + }, + { + "t": 86.0000035028518 + } + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 1.95, + 4.218, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100, + 100 + ], + "ix": 6 + } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 0.192, + 0 + ], + [ + 0.146, + 0.147 + ], + [ + -0.293, + 0.293 + ], + [ + 1.462, + 1.462 + ], + [ + -0.293, + 0.293 + ], + [ + -0.293, + -0.292 + ], + [ + 2.046, + -2.048 + ] + ], + "o": [ + [ + -0.191, + 0 + ], + [ + -0.293, + -0.292 + ], + [ + 1.462, + -1.462 + ], + [ + -0.293, + -0.293 + ], + [ + 0.293, + -0.292 + ], + [ + 2.046, + 2.047 + ], + [ + -0.146, + 0.147 + ] + ], + "v": [ + [ + -0.876, + 3.969 + ], + [ + -1.406, + 3.749 + ], + [ + -1.406, + 2.689 + ], + [ + -1.406, + -2.615 + ], + [ + -1.406, + -3.676 + ], + [ + -0.346, + -3.676 + ], + [ + -0.346, + 3.749 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 1, + 1, + 1, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 1.95, + 4.218 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 1", + "np": 2, + "cix": 2, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + } + ], + "ip": 0, + "op": 91.000003706506, + "st": 0, + "bm": 0 + }, + { + "ddd": 0, + "ind": 5, + "ty": 4, + "nm": "bar Outlines", + "sr": 1, + "ks": { + "o": { + "a": 0, + "k": 100, + "ix": 11 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "p": { + "a": 0, + "k": [ + 10.5, + 9.463, + 0 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 6.475, + 6.439, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100, + 100 + ], + "ix": 6 + } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 1, + "k": [ + { + "i": { + "x": 0.667, + "y": 1 + }, + "o": { + "x": 0.167, + "y": 0.167 + }, + "n": "0p667_1_0p167_0p167", + "t": 19, + "s": [ + { + "i": [ + [ + 0.192, + 0 + ], + [ + 0.146, + 0.147 + ], + [ + 0, + 0 + ], + [ + -0.293, + 0.293 + ], + [ + -0.293, + -0.293 + ], + [ + 0, + 0 + ], + [ + 0.293, + -0.293 + ] + ], + "o": [ + [ + -0.192, + 0 + ], + [ + 0, + 0 + ], + [ + -0.293, + -0.293 + ], + [ + 0.293, + -0.293 + ], + [ + 0, + 0 + ], + [ + 0.293, + 0.293 + ], + [ + -0.146, + 0.147 + ] + ], + "v": [ + [ + -5.569, + -4.777 + ], + [ + -6.099, + -4.996 + ], + [ + -5.932, + -4.836 + ], + [ + -5.932, + -5.896 + ], + [ + -4.872, + -5.896 + ], + [ + -5.039, + -6.056 + ], + [ + -5.039, + -4.996 + ] + ], + "c": true + } + ], + "e": [ + { + "i": [ + [ + 0.192, + 0 + ], + [ + 0.146, + 0.147 + ], + [ + 0, + 0 + ], + [ + -0.293, + 0.293 + ], + [ + -0.293, + -0.293 + ], + [ + 0, + 0 + ], + [ + 0.293, + -0.293 + ] + ], + "o": [ + [ + -0.192, + 0 + ], + [ + 0, + 0 + ], + [ + -0.293, + -0.293 + ], + [ + 0.293, + -0.293 + ], + [ + 0, + 0 + ], + [ + 0.293, + 0.293 + ], + [ + -0.146, + 0.147 + ] + ], + "v": [ + [ + 5.402, + 6.189 + ], + [ + 4.872, + 5.97 + ], + [ + -5.932, + -4.836 + ], + [ + -5.932, + -5.896 + ], + [ + -4.872, + -5.896 + ], + [ + 5.932, + 4.91 + ], + [ + 5.932, + 5.97 + ] + ], + "c": true + } + ] + }, + { + "i": { + "x": 0.667, + "y": 1 + }, + "o": { + "x": 0.167, + "y": 0.167 + }, + "n": "0p667_1_0p167_0p167", + "t": 25, + "s": [ + { + "i": [ + [ + 0.192, + 0 + ], + [ + 0.146, + 0.147 + ], + [ + 0, + 0 + ], + [ + -0.293, + 0.293 + ], + [ + -0.293, + -0.293 + ], + [ + 0, + 0 + ], + [ + 0.293, + -0.293 + ] + ], + "o": [ + [ + -0.192, + 0 + ], + [ + 0, + 0 + ], + [ + -0.293, + -0.293 + ], + [ + 0.293, + -0.293 + ], + [ + 0, + 0 + ], + [ + 0.293, + 0.293 + ], + [ + -0.146, + 0.147 + ] + ], + "v": [ + [ + 5.402, + 6.189 + ], + [ + 4.872, + 5.97 + ], + [ + -5.932, + -4.836 + ], + [ + -5.932, + -5.896 + ], + [ + -4.872, + -5.896 + ], + [ + 5.932, + 4.91 + ], + [ + 5.932, + 5.97 + ] + ], + "c": true + } + ], + "e": [ + { + "i": [ + [ + 0.192, + 0 + ], + [ + 0.146, + 0.147 + ], + [ + 0, + 0 + ], + [ + -0.293, + 0.293 + ], + [ + -0.293, + -0.293 + ], + [ + 0, + 0 + ], + [ + 0.293, + -0.293 + ] + ], + "o": [ + [ + -0.192, + 0 + ], + [ + 0, + 0 + ], + [ + -0.293, + -0.293 + ], + [ + 0.293, + -0.293 + ], + [ + 0, + 0 + ], + [ + 0.293, + 0.293 + ], + [ + -0.146, + 0.147 + ] + ], + "v": [ + [ + 5.402, + 6.189 + ], + [ + 4.872, + 5.97 + ], + [ + -5.932, + -4.836 + ], + [ + -5.932, + -5.896 + ], + [ + -4.872, + -5.896 + ], + [ + 5.932, + 4.91 + ], + [ + 5.932, + 5.97 + ] + ], + "c": true + } + ] + }, + { + "i": { + "x": 0.667, + "y": 1 + }, + "o": { + "x": 0.167, + "y": 0.167 + }, + "n": "0p667_1_0p167_0p167", + "t": 60, + "s": [ + { + "i": [ + [ + 0.192, + 0 + ], + [ + 0.146, + 0.147 + ], + [ + 0, + 0 + ], + [ + -0.293, + 0.293 + ], + [ + -0.293, + -0.293 + ], + [ + 0, + 0 + ], + [ + 0.293, + -0.293 + ] + ], + "o": [ + [ + -0.192, + 0 + ], + [ + 0, + 0 + ], + [ + -0.293, + -0.293 + ], + [ + 0.293, + -0.293 + ], + [ + 0, + 0 + ], + [ + 0.293, + 0.293 + ], + [ + -0.146, + 0.147 + ] + ], + "v": [ + [ + 5.402, + 6.189 + ], + [ + 4.872, + 5.97 + ], + [ + -5.932, + -4.836 + ], + [ + -5.932, + -5.896 + ], + [ + -4.872, + -5.896 + ], + [ + 5.932, + 4.91 + ], + [ + 5.932, + 5.97 + ] + ], + "c": true + } + ], + "e": [ + { + "i": [ + [ + 0.192, + 0 + ], + [ + 0.146, + 0.147 + ], + [ + 0, + 0 + ], + [ + -0.293, + 0.293 + ], + [ + -0.293, + -0.293 + ], + [ + 0, + 0 + ], + [ + 0.293, + -0.293 + ] + ], + "o": [ + [ + -0.192, + 0 + ], + [ + 0, + 0 + ], + [ + -0.293, + -0.293 + ], + [ + 0.293, + -0.293 + ], + [ + 0, + 0 + ], + [ + 0.293, + 0.293 + ], + [ + -0.146, + 0.147 + ] + ], + "v": [ + [ + -5.569, + -4.777 + ], + [ + -6.099, + -4.996 + ], + [ + -5.932, + -4.836 + ], + [ + -5.932, + -5.896 + ], + [ + -4.872, + -5.896 + ], + [ + -5.039, + -6.056 + ], + [ + -5.039, + -4.996 + ] + ], + "c": true + } + ] + }, + { + "t": 66.0000026882351 + } + ], + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 1, + 1, + 1, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 6.475, + 6.439 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 1", + "np": 2, + "cix": 2, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + } + ], + "ip": 19.0000007738859, + "op": 66.0000026882351, + "st": 0, + "bm": 0 + }, + { + "ddd": 0, + "ind": 6, + "ty": 4, + "nm": "mask_bar Outlines", + "td": 1, + "sr": 1, + "ks": { + "o": { + "a": 0, + "k": 100, + "ix": 11 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "p": { + "a": 0, + "k": [ + 10.585, + 9.499, + 0 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 7.488, + 7.402, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100, + 100 + ], + "ix": 6 + } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 1, + "k": [ + { + "i": { + "x": 0.667, + "y": 1 + }, + "o": { + "x": 0.167, + "y": 0.167 + }, + "n": "0p667_1_0p167_0p167", + "t": 18, + "s": [ + { + "i": [ + [ + 0.683, + 0.683 + ], + [ + 0, + 0 + ], + [ + 0.467, + 0 + ], + [ + 0.33, + -0.331 + ], + [ + 0, + -0.467 + ], + [ + -0.331, + -0.33 + ], + [ + 0, + 0 + ], + [ + -0.468, + 0 + ], + [ + -0.33, + 0.33 + ] + ], + "o": [ + [ + 0, + 0 + ], + [ + -0.33, + -0.331 + ], + [ + -0.467, + 0 + ], + [ + -0.331, + 0.33 + ], + [ + 0, + 0.467 + ], + [ + 0, + 0 + ], + [ + 0.33, + 0.33 + ], + [ + 0.467, + 0 + ], + [ + 0.683, + -0.683 + ] + ], + "v": [ + [ + -5.614, + -8.041 + ], + [ + -4.251, + -6.639 + ], + [ + -5.488, + -7.152 + ], + [ + -6.725, + -6.639 + ], + [ + -7.238, + -5.402 + ], + [ + -6.725, + -4.165 + ], + [ + -8.089, + -5.565 + ], + [ + -6.851, + -5.054 + ], + [ + -5.614, + -5.565 + ] + ], + "c": true + } + ], + "e": [ + { + "i": [ + [ + 0.683, + 0.683 + ], + [ + 0, + 0 + ], + [ + 0.467, + 0 + ], + [ + 0.33, + -0.331 + ], + [ + 0, + -0.467 + ], + [ + -0.331, + -0.33 + ], + [ + 0, + 0 + ], + [ + -0.468, + 0 + ], + [ + -0.33, + 0.33 + ] + ], + "o": [ + [ + 0, + 0 + ], + [ + -0.33, + -0.331 + ], + [ + -0.467, + 0 + ], + [ + -0.331, + 0.33 + ], + [ + 0, + 0.467 + ], + [ + 0, + 0 + ], + [ + 0.33, + 0.33 + ], + [ + 0.467, + 0 + ], + [ + 0.683, + -0.683 + ] + ], + "v": [ + [ + 6.555, + 4.165 + ], + [ + -4.251, + -6.639 + ], + [ + -5.488, + -7.152 + ], + [ + -6.725, + -6.639 + ], + [ + -7.238, + -5.402 + ], + [ + -6.725, + -4.165 + ], + [ + 4.079, + 6.641 + ], + [ + 5.318, + 7.152 + ], + [ + 6.555, + 6.641 + ] + ], + "c": true + } + ] + }, + { + "i": { + "x": 0.667, + "y": 1 + }, + "o": { + "x": 0.167, + "y": 0.167 + }, + "n": "0p667_1_0p167_0p167", + "t": 24, + "s": [ + { + "i": [ + [ + 0.683, + 0.683 + ], + [ + 0, + 0 + ], + [ + 0.467, + 0 + ], + [ + 0.33, + -0.331 + ], + [ + 0, + -0.467 + ], + [ + -0.331, + -0.33 + ], + [ + 0, + 0 + ], + [ + -0.468, + 0 + ], + [ + -0.33, + 0.33 + ] + ], + "o": [ + [ + 0, + 0 + ], + [ + -0.33, + -0.331 + ], + [ + -0.467, + 0 + ], + [ + -0.331, + 0.33 + ], + [ + 0, + 0.467 + ], + [ + 0, + 0 + ], + [ + 0.33, + 0.33 + ], + [ + 0.467, + 0 + ], + [ + 0.683, + -0.683 + ] + ], + "v": [ + [ + 6.555, + 4.165 + ], + [ + -4.251, + -6.639 + ], + [ + -5.488, + -7.152 + ], + [ + -6.725, + -6.639 + ], + [ + -7.238, + -5.402 + ], + [ + -6.725, + -4.165 + ], + [ + 4.079, + 6.641 + ], + [ + 5.318, + 7.152 + ], + [ + 6.555, + 6.641 + ] + ], + "c": true + } + ], + "e": [ + { + "i": [ + [ + 0.683, + 0.683 + ], + [ + 0, + 0 + ], + [ + 0.467, + 0 + ], + [ + 0.33, + -0.331 + ], + [ + 0, + -0.467 + ], + [ + -0.331, + -0.33 + ], + [ + 0, + 0 + ], + [ + -0.468, + 0 + ], + [ + -0.33, + 0.33 + ] + ], + "o": [ + [ + 0, + 0 + ], + [ + -0.33, + -0.331 + ], + [ + -0.467, + 0 + ], + [ + -0.331, + 0.33 + ], + [ + 0, + 0.467 + ], + [ + 0, + 0 + ], + [ + 0.33, + 0.33 + ], + [ + 0.467, + 0 + ], + [ + 0.683, + -0.683 + ] + ], + "v": [ + [ + 6.555, + 4.165 + ], + [ + -4.251, + -6.639 + ], + [ + -5.488, + -7.152 + ], + [ + -6.725, + -6.639 + ], + [ + -7.238, + -5.402 + ], + [ + -6.725, + -4.165 + ], + [ + 4.079, + 6.641 + ], + [ + 5.318, + 7.152 + ], + [ + 6.555, + 6.641 + ] + ], + "c": true + } + ] + }, + { + "i": { + "x": 0.667, + "y": 1 + }, + "o": { + "x": 0.167, + "y": 0.167 + }, + "n": "0p667_1_0p167_0p167", + "t": 60, + "s": [ + { + "i": [ + [ + 0.683, + 0.683 + ], + [ + 0, + 0 + ], + [ + 0.467, + 0 + ], + [ + 0.33, + -0.331 + ], + [ + 0, + -0.467 + ], + [ + -0.331, + -0.33 + ], + [ + 0, + 0 + ], + [ + -0.468, + 0 + ], + [ + -0.33, + 0.33 + ] + ], + "o": [ + [ + 0, + 0 + ], + [ + -0.33, + -0.331 + ], + [ + -0.467, + 0 + ], + [ + -0.331, + 0.33 + ], + [ + 0, + 0.467 + ], + [ + 0, + 0 + ], + [ + 0.33, + 0.33 + ], + [ + 0.467, + 0 + ], + [ + 0.683, + -0.683 + ] + ], + "v": [ + [ + 6.555, + 4.165 + ], + [ + -4.251, + -6.639 + ], + [ + -5.488, + -7.152 + ], + [ + -6.725, + -6.639 + ], + [ + -7.238, + -5.402 + ], + [ + -6.725, + -4.165 + ], + [ + 4.079, + 6.641 + ], + [ + 5.318, + 7.152 + ], + [ + 6.555, + 6.641 + ] + ], + "c": true + } + ], + "e": [ + { + "i": [ + [ + 0.683, + 0.683 + ], + [ + 0, + 0 + ], + [ + 0.467, + 0 + ], + [ + 0.33, + -0.331 + ], + [ + 0, + -0.467 + ], + [ + -0.331, + -0.33 + ], + [ + 0, + 0 + ], + [ + -0.468, + 0 + ], + [ + -0.33, + 0.33 + ] + ], + "o": [ + [ + 0, + 0 + ], + [ + -0.33, + -0.331 + ], + [ + -0.467, + 0 + ], + [ + -0.331, + 0.33 + ], + [ + 0, + 0.467 + ], + [ + 0, + 0 + ], + [ + 0.33, + 0.33 + ], + [ + 0.467, + 0 + ], + [ + 0.683, + -0.683 + ] + ], + "v": [ + [ + -5.614, + -8.041 + ], + [ + -4.251, + -6.639 + ], + [ + -5.488, + -7.152 + ], + [ + -6.725, + -6.639 + ], + [ + -7.238, + -5.402 + ], + [ + -6.725, + -4.165 + ], + [ + -8.089, + -5.565 + ], + [ + -6.851, + -5.054 + ], + [ + -5.614, + -5.565 + ] + ], + "c": true + } + ] + }, + { + "t": 66.0000026882351 + } + ], + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0, + 0, + 0, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 7.488, + 7.403 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 1", + "np": 2, + "cix": 2, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + } + ], + "ip": -7.00000028511585, + "op": 91.000003706506, + "st": 0, + "bm": 0 + }, + { + "ddd": 0, + "ind": 7, + "ty": 4, + "nm": "speaker Outlines", + "tt": 2, + "sr": 1, + "ks": { + "o": { + "a": 0, + "k": 100, + "ix": 11 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "p": { + "a": 1, + "k": [ + { + "i": { + "x": 0.936, + "y": 1 + }, + "o": { + "x": 0.237, + "y": 0.075 + }, + "n": "0p936_1_0p237_0p075", + "t": 8, + "s": [ + 5.049, + 9.975, + 0 + ], + "e": [ + 9.924, + 9.975, + 0 + ], + "to": [ + 0.8125, + 0, + 0 + ], + "ti": [ + -0.8125, + 0, + 0 + ] + }, + { + "i": { + "x": 0.936, + "y": 0.936 + }, + "o": { + "x": 0.167, + "y": 0.167 + }, + "n": "0p936_0p936_0p167_0p167", + "t": 18, + "s": [ + 9.924, + 9.975, + 0 + ], + "e": [ + 9.924, + 9.975, + 0 + ], + "to": [ + 0, + 0, + 0 + ], + "ti": [ + 0, + 0, + 0 + ] + }, + { + "i": { + "x": 0.833, + "y": 0.833 + }, + "o": { + "x": 0.167, + "y": 0 + }, + "n": "0p833_0p833_0p167_0", + "t": 66, + "s": [ + 9.924, + 9.975, + 0 + ], + "e": [ + 5.049, + 9.975, + 0 + ], + "to": [ + -0.8125, + 0, + 0 + ], + "ti": [ + 0.8125, + 0, + 0 + ] + }, + { + "t": 76.0000030955435 + } + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 5.051, + 7.326, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100, + 100 + ], + "ix": 6 + } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + -0.132, + -0.106 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0.17, + 0 + ], + [ + 0, + 0 + ] + ], + "o": [ + [ + 0, + 0 + ], + [ + 0.17, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + -0.132, + 0.106 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ] + ], + "v": [ + [ + -3.301, + 1.976 + ], + [ + -0.45, + 1.976 + ], + [ + 0.018, + 2.14 + ], + [ + 3.301, + 4.765 + ], + [ + 3.301, + -4.716 + ], + [ + 0.018, + -2.09 + ], + [ + -0.45, + -1.926 + ], + [ + -3.301, + -1.926 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ind": 1, + "ty": "sh", + "ix": 2, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 0.11, + 0 + ], + [ + 0.136, + 0.109 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0.414 + ], + [ + 0, + 0 + ], + [ + -0.414, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + -0.26, + -0.124 + ], + [ + 0, + -0.289 + ], + [ + 0, + 0 + ], + [ + 0.26, + -0.124 + ] + ], + "o": [ + [ + -0.167, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + -0.414, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + -0.414 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0.225, + -0.181 + ], + [ + 0.26, + 0.124 + ], + [ + 0, + 0 + ], + [ + 0, + 0.289 + ], + [ + -0.104, + 0.051 + ] + ], + "v": [ + [ + 4.051, + 7.076 + ], + [ + 3.582, + 6.912 + ], + [ + -0.713, + 3.476 + ], + [ + -4.051, + 3.476 + ], + [ + -4.801, + 2.726 + ], + [ + -4.801, + -2.676 + ], + [ + -4.051, + -3.426 + ], + [ + -0.713, + -3.426 + ], + [ + 3.582, + -6.862 + ], + [ + 4.376, + -6.952 + ], + [ + 4.801, + -6.276 + ], + [ + 4.801, + 6.326 + ], + [ + 4.376, + 7.001 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 2", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "mm", + "mm": 1, + "nm": "Merge Paths 1", + "mn": "ADBE Vector Filter - Merge", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 1, + 1, + 1, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 5.051, + 7.326 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 1", + "np": 4, + "cix": 2, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + } + ], + "ip": 0, + "op": 91.000003706506, + "st": 0, + "bm": 0 + } + ], + "markers": [] +} \ No newline at end of file From 73e76f278909b2d89d4d7c403a9d9aa972b561d4 Mon Sep 17 00:00:00 2001 From: DongHyeon Park Date: Sun, 2 Jul 2023 22:48:36 +0900 Subject: [PATCH 4/6] =?UTF-8?q?issue=20#161=20refactor:=20ViewModel=20?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=84=B0=20Flow=EB=A1=9C=20=EB=A6=AC?= =?UTF-8?q?=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../uploadfilm/UploadFilmViewModel.kt | 95 ++++++++++++------- 1 file changed, 60 insertions(+), 35 deletions(-) diff --git a/app/src/main/java/com/boostcamp/dailyfilm/presentation/uploadfilm/UploadFilmViewModel.kt b/app/src/main/java/com/boostcamp/dailyfilm/presentation/uploadfilm/UploadFilmViewModel.kt index 88b3b21..1ffb352 100644 --- a/app/src/main/java/com/boostcamp/dailyfilm/presentation/uploadfilm/UploadFilmViewModel.kt +++ b/app/src/main/java/com/boostcamp/dailyfilm/presentation/uploadfilm/UploadFilmViewModel.kt @@ -24,6 +24,7 @@ import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharedFlow +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch import javax.inject.Inject @@ -39,7 +40,7 @@ class UploadFilmViewModel @Inject constructor( val startTime = savedStateHandle.get(KEY_START_TIME) ?: 0L val dateModel = savedStateHandle.get(KEY_DATE_MODEL) val calendarIndex = savedStateHandle.get(KEY_CALENDAR_INDEX) - val editState = savedStateHandle.get(KEY_EDIT_STATE) + val editState = savedStateHandle.getStateFlow(KEY_EDIT_STATE, null) private val _uploadResult = MutableSharedFlow() val uploadResult: SharedFlow get() = _uploadResult @@ -61,12 +62,25 @@ class UploadFilmViewModel @Inject constructor( private val _isWriting = MutableLiveData(false) val isWriting: LiveData get() = _isWriting - private val _clickSound = MutableStateFlow(true) - val clickSound = _clickSound.asStateFlow() - private val _compressProgress = MutableLiveData(0) val compressProgress: LiveData get() = _compressProgress + + private val _uploadUiState = MutableStateFlow(UploadUiState.Idle) + val uploadUiState: StateFlow get() = _uploadUiState + + private val _writingState = MutableStateFlow(false) + val writingState: StateFlow get() = _writingState + + private val _muteState = MutableStateFlow(false) + val muteState = _muteState.asStateFlow() + + private val _contentState = MutableStateFlow("") + + private val _compressState = MutableStateFlow(0) + val compressState: StateFlow get() = _compressState + + init { calcProgress() } @@ -75,10 +89,10 @@ class UploadFilmViewModel @Inject constructor( Config.resetStatistics() Config.enableStatisticsCallback { val percentage = it.videoFrameNumber - _compressProgress.postValue(percentage) + _compressState.value = percentage if (isEnded()) - _compressProgress.postValue(240) + _compressState.value = 240 } } @@ -90,21 +104,22 @@ class UploadFilmViewModel @Inject constructor( fun uploadVideo() { - val text = textContent.value ?: "" - val progress = _compressProgress.value ?: 0 + val text = _contentState.value ?: "" + val progress = _compressState.value when { text.isEmpty() -> { - _uiState.value = UiState.Failure(Throwable("영상에 맞는 문구를 입력해주세요.")) + _uploadUiState.value = UploadUiState.UploadFailed(Throwable("일기가 비어있습니다")) return } - (editState != EditState.EDIT_CONTENT) && progress < 240 -> { - _uiState.value = UiState.Failure(Throwable("영상 처리중입니다. 잠시만 기다려주세요.")) + (editState.value != EditState.EDIT_CONTENT) && progress < 240 -> { + _uploadUiState.value = UploadUiState.UploadFailed(Throwable("영상이 처리중입니다. 잠시만 기다려주세요")) return } } - editState?.let { state -> + _uploadUiState.value = UploadUiState.UploadLoading + editState.value?.let { state -> when (state) { EditState.NEW_UPLOAD -> uploadStorage() EditState.EDIT_CONTENT -> uploadEdit() @@ -115,22 +130,19 @@ class UploadFilmViewModel @Inject constructor( private fun uploadEdit() { - val text = textContent.value ?: "" + val text = _contentState.value ?: "" infoItem?.let { item -> - _uiState.value = UiState.Loading viewModelScope.launch { dateModel ?: return@launch val date = item.uploadDate val dailyFilmItem = DailyFilmItem(dateModel.videoUrl.toString(), text, date) when (val result = uploadFilmRepository.uploadEditVideo(date, dailyFilmItem)) { is Result.Success -> { - _uiState.value = UiState.Success( - dateModel.copy(text = text) - ) + _uploadUiState.value = UploadUiState.UploadSuccess(dateModel.copy(text = text)) } is Result.Error -> { - _uiState.value = UiState.Failure(result.exception) + _uploadUiState.value = UploadUiState.UploadFailed(result.exception) } } } @@ -139,14 +151,13 @@ class UploadFilmViewModel @Inject constructor( private fun uploadStorage() { infoItem?.let { item -> - _uiState.value = UiState.Loading viewModelScope.launch { when (val result = uploadFilmRepository.uploadVideo(item.uploadDate, item.uri)) { is Result.Success -> { uploadRealtime(result.data) } is Result.Error -> { - _uiState.value = UiState.Failure(result.exception) + _uploadUiState.value = UploadUiState.UploadFailed(result.exception) } } } @@ -155,9 +166,9 @@ class UploadFilmViewModel @Inject constructor( private fun uploadRealtime(videoUrl: Uri?) { val uploadDate = infoItem?.uploadDate - val text = textContent.value ?: "" + val text = _contentState.value ?: "" if (dateModel ==null){ - _uiState.value = UiState.Failure(Throwable("dateModel Fail")) + _uploadUiState.value = UploadUiState.UploadFailed(Throwable("dateModel failed")) return } if (videoUrl != null && uploadDate != null) { @@ -166,23 +177,23 @@ class UploadFilmViewModel @Inject constructor( when (val result = uploadFilmRepository.uploadFilmInfo(uploadDate, filmItem)) { is Result.Success -> { uploadFilmRepository.insertFilmEntity(filmItem) - _uiState.value = UiState.Success( + _uploadUiState.value = UploadUiState.UploadSuccess( dateModel.copy(text = text, videoUrl = videoUrl.toString()) ) } is Result.Error -> { - _uiState.value = UiState.Failure(result.exception) + _uploadUiState.value = UploadUiState.UploadFailed(result.exception) } } } } else { - _uiState.value = - UiState.Failure(Throwable("userId == null or videoUrl == null or uploadDate or null ")) + _uploadUiState.value = + UploadUiState.UploadFailed(Throwable("userId or videoUrl or uploadDate is null")) } } fun updateSpannableText() { - textContent.value?.let { text -> + _contentState.value.let { text -> if (text.isNotEmpty()) { _showedTextContent.value = SpannableString(text).apply { setSpan( @@ -198,11 +209,14 @@ class UploadFilmViewModel @Inject constructor( } } + fun updateTextContent(text: String) { + _contentState.value = text + } + private fun deleteVideo() { dateModel ?: return viewModelScope.launch { - _uiState.value = UiState.Loading val updateDate = dateModel.getDate() when (val result = deleteFilmRepository.delete(updateDate)) { @@ -210,29 +224,27 @@ class UploadFilmViewModel @Inject constructor( uploadStorage() } is Result.Error -> { - UiState.Failure(result.exception) + _uploadUiState.value = UploadUiState.UploadFailed(result.exception) } } } } fun changeIsWriting() { - _isWriting.value?.let { - _isWriting.value = it.not() - } + _writingState.value = _writingState.value.not() } fun updateIsWriting(flag: Boolean) { - _isWriting.value = flag + _writingState.value = flag } fun controlSound() { - _clickSound.value = !_clickSound.value + _muteState.value = !_muteState.value } fun cancelUploadVideo() { viewModelScope.launch { - _cancelUploadResult.emit(true) + _uploadUiState.emit(UploadUiState.Canceled) } } @@ -241,3 +253,16 @@ class UploadFilmViewModel @Inject constructor( const val KEY_START_TIME = "start_time" } } + +sealed interface UploadUiState { + + object Idle: UploadUiState + + object Canceled: UploadUiState + object UploadLoading: UploadUiState + + data class UploadSuccess(val dateModel: DateModel): UploadUiState + + data class UploadFailed(val throwable: Throwable): UploadUiState + +} From c61ef454a6985643ae2b5f5f4d56046e3f635a75 Mon Sep 17 00:00:00 2001 From: DongHyeon Park Date: Sun, 2 Jul 2023 22:49:48 +0900 Subject: [PATCH 5/6] =?UTF-8?q?issue=20#161=20feat:=20=EB=82=B4=EC=9A=A9?= =?UTF-8?q?=20=EC=9E=91=EC=84=B1=20=ED=99=94=EB=A9=B4=20Compose=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../uploadfilm/UploadFilmCompose.kt | 564 ++++++++++++++++++ 1 file changed, 564 insertions(+) create mode 100644 app/src/main/java/com/boostcamp/dailyfilm/presentation/uploadfilm/UploadFilmCompose.kt diff --git a/app/src/main/java/com/boostcamp/dailyfilm/presentation/uploadfilm/UploadFilmCompose.kt b/app/src/main/java/com/boostcamp/dailyfilm/presentation/uploadfilm/UploadFilmCompose.kt new file mode 100644 index 0000000..f403150 --- /dev/null +++ b/app/src/main/java/com/boostcamp/dailyfilm/presentation/uploadfilm/UploadFilmCompose.kt @@ -0,0 +1,564 @@ +package com.boostcamp.dailyfilm.presentation.uploadfilm + +import android.app.Activity +import android.net.Uri +import android.view.ViewGroup +import android.widget.FrameLayout +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.focusable +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.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.wrapContentHeight +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.text.KeyboardActions +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material.Text +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.ArrowBack +import androidx.compose.material.icons.outlined.Check +import androidx.compose.material.MaterialTheme +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.FilledIconButton +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButtonDefaults +import androidx.compose.material3.LinearProgressIndicator +import androidx.compose.material3.Scaffold +import androidx.compose.material3.SnackbarHost +import androidx.compose.material3.SnackbarHostState +import androidx.compose.material3.TextField +import androidx.compose.material3.TextFieldDefaults +import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberUpdatedState +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.focus.focusRequester +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalFocusManager +import androidx.compose.ui.platform.LocalLifecycleOwner +import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.buildAnnotatedString +import androidx.compose.ui.text.input.ImeAction +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextDecoration +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.compose.ui.viewinterop.AndroidView +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.LifecycleEventObserver +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.airbnb.lottie.LottieComposition +import com.airbnb.lottie.compose.LottieAnimation +import com.airbnb.lottie.compose.LottieClipSpec +import com.airbnb.lottie.compose.LottieCompositionSpec +import com.airbnb.lottie.compose.rememberLottieAnimatable +import com.airbnb.lottie.compose.rememberLottieComposition +import com.boostcamp.dailyfilm.R +import com.boostcamp.dailyfilm.presentation.playfilm.model.EditState +import com.google.android.exoplayer2.ExoPlayer +import com.google.android.exoplayer2.MediaItem +import com.google.android.exoplayer2.Player +import com.google.android.exoplayer2.ui.AspectRatioFrameLayout +import com.google.android.exoplayer2.ui.StyledPlayerView +import kotlinx.coroutines.delay +import me.saket.extendedspans.ExtendedSpans +import me.saket.extendedspans.RoundedCornerSpanPainter +import me.saket.extendedspans.SquigglyUnderlineSpanPainter +import me.saket.extendedspans.drawBehind +import me.saket.extendedspans.rememberSquigglyUnderlineAnimator +import net.yslibrary.android.keyboardvisibilityevent.KeyboardVisibilityEvent +import kotlin.time.Duration + + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun UploadFilmScreen( + viewModel: UploadFilmViewModel, + modifier: Modifier = Modifier, +) { + + val activity = LocalContext.current as Activity + val editState by viewModel.editState.collectAsStateWithLifecycle() + val uploadUiState by viewModel.uploadUiState.collectAsStateWithLifecycle() + val writingState by viewModel.writingState.collectAsStateWithLifecycle() + val muteState by viewModel.muteState.collectAsStateWithLifecycle() + val compressState by viewModel.compressState.collectAsStateWithLifecycle() + val snackbarHostState = remember { SnackbarHostState() } + val focusRequester = remember { FocusRequester() } + + LaunchedEffect(Unit) { + KeyboardVisibilityEvent.setEventListener(activity) { viewModel.updateIsWriting(it) } + } + + LaunchedEffect(uploadUiState) { + when (uploadUiState) { + is UploadUiState.UploadFailed -> { + val state = uploadUiState as UploadUiState.UploadFailed + state.throwable.message?.let { + snackbarHostState.showSnackbar(it) + } + } + + else -> {} + } + } + + when (writingState) { + true -> focusRequester.requestFocus() + false -> LocalFocusManager.current.clearFocus() + } + + BackgroundVideoPlayer( + originUri = viewModel.beforeItem?.uri, + resultUri = viewModel.infoItem?.uri, + startTime = viewModel.startTime, + editState = editState, + muteState = muteState, + modifier = Modifier.fillMaxSize() + ) + + Scaffold( + snackbarHost = { SnackbarHost(hostState = snackbarHostState) }, + containerColor = Color.Transparent, + topBar = { + UploadFilmTopArea( + writingState = writingState, + muteState = muteState, + backAction = viewModel::cancelUploadVideo, + uploadAction = viewModel::uploadVideo, + muteAction = viewModel::controlSound, + editTextAction = viewModel::changeIsWriting, + modifier = Modifier + .background(color = Color.Transparent) + .fillMaxWidth() + .padding(4.dp) + ) + }, + content = { innerPadding -> + UploadFilmMainArea( + compressVal = compressState, + focusRequester = focusRequester, + onTextChanged = viewModel::updateTextContent, + onKeyboardHide = viewModel::changeIsWriting, + modifier = Modifier + .padding(innerPadding) + .fillMaxSize() + .background(color = Color.Transparent) + ) + }, + modifier = modifier + .background(color = Color.Transparent) + ) + + // 업로드 로딩 Composition + if (uploadUiState is UploadUiState.UploadLoading) + UploadLoadingProgress( + modifier = Modifier + .fillMaxSize() + ) + +} + +@Composable +fun UploadFilmTopArea( + writingState: Boolean, + muteState: Boolean, + backAction: () -> Unit, + uploadAction: () -> Unit, + muteAction: () -> Unit, + editTextAction: () -> Unit, + modifier: Modifier = Modifier +) { + + val muteComposition by rememberLottieComposition(spec = LottieCompositionSpec.RawRes(R.raw.lottie_sound)) + val writingComposition by rememberLottieComposition(spec = LottieCompositionSpec.RawRes(R.raw.lottie_writing)) + + Box(modifier = modifier) { + val muteAnimatable = rememberLottieAnimatable() + LaunchedEffect(muteState) { + muteAnimatable.animate( + muteComposition, + clipSpec = when (muteState) { + true -> LottieClipSpec.Progress(0f, 0.5f) + false -> LottieClipSpec.Progress(0.5f, 1.0f) + }, + speed = 5f + ) + } + + Row( + modifier = Modifier + .align(Alignment.CenterStart) + .wrapContentSize() + .background(color = Color.Transparent) + ) { + + // 뒤로 가기 버튼 + TopButton( + onClick = backAction, + icon = Icons.Outlined.ArrowBack + ) + + LottieButton( + composition = muteComposition, + progress = muteAnimatable.progress, + onClick = muteAction, + modifier = Modifier + .padding(start = 12.dp, top = 4.dp, bottom = 4.dp) + ) + } + + val writingAnimatable = rememberLottieAnimatable() + LaunchedEffect(writingState) { + writingAnimatable.animate( + writingComposition, + clipSpec = when (writingState) { + true -> LottieClipSpec.Progress(0f, 0.5f) + false -> LottieClipSpec.Progress(0.5f, 1f) + }, + speed = 2f + ) + } + LottieButton( + composition = writingComposition, + progress = writingAnimatable.progress, + onClick = editTextAction, + modifier = Modifier + .align(Alignment.Center) + ) + + // 업로드 버튼 + TopButton( + onClick = uploadAction, + icon = Icons.Outlined.Check, + modifier = Modifier.align(Alignment.CenterEnd) + ) + + } + +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun UploadFilmMainArea( + compressVal: Int, + focusRequester: FocusRequester, + onTextChanged: (String) -> Unit, + onKeyboardHide: () -> Unit, + modifier: Modifier +) { + + Box(modifier = modifier) { + + LinearProgressIndicator( + progress = (compressVal.toFloat() / 240f), + color = MaterialTheme.colors.primary, + trackColor = MaterialTheme.colors.surface, + modifier = Modifier + .fillMaxWidth() + .align(Alignment.TopCenter) + ) + + val textContent = remember { mutableStateOf("") } + val squigglyAniamtor = rememberSquigglyUnderlineAnimator(duration = Duration.parse("3s")) + val extendedSpans = remember { + ExtendedSpans( + RoundedCornerSpanPainter( + padding = RoundedCornerSpanPainter.TextPaddingValues(6.sp, 6.sp), + topMargin = 2.sp, + bottomMargin = 2.sp + ), + SquigglyUnderlineSpanPainter(wavelength = 20.sp, animator = squigglyAniamtor) + ) + } + + // 실제로 입력받는 필드 (보이지는 않음) + TextField( + value = textContent.value, + onValueChange = { textValue -> + textContent.value = textValue + onTextChanged(textValue) + }, + textStyle = TextStyle( + color = Color.Transparent, // 실제로는 보여주지 않기 + fontSize = 22.sp, + textAlign = TextAlign.Center + ), + keyboardOptions = KeyboardOptions(imeAction = ImeAction.Default), + keyboardActions = KeyboardActions(onDone = { onKeyboardHide() }), + colors = TextFieldDefaults.textFieldColors( + containerColor = Color.Transparent, + placeholderColor = Color.Transparent, + cursorColor = Color.Transparent, + focusedIndicatorColor = Color.Transparent, + disabledIndicatorColor = Color.Transparent, + unfocusedIndicatorColor = Color.Transparent, + ), + modifier = Modifier + .align(Alignment.Center) + .background(color = Color.Transparent) + .focusable(true) + .focusRequester(focusRequester) + ) + + // 눈에 보이는 텍스트 + Text( + modifier = Modifier + .drawBehind(extendedSpans) + .align(Alignment.Center), + text = + buildAnnotatedString { + textContent.value.split("\n").also { texts -> + texts.forEachIndexed { i, text -> + append( + extendedSpans.extend( + AnnotatedString( + text, + spanStyle = SpanStyle( + textDecoration = TextDecoration.Underline, + color = MaterialTheme.colors.surface, + background = MaterialTheme.colors.primary + ), + ) + ) + ) + + if (i < texts.size) + appendLine() + } + } + }, + fontSize = 22.sp, + textAlign = TextAlign.Center, + onTextLayout = { result -> + extendedSpans.onTextLayout(result) + } + ) + + } + +} + +@Composable +fun TopButton( + onClick: () -> Unit, + icon: ImageVector, + modifier: Modifier = Modifier +) { + FilledIconButton( + onClick = onClick, + colors = IconButtonDefaults.filledIconButtonColors( + containerColor = MaterialTheme.colors.primaryVariant, + contentColor = MaterialTheme.colors.surface + ), + modifier = modifier + ) { + Icon(icon, contentDescription = null) + } +} + +@Composable +fun BackgroundVideoPlayer( + originUri: Uri?, + resultUri: Uri?, + startTime: Long, + editState: EditState?, + muteState: Boolean, + modifier: Modifier = Modifier, +) { + if (editState == null) return + + val context = LocalContext.current + val lifecycleOwner = rememberUpdatedState(LocalLifecycleOwner.current) + val mediaItem = remember { + var media = MediaItem.EMPTY + when (editState) { + EditState.EDIT_CONTENT -> { + if (resultUri != null) media = MediaItem.fromUri(resultUri) + } + + EditState.NEW_UPLOAD, EditState.RE_UPLOAD -> { + if (originUri != null) { + media = MediaItem.fromUri(originUri) + } + } + } + media + } + + val exoPlayer = remember { + ExoPlayer.Builder(context).build().apply { + volume = 0.5f + repeatMode = Player.REPEAT_MODE_ONE + setMediaItem(mediaItem) + prepare() + play() + } + } + + LaunchedEffect(mediaItem) { + if (editState == EditState.NEW_UPLOAD || editState == EditState.RE_UPLOAD) { + if (originUri != null) { + while (true) { + exoPlayer.seekTo(startTime) + delay(10_000) + } + } + } + } + + LaunchedEffect(muteState) { + when (muteState) { + true -> exoPlayer.volume = 0.0f + false -> exoPlayer.volume = 0.5f + } + } + + DisposableEffect( + AndroidView( + modifier = modifier, + factory = { + StyledPlayerView(it).apply { + player = exoPlayer + useController = false + layoutParams = + FrameLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + ) + resizeMode = AspectRatioFrameLayout.RESIZE_MODE_ZOOM + } + }) + ) { + lifecycleOwner.value.lifecycle.addObserver( + LifecycleEventObserver { _, event -> + when(event) { + Lifecycle.Event.ON_PAUSE -> exoPlayer.pause() + Lifecycle.Event.ON_RESUME -> exoPlayer.play() + else -> {} + } + } + ) + + onDispose { exoPlayer.release() } + } + + +} + +@Composable +fun LottieButton( + composition: LottieComposition?, + progress: Float, + onClick: () -> Unit, + modifier: Modifier = Modifier +) { + + Box(modifier = modifier + .background( + color = MaterialTheme.colors.primaryVariant, + shape = CircleShape + ) + .size(40.dp) + .clip(CircleShape) + .clickable { onClick() } + ) { + LottieAnimation( + composition = composition, + progress = { progress }, + modifier = Modifier + .padding(8.dp) + .align(Alignment.Center) + .fillMaxSize() + ) + } + +} + +@Composable +fun UploadLoadingProgress( + modifier: Modifier = Modifier +) { + + Column( + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally, + modifier = modifier + .background(MaterialTheme.colors.primaryVariant) + ) { + + CircularProgressIndicator( + modifier = Modifier + .align(Alignment.CenterHorizontally) + .size(100.dp), + color = MaterialTheme.colors.surface, + ) + + } + +} + +@Preview +@Composable +fun PreviewLottieButton() { + LottieButton( + composition = LottieComposition(), + progress = 0f, + onClick = {} + ) +} + +@Preview +@Composable +fun PreviewLoadingProgress() { + UploadLoadingProgress() +} + +@Preview +@Composable +fun PreviewUploadFilmTopArea() { + UploadFilmTopArea( + writingState = true, + muteState = true, + backAction = {}, + uploadAction = {}, + muteAction = {}, + editTextAction = {}, + modifier = Modifier + .fillMaxWidth() + .wrapContentHeight() + ) +} + +@Preview +@Composable +fun PreviewUploadFilmMainArea() { + UploadFilmMainArea( + compressVal = 240, + focusRequester = FocusRequester(), + onTextChanged = {}, + onKeyboardHide = {}, + modifier = Modifier + .fillMaxSize() + ) +} \ No newline at end of file From c05b627d49c4c8b61056c9e23eda98e281bf9ec1 Mon Sep 17 00:00:00 2001 From: DongHyeon Park Date: Sun, 2 Jul 2023 22:50:10 +0900 Subject: [PATCH 6/6] =?UTF-8?q?issue=20#161=20feat:=20Compose=EC=9A=A9=20?= =?UTF-8?q?=EC=95=A1=ED=8B=B0=EB=B9=84=ED=8B=B0=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 3 + .../trimvideo/TrimVideoActivity.kt | 3 +- .../uploadfilm/UploadFilmComposeActivity.kt | 106 ++++++++++++++++++ 3 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/com/boostcamp/dailyfilm/presentation/uploadfilm/UploadFilmComposeActivity.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a25bc8e..cef3214 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -42,6 +42,9 @@ + diff --git a/app/src/main/java/com/boostcamp/dailyfilm/presentation/trimvideo/TrimVideoActivity.kt b/app/src/main/java/com/boostcamp/dailyfilm/presentation/trimvideo/TrimVideoActivity.kt index f7a2580..dd6505d 100644 --- a/app/src/main/java/com/boostcamp/dailyfilm/presentation/trimvideo/TrimVideoActivity.kt +++ b/app/src/main/java/com/boostcamp/dailyfilm/presentation/trimvideo/TrimVideoActivity.kt @@ -19,6 +19,7 @@ import com.boostcamp.dailyfilm.presentation.calendar.model.DateModel import com.boostcamp.dailyfilm.presentation.selectvideo.SelectVideoActivity import com.boostcamp.dailyfilm.presentation.selectvideo.SelectVideoActivity.Companion.DATE_VIDEO_ITEM import com.boostcamp.dailyfilm.presentation.uploadfilm.UploadFilmActivity +import com.boostcamp.dailyfilm.presentation.uploadfilm.UploadFilmComposeActivity import com.boostcamp.dailyfilm.presentation.uploadfilm.model.DateAndVideoModel import com.gowtham.library.utils.CompressOption import com.gowtham.library.utils.TrimType @@ -100,7 +101,7 @@ class TrimVideoActivity : BaseActivity(R.layout.activi private fun moveToUpload(trimAndVideoModel: DateAndVideoModel, startTime: Long) { startActivity( - Intent(this, UploadFilmActivity::class.java).apply { + Intent(this, UploadFilmComposeActivity::class.java).apply { putExtra(DATE_VIDEO_ITEM, trimAndVideoModel) putExtra(KEY_CALENDAR_INDEX, viewModel.calendarIndex) putExtra(KEY_INFO_ITEM, viewModel.infoItem) diff --git a/app/src/main/java/com/boostcamp/dailyfilm/presentation/uploadfilm/UploadFilmComposeActivity.kt b/app/src/main/java/com/boostcamp/dailyfilm/presentation/uploadfilm/UploadFilmComposeActivity.kt new file mode 100644 index 0000000..830ea83 --- /dev/null +++ b/app/src/main/java/com/boostcamp/dailyfilm/presentation/uploadfilm/UploadFilmComposeActivity.kt @@ -0,0 +1,106 @@ +package com.boostcamp.dailyfilm.presentation.uploadfilm + +import android.app.Activity +import android.content.Intent +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.activity.viewModels +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.repeatOnLifecycle +import com.boostcamp.dailyfilm.presentation.calendar.CalendarActivity +import com.boostcamp.dailyfilm.presentation.calendar.DateFragment +import com.boostcamp.dailyfilm.presentation.playfilm.PlayFilmActivity +import com.boostcamp.dailyfilm.presentation.playfilm.PlayFilmFragment +import com.boostcamp.dailyfilm.presentation.playfilm.model.EditState +import com.boostcamp.dailyfilm.presentation.selectvideo.SelectVideoActivity +import com.boostcamp.dailyfilm.presentation.trimvideo.TrimVideoActivity +import com.boostcamp.dailyfilm.presentation.ui.theme.DailyFilmTheme +import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.launch +import java.io.File + +@AndroidEntryPoint +class UploadFilmComposeActivity : ComponentActivity() { + + private val viewModel by viewModels() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + subscribeUiState() + + setContent { + DailyFilmTheme { + UploadFilmScreen(viewModel = viewModel) + } + } + } + + private fun subscribeUiState() { + lifecycleScope.launch { + repeatOnLifecycle(Lifecycle.State.STARTED) { + viewModel.uploadUiState.collect { uiState -> + when (uiState) { + is UploadUiState.Canceled -> { + if (viewModel.beforeItem != null) { + // 업로드 안 한 영상은 로컬에서도 삭제 + deleteLocalFile(viewModel.infoItem?.uri?.path) + + // 돌아가기 + startActivity( + Intent( + this@UploadFilmComposeActivity, + TrimVideoActivity::class.java + ).apply { + putExtra(CalendarActivity.KEY_EDIT_STATE, viewModel.editState.value) + putExtra(SelectVideoActivity.DATE_VIDEO_ITEM, viewModel.beforeItem) + putExtra(PlayFilmFragment.KEY_DATE_MODEL, viewModel.dateModel) + putExtra(DateFragment.KEY_CALENDAR_INDEX, viewModel.calendarIndex) + } + ) + } + finish() + } + + is UploadUiState.UploadSuccess -> { + when (viewModel.editState.value) { + EditState.EDIT_CONTENT -> { + setResult( + Activity.RESULT_OK, + Intent( + this@UploadFilmComposeActivity, + PlayFilmActivity::class.java + ).apply { + putExtra(PlayFilmFragment.KET_EDIT_TEXT, uiState.dateModel.text) + } + ) + } + else -> { + setResult( + Activity.RESULT_OK, + Intent( + this@UploadFilmComposeActivity, + CalendarActivity::class.java + ).apply { + putExtra(DateFragment.KEY_CALENDAR_INDEX, viewModel.calendarIndex) + putExtra(PlayFilmFragment.KEY_DATE_MODEL, uiState.dateModel) + } + ) + } + } + finish() + } + + else -> {} + } + } + } + } + } + + private fun deleteLocalFile(filePath: String?) { + filePath?.let { File(it).delete() } + } + +} \ No newline at end of file