From 868c704ecadf9c7d513914ed944ab41422926ad1 Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Sat, 28 Oct 2023 14:21:20 +0900 Subject: [PATCH 01/25] :lipstick: Setup basic structure for symbol selection screen --- .../symbolselection/SymbolSelectionScreen.kt | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSelectionScreen.kt diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSelectionScreen.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSelectionScreen.kt new file mode 100644 index 00000000..9b1ad9f2 --- /dev/null +++ b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSelectionScreen.kt @@ -0,0 +1,52 @@ +package com.example.speechbuddy.compose.symbolselection + +import android.annotation.SuppressLint +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.example.speechbuddy.compose.utils.TopAppBarUi +import com.example.speechbuddy.ui.SpeechBuddyTheme + +@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun SymbolSelectionScreen( + modifier: Modifier = Modifier, + onBackClick: () -> Unit +) { + Surface(modifier = modifier.fillMaxSize()) { + Scaffold( + topBar = { TopAppBarUi(onBackClick = onBackClick) } + ) { + Column( + modifier = Modifier + .padding(24.dp) + .fillMaxSize(), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text("hello") + + // TODO + } + } + } +} + +@Preview +@Composable +fun SymbolSelectionScreenPreview() { + SpeechBuddyTheme { + SymbolSelectionScreen(onBackClick = {}) + } +} \ No newline at end of file From 82c255009bc3023caead2b1c2c5bd689d8141279 Mon Sep 17 00:00:00 2001 From: JH Date: Sat, 28 Oct 2023 18:36:44 +0900 Subject: [PATCH 02/25] :lipstick: SymbolSearchBox and Symbol implement --- .../compose/symbolselection/Symbol.kt | 96 +++++++++++++++++++ .../symbolselection/SymbolSearchBox.kt | 71 ++++++++++++++ .../symbolselection/SymbolSelectedBox.kt | 51 ++++++++++ 3 files changed, 218 insertions(+) create mode 100644 frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/Symbol.kt create mode 100644 frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSearchBox.kt create mode 100644 frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSelectedBox.kt diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/Symbol.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/Symbol.kt new file mode 100644 index 00000000..207bbc39 --- /dev/null +++ b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/Symbol.kt @@ -0,0 +1,96 @@ +package com.example.speechbuddy.compose.symbolselection + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.Image + +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.DateRange +import androidx.compose.material.icons.filled.FavoriteBorder +import androidx.compose.material.icons.filled.Star +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedCard +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.ColorFilter +import androidx.compose.ui.graphics.ColorMatrix +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.example.speechbuddy.R +import com.example.speechbuddy.ui.SpeechBuddyTheme + +@Composable +fun Symbol( + +) { + OutlinedCard( + modifier = Modifier + .size(width = 140.dp, height = 140.dp), + shape = RoundedCornerShape(10.dp), + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.primaryContainer, + ), + border = BorderStroke(1.dp, MaterialTheme.colorScheme.onPrimaryContainer), + + ) { + Image( + painter = painterResource(id = R.drawable.fav_star), + modifier = Modifier + .padding(start=4.dp, top = 4.dp) + .align(Alignment.Start) + .size(16.dp), + contentDescription = "favorite star", + colorFilter = ColorFilter.tint(Color.Red) + ) + + OutlinedCard( + modifier = Modifier + .align(Alignment.CenterHorizontally) + .size(width = 96.dp, height = 96.dp), + shape = RoundedCornerShape(10.dp), + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.background + ), + border = BorderStroke(1.dp, MaterialTheme.colorScheme.onPrimaryContainer), + ){ + Image( + modifier = Modifier + .align(Alignment.CenterHorizontally) + .size(96.dp), + imageVector = Icons.Default.DateRange, + contentDescription ="symbol image", + ) + } + + Text( + text = "Outlined", + modifier = Modifier + .align(Alignment.CenterHorizontally), + color = MaterialTheme.colorScheme.onPrimaryContainer, + style = MaterialTheme.typography.bodyLarge + ) + + + } +} + + +@Preview(showBackground = true) +@Composable +fun SymbolPreview() { + SpeechBuddyTheme { + Symbol( + + ) + } +} \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSearchBox.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSearchBox.kt new file mode 100644 index 00000000..2734dbdc --- /dev/null +++ b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSearchBox.kt @@ -0,0 +1,71 @@ +package com.example.speechbuddy.compose.symbolselection + +import androidx.compose.foundation.layout.defaultMinSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Search +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.TextFieldDefaults +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.example.speechbuddy.ui.SpeechBuddyTheme + +/** + * Custom UI designed for SymbolSearchBox + * + * @param value the input text to be shown in the text field + * @param onValueChange the callback that is triggered when the input service updates the text. An updated text comes as a parameter of the callback + * @param modifier the Modifier to be applied to this text field + * @param isEnabled indicates if the text in the text field is modifiable + */ + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun SymbolSearchBox( + value: String, + onValueChange: (String) -> Unit, + modifier: Modifier = Modifier, + isEnabled: Boolean = true +) { + OutlinedTextField( + value = value, + onValueChange = onValueChange, + modifier = modifier + .fillMaxWidth() + .defaultMinSize(minHeight = 48.dp), + enabled = isEnabled, + textStyle = MaterialTheme.typography.bodyMedium, + trailingIcon = { + Icon( + imageVector = Icons.Default.Search, + contentDescription = "Find corresponding words" + ) + }, + singleLine = true, + shape = RoundedCornerShape(10.dp), + colors = TextFieldDefaults.outlinedTextFieldColors( + textColor = MaterialTheme.colorScheme.onSurface, + containerColor = MaterialTheme.colorScheme.surface, + focusedBorderColor = MaterialTheme.colorScheme.primary, + unfocusedBorderColor = MaterialTheme.colorScheme.primary + ) + ) +} + + +@Preview(showBackground = true) +@Composable +fun SymbolSearchBoxPreview() { + SpeechBuddyTheme { + SymbolSearchBox( + value = "검색어를 입력하세요", + onValueChange = {}, + ) + } +} \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSelectedBox.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSelectedBox.kt new file mode 100644 index 00000000..4a3fc430 --- /dev/null +++ b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSelectedBox.kt @@ -0,0 +1,51 @@ +package com.example.speechbuddy.compose.symbolselection + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.defaultMinSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Search +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.TextFieldDefaults +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.example.speechbuddy.ui.SpeechBuddyTheme + + +/** + * Custom UI designed for SymbolSearchBox + * + * @param value the input text to be shown in the text field + * @param onValueChange the callback that is triggered when the input service updates the text. An updated text comes as a parameter of the callback + * @param modifier the Modifier to be applied to this text field + * @param isEnabled indicates if the text in the text field is modifiable + */ +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun SymbolSelectedBox( + value: String, + onValueChange: (String) -> Unit, + modifier: Modifier = Modifier, + isEnabled: Boolean = true +) { + +} + + +@Preview(showBackground = true) +@Composable +fun SymbolSelectedBoxPreview() { + SpeechBuddyTheme { + SymbolSelectedBox( + value = "검색어를 입력하세요", + onValueChange = {}, + ) + } +} \ No newline at end of file From 93b7ecc19061b5474c07d70b20aa10fe7977907c Mon Sep 17 00:00:00 2001 From: JH Date: Sat, 28 Oct 2023 19:53:12 +0900 Subject: [PATCH 03/25] :truck: Add drawables fav_star, fav_star_selected --- .../compose/symbolselection/Symbol.kt | 1 - frontend/app/src/main/res/drawable/fav_star.png | Bin 0 -> 1336 bytes .../src/main/res/drawable/fav_star_selected.png | Bin 0 -> 1002 bytes 3 files changed, 1 deletion(-) create mode 100644 frontend/app/src/main/res/drawable/fav_star.png create mode 100644 frontend/app/src/main/res/drawable/fav_star_selected.png diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/Symbol.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/Symbol.kt index 207bbc39..90e4fe00 100644 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/Symbol.kt +++ b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/Symbol.kt @@ -50,7 +50,6 @@ fun Symbol( .align(Alignment.Start) .size(16.dp), contentDescription = "favorite star", - colorFilter = ColorFilter.tint(Color.Red) ) OutlinedCard( diff --git a/frontend/app/src/main/res/drawable/fav_star.png b/frontend/app/src/main/res/drawable/fav_star.png new file mode 100644 index 0000000000000000000000000000000000000000..b58c87e02b1b06e6c32dc166805b0e6bcc063ba2 GIT binary patch literal 1336 zcmV-81;_e{P)lJ$Y__({P5JIRQQp$V${{;DAzUCB^0dT&>g!UtfSAMEj_d z^%p3qb6<5dq&zzI^Q(~`${Y`3d$Nxw7 z%tQP+VsGw|^eCK#_%p=*q)+g-wK~>(5YjPcR}zKiDFOJ#L2*e+j!xy6vWEAD}Pjvl?x~Nid0Mx@{}e zn`|~85WHy2Cl?+S9)j58J{jWgWgp89VmrpzZ6_x;cM>A#)g!p(xIZb`$<=RgiytmQ zTkJ8~Rz2YRi%@o36A+^sWhEAS43_w3rhaLU7eV!Ju}Dx_?0;VbiBM4Jm}3%Bp%Rqj0(Vw0A_9QLMq)V7ONC2IhCR?uwr_}Od0v=93fFDMHjY1FL1 zwb5}cL__xVUTv}lP^-70rRZ3Yeciy$Ohzls#>pu7(~tO;u1fXRX4J>PHsNT_1{v0| z1HOMMpiM_VhM;ly{;I&JT;8oT8=yPfss?R3`Z=*`4QtyrydBoi6J4_pXxuoM%#PGM zYG=G@)KC0OH87i>j-WZg_ba?R{0!(&XtYr;sp@lNt{-gE_jyREo+P0~zR{LS28tl` zqg{rzuX4N5y?*Xoqm3}I$qP*qP$k~pPJ@vaGY=dQP2x!do6yQ619h@+Fp=iaOL#=E zXfK2Rmj;$P=nH~BX;k^BM;mn{s!9VZ!-f^;*SF~mwq2cpWmKx-^i}90pw6yF5|)sk zfiY`rBx^bgOBvP(Uf71?{$f}g*<{QzZU!0WrACC2q>I7>Zg&9eQY9E|^%z)5h;E25 zb>Zksg3(rofh7&Ahi1fRJAm7x5W9b16At#`_HGW!usR6GqPDo5SVZo?8$ztOotuL) ztccFJ;I-&iI4J*jVihYF%z%wmz|W=vyC^so0B#DFVU?SYl%vWAZc*SAm~03c)@wz5 zD#+1R(!lyw3Ak1v7tF|)?xpLZD;JI}wS9?E<%83LL>zNZ4tX}LNvuLHAPZ8)z*>ei usa41Ydy}Pzf$h)0m(znQ0YzboZ2SX2O6HV+iJam90000%CLW<9WP|Gn*`OUE8(cR?H@Fcp0wdfAjL@?vNvUiTV@xe#fA4*N zNMeMrEcrv^;ej!PP)`7`r^gFCAw~VJd7{S)Jh0s=1!DK1*={y!Lq9LL0U_j}ci;z9 z^^tyFa05c@{#_lYXCeK(UnTM2 zM!#P$KtKCh>bL<*Nizm(@}MjwjT@wNu@b*Se^;OZTeYXoaYe3FNSrKCZ4l`am7U-c^;FFORzz6EdFR$wbQf4|PN^b1Z3QCJ)NIN}4ΠGnyf7A2aEx<0>&*l9k6AUY*lZAK` zPkM$ti!IK)`pt6jQHY9lcaAOWk$7%uQ*xkDNHnlB7U~yV#HCOts5(WZ5mmRojVa4N z&9=Acj5dDSS|8DNys_Q2=$jn0j#_644zBNJcOrdKJb7;bHSAuAH@|`2;a${dpIB!% zfI3K`wZ488lxw4u-o=BqJiCd6x}{s=Y?*gUNMuM8shOr7_rkzx#%*8!r=wywXcj3gjWy)NvScotM zfmB$V5HTtUq{3P<^rB_TT&zHdm?j9M0+s|8Q3V#!CB zp-fimg#b9NgVnB~cCrL+^$g>ga1{w8O4H<0TthSF=RH-2n zi)*UpA-2xQQdo#7AmGM-xb4E(9aAD>DJ(!70pUE>5fDxF<|Zse5D>a>rQ^B~Bdl2o z3v&bn8m_*W9oC$Lg+KwJ84Fim1V0hvBrL!*0bx?O`U1zC=tw@o0y@QFpg|pSr;u>< z#l*1YAuMf3s(VwNx1rA7}iOJ1${SPIEJe)a7&2SK#xzs Yf8x)1KxV2(egFUf07*qoM6N<$g0X73d;kCd literal 0 HcmV?d00001 From 6c1566cce7c0992c877b089ad3cf42f52d2fe6bb Mon Sep 17 00:00:00 2001 From: JH Date: Sat, 28 Oct 2023 21:25:01 +0900 Subject: [PATCH 04/25] :lipstick: Symbol modified, fav_star_selected img file changed --- .../compose/symbolselection/Symbol.kt | 59 ++++++++++-------- .../main/res/drawable/fav_star_selected.png | Bin 1002 -> 1440 bytes 2 files changed, 32 insertions(+), 27 deletions(-) diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/Symbol.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/Symbol.kt index 90e4fe00..40c25982 100644 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/Symbol.kt +++ b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/Symbol.kt @@ -2,14 +2,14 @@ package com.example.speechbuddy.compose.symbolselection import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.Image - +import androidx.compose.foundation.layout.Box +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.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.DateRange -import androidx.compose.material.icons.filled.FavoriteBorder -import androidx.compose.material.icons.filled.Star import androidx.compose.material3.CardDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedCard @@ -17,11 +17,6 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.alpha -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.ColorFilter -import androidx.compose.ui.graphics.ColorMatrix -import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview @@ -31,7 +26,8 @@ import com.example.speechbuddy.ui.SpeechBuddyTheme @Composable fun Symbol( - + modifier: Modifier = Modifier, + isFavorite: Boolean = false ) { OutlinedCard( modifier = Modifier @@ -39,14 +35,17 @@ fun Symbol( shape = RoundedCornerShape(10.dp), colors = CardDefaults.cardColors( containerColor = MaterialTheme.colorScheme.primaryContainer, - ), + ), border = BorderStroke(1.dp, MaterialTheme.colorScheme.onPrimaryContainer), - ) { Image( - painter = painterResource(id = R.drawable.fav_star), + painter = if (isFavorite) { + painterResource(id = R.drawable.fav_star_selected) + } else { + painterResource(id = R.drawable.fav_star) + }, modifier = Modifier - .padding(start=4.dp, top = 4.dp) + .padding(start = 4.dp, top = 4.dp) .align(Alignment.Start) .size(16.dp), contentDescription = "favorite star", @@ -55,31 +54,37 @@ fun Symbol( OutlinedCard( modifier = Modifier .align(Alignment.CenterHorizontally) - .size(width = 96.dp, height = 96.dp), + .size(width = 100.dp, height = 80.dp), shape = RoundedCornerShape(10.dp), colors = CardDefaults.cardColors( containerColor = MaterialTheme.colorScheme.background ), border = BorderStroke(1.dp, MaterialTheme.colorScheme.onPrimaryContainer), - ){ + ) { Image( modifier = Modifier .align(Alignment.CenterHorizontally) - .size(96.dp), + .size(80.dp), imageVector = Icons.Default.DateRange, - contentDescription ="symbol image", - ) + contentDescription = "symbol image", + ) } - Text( - text = "Outlined", + Box( modifier = Modifier - .align(Alignment.CenterHorizontally), - color = MaterialTheme.colorScheme.onPrimaryContainer, - style = MaterialTheme.typography.bodyLarge - ) - - + .padding(horizontal = 2.dp) + .fillMaxSize(), + contentAlignment = Alignment.Center + ) { + Text( + text = "119에 전화를 걸어주시기 바랍니다. ", + modifier = Modifier + .fillMaxWidth(), + color = MaterialTheme.colorScheme.onPrimaryContainer, + style = MaterialTheme.typography.bodySmall, + textAlign = TextAlign.Center + ) + } } } @@ -89,7 +94,7 @@ fun Symbol( fun SymbolPreview() { SpeechBuddyTheme { Symbol( - + isFavorite = true ) } } \ No newline at end of file diff --git a/frontend/app/src/main/res/drawable/fav_star_selected.png b/frontend/app/src/main/res/drawable/fav_star_selected.png index 3b34032710ddff6fe5df2c2b96aa9f1f4f9f4dd5..27bf47defa68854dd7a222d8ba61a56e1da45e51 100644 GIT binary patch delta 1423 zcmV;A1#tT62cQd(BYy>FNkl&dAt} z2$2Iw7bHlR8IdEz0g$=CvKLt73#`NikcRo)V~<~z+gt?eXlI3B+f_opK|3l$dHBt$gB-MzV(>Ss4%$LHC`N%*ttw~-#aOpA2j$StvGM|| z!mIC-k3I5whkvr};f9q#JEi5-kJ$bCi@q*kA2+Klv_onhKf>-!x_ zc65t!(9UT2>PzoH^3B)!zThU4$@kEXXnFhB(Sclr^1h(J4XT26M9s6$kIrj|B$J!l z(&W%iX!+xJ?Lc0W?F4tYA(hY$sA-Z%ACXnaKL2-OSbsVA|1fw0zw%gBmXmMc)LZ3NO$gdj!LL%*?A;b`_pc`L=zO73L!9ebJPz?TtE0M4- z_Q}3E2FK!<99!CR0wqRf>B0S47iQ0w-};GgLVs`HOmoUy&=x)@+Qx@QTWPbL#{gSQ zQ~}+Y;_*Xopfo&HUYGm*G^0ScU`7to#d!jpnDHZ@-Tr0pJnb3coibxhkFzKf*M zsW4&_&bekdvmA^Wx?2oQ1==L-3{b(4X{XA;=tO416cPz-7_sr@?!#ebF_rUtCSKTWI53=GY$^KEBhYs}U26oPR(K%S>|e=OVIg$!XZNC|C-!d^noQ7f5^yJ=G(@Yv-I7kdfX1QEqRsDhSyj&(AgHRuEZ56cz-UA zefwn+7%Bp=vJ*=}k#EMdEot$5DUEKClWl0iRkjZ?6xN1+KuYcm+!a5T$wTXzREGMvio3IM-oYn1QjeGOn`lL zk6jLt64^+SEGz^I2qP#leB5#vxf%l`S6CPO z84^+fZD0(BQHImSlSKvHe~bbNsf0E##Mp4PihWkl%4p8(t3_G!_}%B deh!oMA1d|tD)WxcrT_o{00>D%PDHLkV1n6cwzdEO delta 981 zcmV;`11kKW3+e}uBYy+2Nkl%CLW<9WP|Gn*`OUE8(cR? zH@Fcp0wdfAjL@?vNvUiTV@xe#fA4*NNMeMrEcrv^;ej!PP)`7`r^gFCAw~VJd7{S) zJh0s=1!DK1*={y!Lq9LL0U_j}ci;z9^^tyFa05c@{#_lYXMZ96ykG?1X5WP+nfOCH z>})ttAEVzZuwalpOqN-A8(6v+j_WBz{YJlEFhD>1TI#p~OGz^ZYx1BhC5;=Tbg>e@ zLw{GG0b8}F&T_IO6B814e+@^uSxTBAMoSk5@i%mwY%x~4I9Za(7krY3g{7oHc$F>= zieL3B9WOfs&VRlO^G+s{N*5P%E@^_2hsiu=VMyuXVwTB7%K8s=L@;wKX=Wx5%DhUN zIi-t>RV9DZ^V}`KF4@oJ{Us9&E2Wc#coa{1hCGWc&b<1~a`91!igkC6E$oqaZfa9< zpixLPurn6w7hJ@pP$#H5MWqo{x4w-j%RkMwx9N;Fet+6pAJKNavE8-kn;f)`T4xCk zuJ2}dB7IUkd2awU>|TjCzk%N2UDRlwSZ6nYI$8!O^da=+la%Tic!eByw%TWhYZxQ2 zl}zRpra?p>p|8F&tiQA1{;) zz5B|vp?}Z|=BqJiCd6x}{s=Y?*gUNMuM8s zhOr7_rkzx#%*8!r=wywXcj3gjWy)NvScotMfmB$V5HTtUq{3P<^rB_TT&zHdm?j9M z0+s|8Q3V#!CBp?^$P>xBR~u7lOCp?0zaZuJb~nQ#>e zBudldQd~nb=I29si}4(|hBi1@rg111`8OZ|?|m`vzYgf7e`+)oP>oy0ihWSS6>7_ z5#%H+z%&72Qn>m8$DHU$KEeVz#bTgA9df6TaP`H+u;w8wcnSzn!qpePVa-BVxFH}c z60W}Jdv~1C!9rMY3JCf*hYo Date: Sat, 28 Oct 2023 21:34:49 +0900 Subject: [PATCH 05/25] :memo: annotation update on Symbol --- .../speechbuddy/compose/symbolselection/Symbol.kt | 11 ++++++++++- .../compose/symbolselection/SymbolSelectionScreen.kt | 1 + 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/Symbol.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/Symbol.kt index 40c25982..375c55b8 100644 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/Symbol.kt +++ b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/Symbol.kt @@ -24,9 +24,17 @@ import androidx.compose.ui.unit.dp import com.example.speechbuddy.R import com.example.speechbuddy.ui.SpeechBuddyTheme +/** + * Custom UI designed for Symbol + * + * @param onValueChange the callback that is triggered when the input service updates the text. An updated text comes as a parameter of the callback + * @param modifier the Modifier to be applied to this text field + * @param isFavorite indicates if the symbol is favorite + */ @Composable fun Symbol( modifier: Modifier = Modifier, + onValueChange: (String) -> Unit, isFavorite: Boolean = false ) { OutlinedCard( @@ -94,7 +102,8 @@ fun Symbol( fun SymbolPreview() { SpeechBuddyTheme { Symbol( - isFavorite = true + isFavorite = true, + onValueChange = {}, ) } } \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSelectionScreen.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSelectionScreen.kt index 9b1ad9f2..a9fb36bd 100644 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSelectionScreen.kt +++ b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSelectionScreen.kt @@ -38,6 +38,7 @@ fun SymbolSelectionScreen( Text("hello") // TODO + } } } From f491b52cdb3e9f8217766652600a074841275483 Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Sat, 28 Oct 2023 21:48:25 +0900 Subject: [PATCH 06/25] :lipstick: Refactor symbol search box --- .../symbolselection/SymbolSearchBox.kt | 19 +++++++++---------- frontend/app/src/main/res/values/strings.xml | 1 + 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSearchBox.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSearchBox.kt index 2734dbdc..c6d37bd6 100644 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSearchBox.kt +++ b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSearchBox.kt @@ -9,11 +9,14 @@ import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.Text import androidx.compose.material3.TextFieldDefaults import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import com.example.speechbuddy.R import com.example.speechbuddy.ui.SpeechBuddyTheme /** @@ -22,16 +25,13 @@ import com.example.speechbuddy.ui.SpeechBuddyTheme * @param value the input text to be shown in the text field * @param onValueChange the callback that is triggered when the input service updates the text. An updated text comes as a parameter of the callback * @param modifier the Modifier to be applied to this text field - * @param isEnabled indicates if the text in the text field is modifiable */ - @OptIn(ExperimentalMaterial3Api::class) @Composable fun SymbolSearchBox( value: String, onValueChange: (String) -> Unit, - modifier: Modifier = Modifier, - isEnabled: Boolean = true + modifier: Modifier = Modifier ) { OutlinedTextField( value = value, @@ -39,12 +39,12 @@ fun SymbolSearchBox( modifier = modifier .fillMaxWidth() .defaultMinSize(minHeight = 48.dp), - enabled = isEnabled, textStyle = MaterialTheme.typography.bodyMedium, + placeholder = { Text(text = stringResource(id = R.string.search_box_placeholder)) }, trailingIcon = { Icon( imageVector = Icons.Default.Search, - contentDescription = "Find corresponding words" + contentDescription = stringResource(id = R.string.search_box_placeholder) ) }, singleLine = true, @@ -52,19 +52,18 @@ fun SymbolSearchBox( colors = TextFieldDefaults.outlinedTextFieldColors( textColor = MaterialTheme.colorScheme.onSurface, containerColor = MaterialTheme.colorScheme.surface, - focusedBorderColor = MaterialTheme.colorScheme.primary, - unfocusedBorderColor = MaterialTheme.colorScheme.primary + focusedBorderColor = MaterialTheme.colorScheme.tertiary, + unfocusedBorderColor = MaterialTheme.colorScheme.outline ) ) } - @Preview(showBackground = true) @Composable fun SymbolSearchBoxPreview() { SpeechBuddyTheme { SymbolSearchBox( - value = "검색어를 입력하세요", + value = "검색어", onValueChange = {}, ) } diff --git a/frontend/app/src/main/res/values/strings.xml b/frontend/app/src/main/res/values/strings.xml index 87c870a1..aff1826f 100644 --- a/frontend/app/src/main/res/values/strings.xml +++ b/frontend/app/src/main/res/values/strings.xml @@ -38,4 +38,5 @@ 닉네임을 입력해주세요 로그인 오류 회원가입 오류 + 검색어를 입력하세요 \ No newline at end of file From 532ebcc3aea5589ddc9daf70c67e63824e11241d Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Sat, 28 Oct 2023 22:03:27 +0900 Subject: [PATCH 07/25] :sparkles: Declare data classes for symbol and category --- .../example/speechbuddy/domain/models/Category.kt | 11 +++++++++++ .../example/speechbuddy/domain/models/Symbol.kt | 14 ++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 frontend/app/src/main/java/com/example/speechbuddy/domain/models/Category.kt create mode 100644 frontend/app/src/main/java/com/example/speechbuddy/domain/models/Symbol.kt diff --git a/frontend/app/src/main/java/com/example/speechbuddy/domain/models/Category.kt b/frontend/app/src/main/java/com/example/speechbuddy/domain/models/Category.kt new file mode 100644 index 00000000..1b6cbb11 --- /dev/null +++ b/frontend/app/src/main/java/com/example/speechbuddy/domain/models/Category.kt @@ -0,0 +1,11 @@ +package com.example.speechbuddy.domain.models + +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +@Parcelize +data class Category( + val id: Int, + val text: String, + val imageResId: Int +): Parcelable \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/domain/models/Symbol.kt b/frontend/app/src/main/java/com/example/speechbuddy/domain/models/Symbol.kt new file mode 100644 index 00000000..33c95c9c --- /dev/null +++ b/frontend/app/src/main/java/com/example/speechbuddy/domain/models/Symbol.kt @@ -0,0 +1,14 @@ +package com.example.speechbuddy.domain.models + +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +@Parcelize +data class Symbol( + val id: Int, + val text: String, + val imageResId: Int, + val category: Category, + val isFavorite: Boolean, + val isMine: Boolean +): Parcelable \ No newline at end of file From 9e7986f59f8df62fb05d642151a4383665860484 Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Sat, 28 Oct 2023 22:32:03 +0900 Subject: [PATCH 08/25] :lipstick: Enhance symbol ui --- .../Symbol.kt => utils/SymbolUi.kt} | 96 +++++++++++-------- .../example/speechbuddy/utils/Constants.kt | 1 + frontend/app/src/main/res/values/strings.xml | 1 + 3 files changed, 59 insertions(+), 39 deletions(-) rename frontend/app/src/main/java/com/example/speechbuddy/compose/{symbolselection/Symbol.kt => utils/SymbolUi.kt} (50%) diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/Symbol.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/SymbolUi.kt similarity index 50% rename from frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/Symbol.kt rename to frontend/app/src/main/java/com/example/speechbuddy/compose/utils/SymbolUi.kt index 375c55b8..97fe12c2 100644 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/Symbol.kt +++ b/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/SymbolUi.kt @@ -1,16 +1,15 @@ -package com.example.speechbuddy.compose.symbolselection +package com.example.speechbuddy.compose.utils import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Box 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.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.DateRange import androidx.compose.material3.CardDefaults +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedCard import androidx.compose.material3.Text @@ -18,46 +17,56 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.example.speechbuddy.R +import com.example.speechbuddy.domain.models.Category +import com.example.speechbuddy.domain.models.Symbol import com.example.speechbuddy.ui.SpeechBuddyTheme +import com.example.speechbuddy.utils.Constants.Companion.MAXIMUM_LINES_FOR_SYMBOL_TEXT /** * Custom UI designed for Symbol * - * @param onValueChange the callback that is triggered when the input service updates the text. An updated text comes as a parameter of the callback + * @param symbol data class Symbol to be passed to the UI * @param modifier the Modifier to be applied to this text field - * @param isFavorite indicates if the symbol is favorite + * @param onSelect called when this Symbol is clicked + * @param onToggle called when the upper left start of this Symbol is clicked */ +@ExperimentalMaterial3Api @Composable -fun Symbol( +fun SymbolUi( + symbol: Symbol, modifier: Modifier = Modifier, - onValueChange: (String) -> Unit, - isFavorite: Boolean = false + onSelect: () -> Unit, + onToggle: () -> Unit ) { OutlinedCard( - modifier = Modifier - .size(width = 140.dp, height = 140.dp), + onClick = onSelect, + modifier = modifier.size(140.dp), shape = RoundedCornerShape(10.dp), colors = CardDefaults.cardColors( containerColor = MaterialTheme.colorScheme.primaryContainer, + contentColor = MaterialTheme.colorScheme.onPrimaryContainer ), - border = BorderStroke(1.dp, MaterialTheme.colorScheme.onPrimaryContainer), + border = BorderStroke(1.dp, MaterialTheme.colorScheme.onPrimaryContainer) ) { - Image( - painter = if (isFavorite) { - painterResource(id = R.drawable.fav_star_selected) - } else { - painterResource(id = R.drawable.fav_star) - }, + IconButton( + onClick = onToggle, modifier = Modifier .padding(start = 4.dp, top = 4.dp) - .align(Alignment.Start) - .size(16.dp), - contentDescription = "favorite star", - ) + .size(16.dp) + ) { + Image( + painter = when (symbol.isFavorite) { + true -> painterResource(id = R.drawable.fav_star_selected) + false -> painterResource(id = R.drawable.fav_star) + }, + contentDescription = stringResource(id = R.string.favorite) + ) + } OutlinedCard( modifier = Modifier @@ -65,45 +74,54 @@ fun Symbol( .size(width = 100.dp, height = 80.dp), shape = RoundedCornerShape(10.dp), colors = CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.background + containerColor = MaterialTheme.colorScheme.background, + contentColor = MaterialTheme.colorScheme.onBackground ), - border = BorderStroke(1.dp, MaterialTheme.colorScheme.onPrimaryContainer), + border = BorderStroke(1.dp, MaterialTheme.colorScheme.onBackground) ) { Image( + painter = painterResource(id = symbol.imageResId), + contentDescription = symbol.text, modifier = Modifier .align(Alignment.CenterHorizontally) - .size(80.dp), - imageVector = Icons.Default.DateRange, - contentDescription = "symbol image", + .size(80.dp) ) } Box( modifier = Modifier - .padding(horizontal = 2.dp) + .padding(horizontal = 10.dp) .fillMaxSize(), contentAlignment = Alignment.Center ) { Text( - text = "119에 전화를 걸어주시기 바랍니다. ", - modifier = Modifier - .fillMaxWidth(), - color = MaterialTheme.colorScheme.onPrimaryContainer, - style = MaterialTheme.typography.bodySmall, - textAlign = TextAlign.Center + text = symbol.text, + textAlign = TextAlign.Center, + maxLines = MAXIMUM_LINES_FOR_SYMBOL_TEXT, + style = MaterialTheme.typography.bodySmall ) } } } - @Preview(showBackground = true) +@ExperimentalMaterial3Api @Composable fun SymbolPreview() { + val previewSymbol = Symbol( + id = 0, + text = "앵무새", + imageResId = R.drawable.top_app_bar_ic, + category = Category( + id = 0, + text = "동물", + imageResId = R.drawable.top_app_bar_ic + ), + isFavorite = true, + isMine = false + ) + SpeechBuddyTheme { - Symbol( - isFavorite = true, - onValueChange = {}, - ) + SymbolUi(symbol = previewSymbol, onSelect = {}, onToggle = {}) } } \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/utils/Constants.kt b/frontend/app/src/main/java/com/example/speechbuddy/utils/Constants.kt index a81f6621..8ed2752c 100644 --- a/frontend/app/src/main/java/com/example/speechbuddy/utils/Constants.kt +++ b/frontend/app/src/main/java/com/example/speechbuddy/utils/Constants.kt @@ -6,5 +6,6 @@ class Constants { const val MINIMUM_PASSWORD_LENGTH = 8 const val MAXIMUM_NICKNAME_LENGTH = 15 const val CODE_LENGTH = 6 + const val MAXIMUM_LINES_FOR_SYMBOL_TEXT = 2 } } \ No newline at end of file diff --git a/frontend/app/src/main/res/values/strings.xml b/frontend/app/src/main/res/values/strings.xml index aff1826f..f7621d89 100644 --- a/frontend/app/src/main/res/values/strings.xml +++ b/frontend/app/src/main/res/values/strings.xml @@ -39,4 +39,5 @@ 로그인 오류 회원가입 오류 검색어를 입력하세요 + 즐겨찾기 \ No newline at end of file From cc96f547057859aba04609c0fe01cdfec56c3265 Mon Sep 17 00:00:00 2001 From: JH Date: Sat, 28 Oct 2023 22:55:03 +0900 Subject: [PATCH 09/25] :lipstick: Add CategoryUi --- .../speechbuddy/compose/utils/CategoryUi.kt | 103 ++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 frontend/app/src/main/java/com/example/speechbuddy/compose/utils/CategoryUi.kt diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/CategoryUi.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/CategoryUi.kt new file mode 100644 index 00000000..2c59e212 --- /dev/null +++ b/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/CategoryUi.kt @@ -0,0 +1,103 @@ +package com.example.speechbuddy.compose.utils + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedCard +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.example.speechbuddy.R +import com.example.speechbuddy.domain.models.Category +import com.example.speechbuddy.ui.SpeechBuddyTheme +import com.example.speechbuddy.utils.Constants + +/** + * Custom UI designed for Symbol + * + * @param category data class Category to be passed to the UI + * @param modifier the Modifier to be applied to this text field + * @param onSelect called when this Symbol is clicked + */ +@ExperimentalMaterial3Api +@Composable +fun CategoryUi( + category: Category, + modifier: Modifier = Modifier, + onSelect: () -> Unit, +) { + OutlinedCard( + onClick = onSelect, + modifier = modifier.size(140.dp), + shape = RoundedCornerShape(10.dp), + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.primaryContainer, + contentColor = MaterialTheme.colorScheme.onPrimaryContainer + ), + border = BorderStroke(1.dp, MaterialTheme.colorScheme.onPrimaryContainer) + ) { + Spacer(modifier = Modifier.size(20.dp)) + + OutlinedCard( + modifier = Modifier + .align(Alignment.CenterHorizontally) + .size(width = 100.dp, height = 80.dp), + shape = RoundedCornerShape(10.dp), + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.background, + contentColor = MaterialTheme.colorScheme.onBackground + ), + border = BorderStroke(1.dp, MaterialTheme.colorScheme.onBackground) + ) { + Image( + painter = painterResource(id = category.imageResId), + contentDescription = category.text, + modifier = Modifier + .align(Alignment.CenterHorizontally) + .size(80.dp) + ) + } + + Box( + modifier = Modifier + .padding(horizontal = 10.dp) + .fillMaxSize(), + contentAlignment = Alignment.Center + ) { + Text( + text = category.text, + textAlign = TextAlign.Center, + maxLines = Constants.MAXIMUM_LINES_FOR_SYMBOL_TEXT, + style = MaterialTheme.typography.bodySmall + ) + } + } +} + +@Preview(showBackground = true) +@ExperimentalMaterial3Api +@Composable +fun CategoryPreview() { + val previewCategory = Category( + id = 0, + text = "앵무새", + imageResId = R.drawable.top_app_bar_ic, + ) + + SpeechBuddyTheme { + CategoryUi(category = previewCategory, onSelect = {}) + } +} \ No newline at end of file From 7d6292692db6e96cfb04c0d0836810be6dbf5692 Mon Sep 17 00:00:00 2001 From: JH Date: Sun, 29 Oct 2023 03:49:46 +0900 Subject: [PATCH 10/25] :lipstick: Add SymbolSelectedBox but does not work properly --- .../symbolselection/SymbolSelectedBox.kt | 96 ++++++++++++++++--- 1 file changed, 82 insertions(+), 14 deletions(-) diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSelectedBox.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSelectedBox.kt index 4a3fc430..11f7bced 100644 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSelectedBox.kt +++ b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSelectedBox.kt @@ -1,41 +1,97 @@ package com.example.speechbuddy.compose.symbolselection +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.defaultMinSize +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Search +import androidx.compose.material3.Button +import androidx.compose.material3.CardDefaults import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedTextField -import androidx.compose.material3.TextFieldDefaults +import androidx.compose.material3.OutlinedCard import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import com.example.speechbuddy.R +import com.example.speechbuddy.compose.utils.SymbolUi +import com.example.speechbuddy.domain.models.Category +import com.example.speechbuddy.domain.models.Symbol import com.example.speechbuddy.ui.SpeechBuddyTheme /** * Custom UI designed for SymbolSearchBox * - * @param value the input text to be shown in the text field - * @param onValueChange the callback that is triggered when the input service updates the text. An updated text comes as a parameter of the callback + * @param symbol data class Symbol to be passed to the UI * @param modifier the Modifier to be applied to this text field - * @param isEnabled indicates if the text in the text field is modifiable */ @OptIn(ExperimentalMaterial3Api::class) @Composable fun SymbolSelectedBox( - value: String, - onValueChange: (String) -> Unit, + symbol: Symbol, modifier: Modifier = Modifier, - isEnabled: Boolean = true ) { + OutlinedCard( + modifier = Modifier + .fillMaxWidth() + .height(160.dp), + shape = RoundedCornerShape(10.dp), + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.surface, + contentColor = MaterialTheme.colorScheme.onSurface, + + ), + border = BorderStroke(1.dp, MaterialTheme.colorScheme.onSurface) + + ) { + Row( + modifier = Modifier.fillMaxWidth() + ) { + + LazyRow( + modifier = Modifier + .fillMaxWidth(0.8f) + .height(150.dp) + ) { + items(10) { + SymbolUi( + symbol = symbol, + onSelect = { /*TODO*/ } + ) { + + } + } + + } + + Box( + modifier = Modifier + .fillMaxWidth(0.2f) + .background(Color.Yellow), + + ) { + Button( + modifier = modifier + .fillMaxSize() + .background(Color.Red), + onClick = { /*TODO*/ } + ) { + + } + } + + } + + } + } @@ -43,9 +99,21 @@ fun SymbolSelectedBox( @Composable fun SymbolSelectedBoxPreview() { SpeechBuddyTheme { + val previewSymbol = Symbol( + id = 0, + text = "앵무새", + imageResId = R.drawable.top_app_bar_ic, + category = Category( + id = 0, + text = "동물", + imageResId = R.drawable.top_app_bar_ic + ), + isFavorite = true, + isMine = false + ) SymbolSelectedBox( - value = "검색어를 입력하세요", - onValueChange = {}, + symbol = previewSymbol, + modifier = Modifier ) } } \ No newline at end of file From 128962267a7153d44f05e992398163fc391c7a66 Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Sun, 29 Oct 2023 11:28:19 +0900 Subject: [PATCH 11/25] :memo: Update javadoc for symbol and category ui --- .../com/example/speechbuddy/compose/utils/CategoryUi.kt | 6 +++--- .../java/com/example/speechbuddy/compose/utils/SymbolUi.kt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/CategoryUi.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/CategoryUi.kt index 2c59e212..46d31636 100644 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/CategoryUi.kt +++ b/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/CategoryUi.kt @@ -26,11 +26,11 @@ import com.example.speechbuddy.ui.SpeechBuddyTheme import com.example.speechbuddy.utils.Constants /** - * Custom UI designed for Symbol + * Custom UI designed for Category * * @param category data class Category to be passed to the UI - * @param modifier the Modifier to be applied to this text field - * @param onSelect called when this Symbol is clicked + * @param modifier the Modifier to be applied to this outlined card + * @param onSelect called when this Category is clicked */ @ExperimentalMaterial3Api @Composable diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/SymbolUi.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/SymbolUi.kt index 97fe12c2..ecaddb34 100644 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/SymbolUi.kt +++ b/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/SymbolUi.kt @@ -31,7 +31,7 @@ import com.example.speechbuddy.utils.Constants.Companion.MAXIMUM_LINES_FOR_SYMBO * Custom UI designed for Symbol * * @param symbol data class Symbol to be passed to the UI - * @param modifier the Modifier to be applied to this text field + * @param modifier the Modifier to be applied to this outlined card * @param onSelect called when this Symbol is clicked * @param onToggle called when the upper left start of this Symbol is clicked */ From 15d6d46d25b201200d43113dace29a74e3cbfe34 Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Sun, 29 Oct 2023 20:43:08 +0900 Subject: [PATCH 12/25] :lipstick: Enhance symbol and category UI --- .../speechbuddy/compose/utils/CategoryUi.kt | 88 ++++++------ .../speechbuddy/compose/utils/SymbolUi.kt | 132 ++++++++++-------- .../app/src/main/res/drawable/category_0.png | Bin 0 -> 41416 bytes .../app/src/main/res/drawable/fav_star.png | Bin 1336 -> 0 bytes .../main/res/drawable/fav_star_selected.png | Bin 1440 -> 0 bytes .../app/src/main/res/drawable/symbol_0.png | Bin 0 -> 45603 bytes 6 files changed, 109 insertions(+), 111 deletions(-) create mode 100644 frontend/app/src/main/res/drawable/category_0.png delete mode 100644 frontend/app/src/main/res/drawable/fav_star.png delete mode 100644 frontend/app/src/main/res/drawable/fav_star_selected.png create mode 100644 frontend/app/src/main/res/drawable/symbol_0.png diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/CategoryUi.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/CategoryUi.kt index 46d31636..c687ffb3 100644 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/CategoryUi.kt +++ b/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/CategoryUi.kt @@ -1,21 +1,24 @@ package com.example.speechbuddy.compose.utils -import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.Image +import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedCard import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview @@ -35,66 +38,53 @@ import com.example.speechbuddy.utils.Constants @ExperimentalMaterial3Api @Composable fun CategoryUi( - category: Category, - modifier: Modifier = Modifier, - onSelect: () -> Unit, + category: Category, modifier: Modifier = Modifier, onSelect: () -> Unit ) { - OutlinedCard( + Card( onClick = onSelect, modifier = modifier.size(140.dp), shape = RoundedCornerShape(10.dp), colors = CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.primaryContainer, - contentColor = MaterialTheme.colorScheme.onPrimaryContainer - ), - border = BorderStroke(1.dp, MaterialTheme.colorScheme.onPrimaryContainer) + containerColor = MaterialTheme.colorScheme.background + ) ) { - Spacer(modifier = Modifier.size(20.dp)) + Box { + Column( + modifier = Modifier.fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Image( + painter = painterResource(id = category.imageResId), + contentDescription = category.text, + modifier = Modifier.height(95.dp), + contentScale = ContentScale.FillHeight + ) - OutlinedCard( - modifier = Modifier - .align(Alignment.CenterHorizontally) - .size(width = 100.dp, height = 80.dp), - shape = RoundedCornerShape(10.dp), - colors = CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.background, - contentColor = MaterialTheme.colorScheme.onBackground - ), - border = BorderStroke(1.dp, MaterialTheme.colorScheme.onBackground) - ) { - Image( - painter = painterResource(id = category.imageResId), - contentDescription = category.text, - modifier = Modifier - .align(Alignment.CenterHorizontally) - .size(80.dp) - ) - } - - Box( - modifier = Modifier - .padding(horizontal = 10.dp) - .fillMaxSize(), - contentAlignment = Alignment.Center - ) { - Text( - text = category.text, - textAlign = TextAlign.Center, - maxLines = Constants.MAXIMUM_LINES_FOR_SYMBOL_TEXT, - style = MaterialTheme.typography.bodySmall - ) + Box( + modifier = Modifier + .fillMaxWidth() + .height(45.dp) + .background(color = MaterialTheme.colorScheme.tertiaryContainer) + .padding(horizontal = 10.dp), contentAlignment = Alignment.Center + ) { + Text( + text = category.text, + textAlign = TextAlign.Center, + maxLines = Constants.MAXIMUM_LINES_FOR_SYMBOL_TEXT, + style = MaterialTheme.typography.bodySmall + ) + } + } } } } -@Preview(showBackground = true) +@Preview(showBackground = true, backgroundColor = 0) @ExperimentalMaterial3Api @Composable -fun CategoryPreview() { +fun CategoryUiPreview() { val previewCategory = Category( - id = 0, - text = "앵무새", - imageResId = R.drawable.top_app_bar_ic, + id = 0, text = "인사사회어", imageResId = R.drawable.category_0 ) SpeechBuddyTheme { diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/SymbolUi.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/SymbolUi.kt index ecaddb34..c63baaa9 100644 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/SymbolUi.kt +++ b/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/SymbolUi.kt @@ -1,21 +1,30 @@ package com.example.speechbuddy.compose.utils -import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.Image +import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Favorite +import androidx.compose.material.icons.filled.FavoriteBorder +import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.IconButton +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButtonDefaults +import androidx.compose.material3.IconToggleButton import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedCard import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign @@ -33,7 +42,7 @@ import com.example.speechbuddy.utils.Constants.Companion.MAXIMUM_LINES_FOR_SYMBO * @param symbol data class Symbol to be passed to the UI * @param modifier the Modifier to be applied to this outlined card * @param onSelect called when this Symbol is clicked - * @param onToggle called when the upper left start of this Symbol is clicked + * @param onFavoriteChange called when the upper left icon of this Symbol is clicked */ @ExperimentalMaterial3Api @Composable @@ -41,87 +50,86 @@ fun SymbolUi( symbol: Symbol, modifier: Modifier = Modifier, onSelect: () -> Unit, - onToggle: () -> Unit + onFavoriteChange: () -> Unit ) { - OutlinedCard( + Card( onClick = onSelect, modifier = modifier.size(140.dp), shape = RoundedCornerShape(10.dp), colors = CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.primaryContainer, - contentColor = MaterialTheme.colorScheme.onPrimaryContainer - ), - border = BorderStroke(1.dp, MaterialTheme.colorScheme.onPrimaryContainer) + containerColor = MaterialTheme.colorScheme.background + ) ) { - IconButton( - onClick = onToggle, - modifier = Modifier - .padding(start = 4.dp, top = 4.dp) - .size(16.dp) - ) { - Image( - painter = when (symbol.isFavorite) { - true -> painterResource(id = R.drawable.fav_star_selected) - false -> painterResource(id = R.drawable.fav_star) - }, - contentDescription = stringResource(id = R.string.favorite) - ) - } - - OutlinedCard( - modifier = Modifier - .align(Alignment.CenterHorizontally) - .size(width = 100.dp, height = 80.dp), - shape = RoundedCornerShape(10.dp), - colors = CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.background, - contentColor = MaterialTheme.colorScheme.onBackground - ), - border = BorderStroke(1.dp, MaterialTheme.colorScheme.onBackground) - ) { - Image( - painter = painterResource(id = symbol.imageResId), - contentDescription = symbol.text, + Box(contentAlignment = Alignment.TopEnd) { + IconToggleButton( + checked = symbol.isFavorite, + onCheckedChange = { onFavoriteChange() }, modifier = Modifier - .align(Alignment.CenterHorizontally) - .size(80.dp) - ) - } + .size(24.dp) + .padding(4.dp), + colors = IconButtonDefaults.iconToggleButtonColors( + contentColor = MaterialTheme.colorScheme.onBackground, + checkedContentColor = MaterialTheme.colorScheme.error + ) + ) { + Icon( + imageVector = when (symbol.isFavorite) { + true -> Icons.Default.Favorite + false -> Icons.Default.FavoriteBorder + }, + contentDescription = stringResource(id = R.string.favorite) + ) + } + + Column( + modifier = Modifier.fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Image( + painter = painterResource(id = symbol.imageResId), + contentDescription = symbol.text, + modifier = Modifier.height(95.dp), + contentScale = ContentScale.FillHeight + ) - Box( - modifier = Modifier - .padding(horizontal = 10.dp) - .fillMaxSize(), - contentAlignment = Alignment.Center - ) { - Text( - text = symbol.text, - textAlign = TextAlign.Center, - maxLines = MAXIMUM_LINES_FOR_SYMBOL_TEXT, - style = MaterialTheme.typography.bodySmall - ) + Box( + modifier = Modifier + .fillMaxWidth() + .height(45.dp) + .background(color = MaterialTheme.colorScheme.secondaryContainer) + .padding(horizontal = 10.dp), + contentAlignment = Alignment.Center + ) { + Text( + text = symbol.text, + textAlign = TextAlign.Center, + maxLines = MAXIMUM_LINES_FOR_SYMBOL_TEXT, + style = MaterialTheme.typography.bodySmall + ) + } + } } } } -@Preview(showBackground = true) +@Preview(showBackground = true, backgroundColor = 0) @ExperimentalMaterial3Api @Composable -fun SymbolPreview() { +fun SymbolUiPreview() { val previewSymbol = Symbol( id = 0, - text = "앵무새", - imageResId = R.drawable.top_app_bar_ic, + text = "119에 전화해주세요", + imageResId = R.drawable.symbol_0, category = Category( id = 0, - text = "동물", - imageResId = R.drawable.top_app_bar_ic + text = "인사사회어", + imageResId = R.drawable.category_0 ), isFavorite = true, isMine = false ) SpeechBuddyTheme { - SymbolUi(symbol = previewSymbol, onSelect = {}, onToggle = {}) + SymbolUi(symbol = previewSymbol, onSelect = {}, onFavoriteChange = {}) } } \ No newline at end of file diff --git a/frontend/app/src/main/res/drawable/category_0.png b/frontend/app/src/main/res/drawable/category_0.png new file mode 100644 index 0000000000000000000000000000000000000000..3c22c2b704a41cd939be809d07740d7b88413636 GIT binary patch literal 41416 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 literal 0 HcmV?d00001 diff --git a/frontend/app/src/main/res/drawable/fav_star.png b/frontend/app/src/main/res/drawable/fav_star.png deleted file mode 100644 index b58c87e02b1b06e6c32dc166805b0e6bcc063ba2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1336 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 literal 0 HcmV?d00001 From 411f2aee59e251e3d9f959d7e9aec8446bcd2f98 Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Sun, 29 Oct 2023 21:02:11 +0900 Subject: [PATCH 13/25] :lipstick: Rename symbol selected box to selected symbol ui, enhance UI --- .../symbolselection/SelectedSymbolUi.kt | 125 ++++++++++++++++++ .../symbolselection/SymbolSelectedBox.kt | 119 ----------------- .../speechbuddy/compose/utils/CategoryUi.kt | 1 - .../java/com/example/speechbuddy/ui/Type.kt | 6 +- frontend/app/src/main/res/values/strings.xml | 1 + 5 files changed, 129 insertions(+), 123 deletions(-) create mode 100644 frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SelectedSymbolUi.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSelectedBox.kt diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SelectedSymbolUi.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SelectedSymbolUi.kt new file mode 100644 index 00000000..e2f21e22 --- /dev/null +++ b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SelectedSymbolUi.kt @@ -0,0 +1,125 @@ +package com.example.speechbuddy.compose.symbolselection + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Clear +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.ExperimentalMaterial3Api +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.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.example.speechbuddy.R +import com.example.speechbuddy.domain.models.Category +import com.example.speechbuddy.domain.models.Symbol +import com.example.speechbuddy.ui.SpeechBuddyTheme +import com.example.speechbuddy.utils.Constants + + +/** + * Custom UI designed for SymbolSearchBox + * + * @param symbol data class Symbol to be passed to the UI + * @param modifier the Modifier to be applied to this text field + * @param onDelete called when the upper left icon of this Symbol is clicked + */ +@ExperimentalMaterial3Api +@Composable +fun SelectedSymbolUi( + symbol: Symbol, + modifier: Modifier = Modifier, + onDelete: () -> Unit +) { + Card( + modifier = modifier.size(100.dp), + shape = RoundedCornerShape(10.dp), + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.background + ), + border = BorderStroke(width = 1.dp, color = MaterialTheme.colorScheme.onBackground) + ) { + Box(contentAlignment = Alignment.TopEnd) { + IconButton( + onClick = onDelete, + modifier = Modifier + .size(22.dp) + .padding(5.dp) + ) { + Icon( + imageVector = Icons.Default.Clear, + contentDescription = stringResource(id = R.string.symbol_unselect) + ) + } + + Column( + modifier = Modifier.fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Image( + painter = painterResource(id = symbol.imageResId), + contentDescription = symbol.text, + modifier = Modifier.height(65.dp), + contentScale = ContentScale.FillHeight + ) + + Box( + modifier = Modifier + .fillMaxWidth() + .height(35.dp) + .background(color = MaterialTheme.colorScheme.secondaryContainer) + .padding(horizontal = 8.dp), + contentAlignment = Alignment.Center + ) { + Text( + text = symbol.text, + textAlign = TextAlign.Center, + maxLines = Constants.MAXIMUM_LINES_FOR_SYMBOL_TEXT, + style = MaterialTheme.typography.labelSmall + ) + } + } + } + } +} + +@Preview(showBackground = true) +@ExperimentalMaterial3Api +@Composable +fun SelectedSymbolUiPreview() { + val previewSymbol = Symbol( + id = 0, + text = "119에 전화해주세요", + imageResId = R.drawable.symbol_0, + category = Category( + id = 0, + text = "인사사회어", + imageResId = R.drawable.category_0 + ), + isFavorite = true, + isMine = false + ) + + SpeechBuddyTheme { + SelectedSymbolUi(symbol = previewSymbol, onDelete = {}) + } +} \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSelectedBox.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSelectedBox.kt deleted file mode 100644 index 11f7bced..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSelectedBox.kt +++ /dev/null @@ -1,119 +0,0 @@ -package com.example.speechbuddy.compose.symbolselection - -import androidx.compose.foundation.BorderStroke -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.lazy.LazyRow -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.Button -import androidx.compose.material3.CardDefaults -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedCard -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.example.speechbuddy.R -import com.example.speechbuddy.compose.utils.SymbolUi -import com.example.speechbuddy.domain.models.Category -import com.example.speechbuddy.domain.models.Symbol -import com.example.speechbuddy.ui.SpeechBuddyTheme - - -/** - * Custom UI designed for SymbolSearchBox - * - * @param symbol data class Symbol to be passed to the UI - * @param modifier the Modifier to be applied to this text field - */ -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun SymbolSelectedBox( - symbol: Symbol, - modifier: Modifier = Modifier, -) { - - OutlinedCard( - modifier = Modifier - .fillMaxWidth() - .height(160.dp), - shape = RoundedCornerShape(10.dp), - colors = CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.surface, - contentColor = MaterialTheme.colorScheme.onSurface, - - ), - border = BorderStroke(1.dp, MaterialTheme.colorScheme.onSurface) - - ) { - Row( - modifier = Modifier.fillMaxWidth() - ) { - - LazyRow( - modifier = Modifier - .fillMaxWidth(0.8f) - .height(150.dp) - ) { - items(10) { - SymbolUi( - symbol = symbol, - onSelect = { /*TODO*/ } - ) { - - } - } - - } - - Box( - modifier = Modifier - .fillMaxWidth(0.2f) - .background(Color.Yellow), - - ) { - Button( - modifier = modifier - .fillMaxSize() - .background(Color.Red), - onClick = { /*TODO*/ } - ) { - - } - } - - } - - } - -} - - -@Preview(showBackground = true) -@Composable -fun SymbolSelectedBoxPreview() { - SpeechBuddyTheme { - val previewSymbol = Symbol( - id = 0, - text = "앵무새", - imageResId = R.drawable.top_app_bar_ic, - category = Category( - id = 0, - text = "동물", - imageResId = R.drawable.top_app_bar_ic - ), - isFavorite = true, - isMine = false - ) - SymbolSelectedBox( - symbol = previewSymbol, - modifier = Modifier - ) - } -} \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/CategoryUi.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/CategoryUi.kt index c687ffb3..e26d9ae1 100644 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/CategoryUi.kt +++ b/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/CategoryUi.kt @@ -70,7 +70,6 @@ fun CategoryUi( Text( text = category.text, textAlign = TextAlign.Center, - maxLines = Constants.MAXIMUM_LINES_FOR_SYMBOL_TEXT, style = MaterialTheme.typography.bodySmall ) } diff --git a/frontend/app/src/main/java/com/example/speechbuddy/ui/Type.kt b/frontend/app/src/main/java/com/example/speechbuddy/ui/Type.kt index f96cf614..e9a80441 100644 --- a/frontend/app/src/main/java/com/example/speechbuddy/ui/Type.kt +++ b/frontend/app/src/main/java/com/example/speechbuddy/ui/Type.kt @@ -94,8 +94,8 @@ val Typography = Typography( ), labelSmall = TextStyle( fontFamily = FontFamily.Default, - fontWeight = FontWeight.Medium, - fontSize = 11.sp, - lineHeight = 16.sp, + fontWeight = FontWeight.Normal, + fontSize = 10.sp, + lineHeight = 12.sp, ), ) diff --git a/frontend/app/src/main/res/values/strings.xml b/frontend/app/src/main/res/values/strings.xml index f7621d89..4149f03f 100644 --- a/frontend/app/src/main/res/values/strings.xml +++ b/frontend/app/src/main/res/values/strings.xml @@ -40,4 +40,5 @@ 회원가입 오류 검색어를 입력하세요 즐겨찾기 + 상징 선택 취소 \ No newline at end of file From 921f688e14f3148eb09b71cb7276b2e3415f514f Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Sun, 29 Oct 2023 21:03:58 +0900 Subject: [PATCH 14/25] :label: Change category field of symbols to categoryId --- .../speechbuddy/compose/symbolselection/SelectedSymbolUi.kt | 6 +----- .../java/com/example/speechbuddy/compose/utils/SymbolUi.kt | 6 +----- .../java/com/example/speechbuddy/domain/models/Symbol.kt | 2 +- 3 files changed, 3 insertions(+), 11 deletions(-) diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SelectedSymbolUi.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SelectedSymbolUi.kt index e2f21e22..98570892 100644 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SelectedSymbolUi.kt +++ b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SelectedSymbolUi.kt @@ -110,11 +110,7 @@ fun SelectedSymbolUiPreview() { id = 0, text = "119에 전화해주세요", imageResId = R.drawable.symbol_0, - category = Category( - id = 0, - text = "인사사회어", - imageResId = R.drawable.category_0 - ), + categoryId = 0, isFavorite = true, isMine = false ) diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/SymbolUi.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/SymbolUi.kt index c63baaa9..2ded52bf 100644 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/SymbolUi.kt +++ b/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/SymbolUi.kt @@ -120,11 +120,7 @@ fun SymbolUiPreview() { id = 0, text = "119에 전화해주세요", imageResId = R.drawable.symbol_0, - category = Category( - id = 0, - text = "인사사회어", - imageResId = R.drawable.category_0 - ), + categoryId = 0, isFavorite = true, isMine = false ) diff --git a/frontend/app/src/main/java/com/example/speechbuddy/domain/models/Symbol.kt b/frontend/app/src/main/java/com/example/speechbuddy/domain/models/Symbol.kt index 33c95c9c..13ec7948 100644 --- a/frontend/app/src/main/java/com/example/speechbuddy/domain/models/Symbol.kt +++ b/frontend/app/src/main/java/com/example/speechbuddy/domain/models/Symbol.kt @@ -8,7 +8,7 @@ data class Symbol( val id: Int, val text: String, val imageResId: Int, - val category: Category, + val categoryId: Int, val isFavorite: Boolean, val isMine: Boolean ): Parcelable \ No newline at end of file From 4b94283c7b12cac691bcc27e9b5bf598174a6500 Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Sun, 29 Oct 2023 21:07:32 +0900 Subject: [PATCH 15/25] :art: Removed unused import directives & javadoc --- .../compose/symbolselection/SelectedSymbolUi.kt | 9 --------- .../compose/symbolselection/SymbolSearchBox.kt | 7 ------- .../com/example/speechbuddy/compose/utils/CategoryUi.kt | 1 - .../com/example/speechbuddy/compose/utils/SymbolUi.kt | 1 - 4 files changed, 18 deletions(-) diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SelectedSymbolUi.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SelectedSymbolUi.kt index 98570892..4240c22e 100644 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SelectedSymbolUi.kt +++ b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SelectedSymbolUi.kt @@ -30,19 +30,10 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.example.speechbuddy.R -import com.example.speechbuddy.domain.models.Category import com.example.speechbuddy.domain.models.Symbol import com.example.speechbuddy.ui.SpeechBuddyTheme import com.example.speechbuddy.utils.Constants - -/** - * Custom UI designed for SymbolSearchBox - * - * @param symbol data class Symbol to be passed to the UI - * @param modifier the Modifier to be applied to this text field - * @param onDelete called when the upper left icon of this Symbol is clicked - */ @ExperimentalMaterial3Api @Composable fun SelectedSymbolUi( diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSearchBox.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSearchBox.kt index c6d37bd6..5eaa57d0 100644 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSearchBox.kt +++ b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSearchBox.kt @@ -19,13 +19,6 @@ import androidx.compose.ui.unit.dp import com.example.speechbuddy.R import com.example.speechbuddy.ui.SpeechBuddyTheme -/** - * Custom UI designed for SymbolSearchBox - * - * @param value the input text to be shown in the text field - * @param onValueChange the callback that is triggered when the input service updates the text. An updated text comes as a parameter of the callback - * @param modifier the Modifier to be applied to this text field - */ @OptIn(ExperimentalMaterial3Api::class) @Composable fun SymbolSearchBox( diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/CategoryUi.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/CategoryUi.kt index e26d9ae1..f1f46e59 100644 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/CategoryUi.kt +++ b/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/CategoryUi.kt @@ -26,7 +26,6 @@ import androidx.compose.ui.unit.dp import com.example.speechbuddy.R import com.example.speechbuddy.domain.models.Category import com.example.speechbuddy.ui.SpeechBuddyTheme -import com.example.speechbuddy.utils.Constants /** * Custom UI designed for Category diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/SymbolUi.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/SymbolUi.kt index 2ded52bf..5099d3d2 100644 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/SymbolUi.kt +++ b/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/SymbolUi.kt @@ -31,7 +31,6 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.example.speechbuddy.R -import com.example.speechbuddy.domain.models.Category import com.example.speechbuddy.domain.models.Symbol import com.example.speechbuddy.ui.SpeechBuddyTheme import com.example.speechbuddy.utils.Constants.Companion.MAXIMUM_LINES_FOR_SYMBOL_TEXT From 71d37f1db7bcaf747ea90b88fe422fad092c7165 Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Sun, 29 Oct 2023 21:44:29 +0900 Subject: [PATCH 16/25] :sparkles: Implement selected symbols box --- .../symbolselection/SelectedSymbolUi.kt | 6 +- .../symbolselection/SelectedSymbolsBox.kt | 104 ++++++++++++++++++ ...lSearchBox.kt => SymbolSearchTextField.kt} | 8 +- frontend/app/src/main/res/values/strings.xml | 1 + 4 files changed, 112 insertions(+), 7 deletions(-) create mode 100644 frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SelectedSymbolsBox.kt rename frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/{SymbolSearchBox.kt => SymbolSearchTextField.kt} (92%) diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SelectedSymbolUi.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SelectedSymbolUi.kt index 4240c22e..634bceb2 100644 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SelectedSymbolUi.kt +++ b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SelectedSymbolUi.kt @@ -39,7 +39,7 @@ import com.example.speechbuddy.utils.Constants fun SelectedSymbolUi( symbol: Symbol, modifier: Modifier = Modifier, - onDelete: () -> Unit + onClear: () -> Unit ) { Card( modifier = modifier.size(100.dp), @@ -51,7 +51,7 @@ fun SelectedSymbolUi( ) { Box(contentAlignment = Alignment.TopEnd) { IconButton( - onClick = onDelete, + onClick = onClear, modifier = Modifier .size(22.dp) .padding(5.dp) @@ -107,6 +107,6 @@ fun SelectedSymbolUiPreview() { ) SpeechBuddyTheme { - SelectedSymbolUi(symbol = previewSymbol, onDelete = {}) + SelectedSymbolUi(symbol = previewSymbol, onClear = {}) } } \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SelectedSymbolsBox.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SelectedSymbolsBox.kt new file mode 100644 index 00000000..d4cfb96f --- /dev/null +++ b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SelectedSymbolsBox.kt @@ -0,0 +1,104 @@ +package com.example.speechbuddy.compose.symbolselection + +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.example.speechbuddy.R +import com.example.speechbuddy.domain.models.Symbol +import com.example.speechbuddy.ui.SpeechBuddyTheme + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun SelectedSymbolsBox( + selectedSymbols: List, + onClearAll: () -> Unit, + modifier: Modifier = Modifier +) { + Box( + modifier = modifier + .fillMaxWidth() + .height(120.dp) + .background(color = MaterialTheme.colorScheme.surface) + .border( + width = 1.dp, + color = MaterialTheme.colorScheme.surfaceVariant, + shape = RoundedCornerShape(10.dp) + ), + contentAlignment = Alignment.CenterEnd + ) { + LazyRow( + contentPadding = PaddingValues(10.dp), + horizontalArrangement = Arrangement.spacedBy(10.dp) + ) { + items(selectedSymbols) { symbol -> + SelectedSymbolUi(symbol = symbol, onClear = {}) + } + } + + Box( + modifier = Modifier + .width(50.dp) + .background(color = MaterialTheme.colorScheme.background) + ) { + Button( + onClick = onClearAll, + modifier = Modifier + .fillMaxSize() + .padding(6.dp), + enabled = selectedSymbols.isNotEmpty(), + shape = RoundedCornerShape(5.dp), + colors = ButtonDefaults.buttonColors( + containerColor = MaterialTheme.colorScheme.tertiary, + contentColor = MaterialTheme.colorScheme.onTertiary, + ), + contentPadding = PaddingValues(2.dp) + ) { + Text( + text = stringResource(id = R.string.clear_all), + textAlign = TextAlign.Center, + style = MaterialTheme.typography.bodyMedium + ) + } + } + } +} + +@Preview +@Composable +fun SelectedSymbolsBoxPreview() { + val previewSymbol = Symbol( + id = 0, + text = "119에 전화해주세요", + imageResId = R.drawable.symbol_0, + categoryId = 0, + isFavorite = true, + isMine = false + ) + val selectedSymbols = List(size = 10, init = { previewSymbol }) + + SpeechBuddyTheme { + SelectedSymbolsBox(selectedSymbols = selectedSymbols, onClearAll = {}) + } +} \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSearchBox.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSearchTextField.kt similarity index 92% rename from frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSearchBox.kt rename to frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSearchTextField.kt index 5eaa57d0..62954fb8 100644 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSearchBox.kt +++ b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSearchTextField.kt @@ -21,7 +21,7 @@ import com.example.speechbuddy.ui.SpeechBuddyTheme @OptIn(ExperimentalMaterial3Api::class) @Composable -fun SymbolSearchBox( +fun SymbolSearchTextField( value: String, onValueChange: (String) -> Unit, modifier: Modifier = Modifier @@ -46,16 +46,16 @@ fun SymbolSearchBox( textColor = MaterialTheme.colorScheme.onSurface, containerColor = MaterialTheme.colorScheme.surface, focusedBorderColor = MaterialTheme.colorScheme.tertiary, - unfocusedBorderColor = MaterialTheme.colorScheme.outline + unfocusedBorderColor = MaterialTheme.colorScheme.surfaceVariant ) ) } @Preview(showBackground = true) @Composable -fun SymbolSearchBoxPreview() { +fun SymbolSearchTextFieldPreview() { SpeechBuddyTheme { - SymbolSearchBox( + SymbolSearchTextField( value = "검색어", onValueChange = {}, ) diff --git a/frontend/app/src/main/res/values/strings.xml b/frontend/app/src/main/res/values/strings.xml index 4149f03f..826899a9 100644 --- a/frontend/app/src/main/res/values/strings.xml +++ b/frontend/app/src/main/res/values/strings.xml @@ -41,4 +41,5 @@ 검색어를 입력하세요 즐겨찾기 상징 선택 취소 + 전체 삭제 \ No newline at end of file From 68fc7b0973bd1330ea877472d67a106cd0bb6d23 Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Sun, 29 Oct 2023 22:12:56 +0900 Subject: [PATCH 17/25] :sparkles: Implement symbol selection screen --- .../symbolselection/SymbolSelectionScreen.kt | 53 ++++++++++++++++--- 1 file changed, 46 insertions(+), 7 deletions(-) diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSelectionScreen.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSelectionScreen.kt index a9fb36bd..abcfb1e7 100644 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSelectionScreen.kt +++ b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSelectionScreen.kt @@ -1,20 +1,28 @@ package com.example.speechbuddy.compose.symbolselection import android.annotation.SuppressLint +import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.grid.GridCells +import androidx.compose.foundation.lazy.grid.LazyVerticalGrid +import androidx.compose.foundation.lazy.grid.items +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Surface -import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import com.example.speechbuddy.R +import com.example.speechbuddy.compose.utils.SymbolUi import com.example.speechbuddy.compose.utils.TopAppBarUi +import com.example.speechbuddy.domain.models.Symbol import com.example.speechbuddy.ui.SpeechBuddyTheme @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @@ -24,6 +32,17 @@ fun SymbolSelectionScreen( modifier: Modifier = Modifier, onBackClick: () -> Unit ) { + /* TODO: ViewModel 연결 후 삭제 */ + val previewSymbol = Symbol( + id = 0, + text = "119에 전화해주세요", + imageResId = R.drawable.symbol_0, + categoryId = 0, + isFavorite = true, + isMine = false + ) + val selectedSymbols = List(size = 10, init = { previewSymbol }) + Surface(modifier = modifier.fillMaxSize()) { Scaffold( topBar = { TopAppBarUi(onBackClick = onBackClick) } @@ -31,14 +50,34 @@ fun SymbolSelectionScreen( Column( modifier = Modifier .padding(24.dp) - .fillMaxSize(), - verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally + .fillMaxSize() + .padding(top = 60.dp), + verticalArrangement = Arrangement.spacedBy(20.dp) ) { - Text("hello") + /* TODO: ViewModel 연결 */ + SymbolSearchTextField(value = "검색어", onValueChange = {}) - // TODO + SelectedSymbolsBox(selectedSymbols = selectedSymbols, onClearAll = {}) + Box( + modifier = Modifier + .fillMaxSize() + .background( + color = MaterialTheme.colorScheme.surfaceVariant, + shape = RoundedCornerShape(20.dp) + ) + .padding(16.dp) + ) { + LazyVerticalGrid( + columns = GridCells.Adaptive(140.dp), + verticalArrangement = Arrangement.spacedBy(16.dp), + horizontalArrangement = Arrangement.spacedBy(16.dp) + ) { + items(selectedSymbols) { symbol -> + SymbolUi(symbol = symbol, onSelect = {}, onFavoriteChange = {}) + } + } + } } } } From 6224f2a5e19ad7949a946b60ba704549d858d090 Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Mon, 30 Oct 2023 00:43:32 +0900 Subject: [PATCH 18/25] :fire: Remove onBackClick from symbol selection screen --- .../symbolselection/SymbolSelectionScreen.kt | 57 ++++++++----------- 1 file changed, 24 insertions(+), 33 deletions(-) diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSelectionScreen.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSelectionScreen.kt index abcfb1e7..a4cfc456 100644 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSelectionScreen.kt +++ b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSelectionScreen.kt @@ -1,6 +1,5 @@ package com.example.speechbuddy.compose.symbolselection -import android.annotation.SuppressLint import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -13,7 +12,6 @@ import androidx.compose.foundation.lazy.grid.items import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Scaffold import androidx.compose.material3.Surface import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier @@ -21,16 +19,13 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.example.speechbuddy.R import com.example.speechbuddy.compose.utils.SymbolUi -import com.example.speechbuddy.compose.utils.TopAppBarUi import com.example.speechbuddy.domain.models.Symbol import com.example.speechbuddy.ui.SpeechBuddyTheme -@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @OptIn(ExperimentalMaterial3Api::class) @Composable fun SymbolSelectionScreen( modifier: Modifier = Modifier, - onBackClick: () -> Unit ) { /* TODO: ViewModel 연결 후 삭제 */ val previewSymbol = Symbol( @@ -44,38 +39,34 @@ fun SymbolSelectionScreen( val selectedSymbols = List(size = 10, init = { previewSymbol }) Surface(modifier = modifier.fillMaxSize()) { - Scaffold( - topBar = { TopAppBarUi(onBackClick = onBackClick) } + Column( + modifier = Modifier + .padding(24.dp) + .fillMaxSize() + .padding(top = 60.dp), + verticalArrangement = Arrangement.spacedBy(20.dp) ) { - Column( + /* TODO: ViewModel 연결 */ + SymbolSearchTextField(value = "검색어", onValueChange = {}) + + SelectedSymbolsBox(selectedSymbols = selectedSymbols, onClearAll = {}) + + Box( modifier = Modifier - .padding(24.dp) .fillMaxSize() - .padding(top = 60.dp), - verticalArrangement = Arrangement.spacedBy(20.dp) + .background( + color = MaterialTheme.colorScheme.surfaceVariant, + shape = RoundedCornerShape(20.dp) + ) + .padding(16.dp) ) { - /* TODO: ViewModel 연결 */ - SymbolSearchTextField(value = "검색어", onValueChange = {}) - - SelectedSymbolsBox(selectedSymbols = selectedSymbols, onClearAll = {}) - - Box( - modifier = Modifier - .fillMaxSize() - .background( - color = MaterialTheme.colorScheme.surfaceVariant, - shape = RoundedCornerShape(20.dp) - ) - .padding(16.dp) + LazyVerticalGrid( + columns = GridCells.Adaptive(140.dp), + verticalArrangement = Arrangement.spacedBy(16.dp), + horizontalArrangement = Arrangement.spacedBy(16.dp) ) { - LazyVerticalGrid( - columns = GridCells.Adaptive(140.dp), - verticalArrangement = Arrangement.spacedBy(16.dp), - horizontalArrangement = Arrangement.spacedBy(16.dp) - ) { - items(selectedSymbols) { symbol -> - SymbolUi(symbol = symbol, onSelect = {}, onFavoriteChange = {}) - } + items(selectedSymbols) { symbol -> + SymbolUi(symbol = symbol, onSelect = {}, onFavoriteChange = {}) } } } @@ -87,6 +78,6 @@ fun SymbolSelectionScreen( @Composable fun SymbolSelectionScreenPreview() { SpeechBuddyTheme { - SymbolSelectionScreen(onBackClick = {}) + SymbolSelectionScreen() } } \ No newline at end of file From 572d7fd1c9ac79704e9e11533ffa01ff6f1b527a Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Mon, 30 Oct 2023 01:04:36 +0900 Subject: [PATCH 19/25] :trucK: Replace speech buddy parrot --- .../compose/landing/LandingScreen.kt | 19 +++++++++++++----- .../main/res/drawable/speechbuddy_parrot.png | Bin 0 -> 41959 bytes 2 files changed, 14 insertions(+), 5 deletions(-) create mode 100644 frontend/app/src/main/res/drawable/speechbuddy_parrot.png diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/landing/LandingScreen.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/landing/LandingScreen.kt index 961ec29b..593a7a43 100644 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/landing/LandingScreen.kt +++ b/frontend/app/src/main/java/com/example/speechbuddy/compose/landing/LandingScreen.kt @@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.runtime.Composable @@ -25,11 +26,19 @@ fun LandingScreen( onGuestClick: () -> Unit, onLoginClick: () -> Unit, ) { - Surface(modifier = modifier.fillMaxSize(), color = MaterialTheme.colorScheme.primaryContainer) { - Image( - painter = painterResource(id = R.mipmap.ic_launcher_foreground), - contentDescription = stringResource(id = R.string.app_name), - ) + Surface( + modifier = modifier.fillMaxSize(), + color = MaterialTheme.colorScheme.primaryContainer + ) { + Box( + modifier = Modifier.size(200.dp), + contentAlignment = Alignment.Center + ) { + Image( + painter = painterResource(id = R.drawable.speechbuddy_parrot), + contentDescription = stringResource(id = R.string.app_name), + ) + } Box( modifier = Modifier.padding(horizontal = 24.dp, vertical = 64.dp), contentAlignment = Alignment.BottomCenter diff --git a/frontend/app/src/main/res/drawable/speechbuddy_parrot.png b/frontend/app/src/main/res/drawable/speechbuddy_parrot.png new file mode 100644 index 0000000000000000000000000000000000000000..a61beac3cd1a62211d6045a2495a4fb7c741865d GIT binary patch literal 41959 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 literal 0 HcmV?d00001 From 257f3bb41526e5f365cbefcdc4be4d78cbf9c939 Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Mon, 30 Oct 2023 02:43:02 +0900 Subject: [PATCH 20/25] :lipstick: Adjust paddings in symbol selection screen --- .../speechbuddy/compose/home/HomeScreen.kt | 16 +++++++++++----- .../symbolselection/SymbolSelectionScreen.kt | 7 +++---- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/home/HomeScreen.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/home/HomeScreen.kt index 780e451c..55623c1c 100644 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/home/HomeScreen.kt +++ b/frontend/app/src/main/java/com/example/speechbuddy/compose/home/HomeScreen.kt @@ -1,7 +1,9 @@ package com.example.speechbuddy.compose.home import android.annotation.SuppressLint +import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.size import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme @@ -26,6 +28,7 @@ import com.example.speechbuddy.compose.settings.SettingsScreen import com.example.speechbuddy.compose.symbolcreation.SymbolCreationScreen import com.example.speechbuddy.compose.symbolselection.SymbolSelectionScreen import com.example.speechbuddy.compose.texttospeech.TextToSpeechScreen +import com.example.speechbuddy.compose.utils.TopAppBarUi import com.example.speechbuddy.ui.SpeechBuddyTheme data class BottomNavItem( @@ -65,12 +68,14 @@ fun HomeScreen( ) Scaffold( + topBar = { + /* TODO: TopAppBar for HomeScreen */ + TopAppBarUi(onBackClick = { navController.navigateUp() }) + }, bottomBar = { BottomNavigationBar( items = navItems, navController = navController, - modifier = Modifier - .height(100.dp), onItemClick = { navController.navigate(it.route) } @@ -87,14 +92,14 @@ fun HomeScreen( private fun BottomNavigationBar( items: List, navController: NavController, - modifier: Modifier = Modifier, onItemClick: (BottomNavItem) -> Unit ) { val backStackEntry = navController.currentBackStackEntryAsState() NavigationBar( - modifier = modifier, - containerColor = MaterialTheme.colorScheme.secondaryContainer + modifier = Modifier.height(80.dp), + containerColor = MaterialTheme.colorScheme.secondaryContainer, + windowInsets = WindowInsets(top = 20.dp) ) { items.forEach { item -> val selected = item.route == backStackEntry.value?.destination?.route @@ -107,6 +112,7 @@ private fun BottomNavigationBar( contentDescription = stringResource(id = item.nameResId) ) }, + modifier = Modifier.size(40.dp), colors = NavigationBarItemDefaults.colors( selectedIconColor = MaterialTheme.colorScheme.onPrimaryContainer, unselectedIconColor = MaterialTheme.colorScheme.outline diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSelectionScreen.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSelectionScreen.kt index a4cfc456..d65b4cf3 100644 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSelectionScreen.kt +++ b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSelectionScreen.kt @@ -41,9 +41,8 @@ fun SymbolSelectionScreen( Surface(modifier = modifier.fillMaxSize()) { Column( modifier = Modifier - .padding(24.dp) - .fillMaxSize() - .padding(top = 60.dp), + .padding(start = 24.dp, top = 80.dp, end = 24.dp, bottom = 80.dp) + .fillMaxSize(), verticalArrangement = Arrangement.spacedBy(20.dp) ) { /* TODO: ViewModel 연결 */ @@ -56,7 +55,7 @@ fun SymbolSelectionScreen( .fillMaxSize() .background( color = MaterialTheme.colorScheme.surfaceVariant, - shape = RoundedCornerShape(20.dp) + shape = RoundedCornerShape(topStart = 20.dp, topEnd = 20.dp) ) .padding(16.dp) ) { From 8d64e40a1ebc599a0ef152488e622586b56e85eb Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Mon, 30 Oct 2023 10:24:48 +0900 Subject: [PATCH 21/25] :art: Implement entry interface --- .../speechbuddy/domain/models/Category.kt | 11 -------- .../speechbuddy/domain/models/Entry.kt | 27 +++++++++++++++++++ .../speechbuddy/domain/models/Symbol.kt | 14 ---------- 3 files changed, 27 insertions(+), 25 deletions(-) delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/domain/models/Category.kt create mode 100644 frontend/app/src/main/java/com/example/speechbuddy/domain/models/Entry.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/domain/models/Symbol.kt diff --git a/frontend/app/src/main/java/com/example/speechbuddy/domain/models/Category.kt b/frontend/app/src/main/java/com/example/speechbuddy/domain/models/Category.kt deleted file mode 100644 index 1b6cbb11..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/domain/models/Category.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.example.speechbuddy.domain.models - -import android.os.Parcelable -import kotlinx.parcelize.Parcelize - -@Parcelize -data class Category( - val id: Int, - val text: String, - val imageResId: Int -): Parcelable \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/domain/models/Entry.kt b/frontend/app/src/main/java/com/example/speechbuddy/domain/models/Entry.kt new file mode 100644 index 00000000..84078cbc --- /dev/null +++ b/frontend/app/src/main/java/com/example/speechbuddy/domain/models/Entry.kt @@ -0,0 +1,27 @@ +package com.example.speechbuddy.domain.models + +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +interface Entry { + val id: Int + val text: String + val imageResId: Int +} + +@Parcelize +data class Category( + override val id: Int, + override val text: String, + override val imageResId: Int +) : Parcelable, Entry + +@Parcelize +data class Symbol( + override val id: Int, + override val text: String, + override val imageResId: Int, + val categoryId: Int, + val isFavorite: Boolean, + val isMine: Boolean +) : Parcelable, Entry \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/domain/models/Symbol.kt b/frontend/app/src/main/java/com/example/speechbuddy/domain/models/Symbol.kt deleted file mode 100644 index 13ec7948..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/domain/models/Symbol.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.example.speechbuddy.domain.models - -import android.os.Parcelable -import kotlinx.parcelize.Parcelize - -@Parcelize -data class Symbol( - val id: Int, - val text: String, - val imageResId: Int, - val categoryId: Int, - val isFavorite: Boolean, - val isMine: Boolean -): Parcelable \ No newline at end of file From 8aaf730713997d34715593aabca43d5157131e38 Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Mon, 30 Oct 2023 11:21:32 +0900 Subject: [PATCH 22/25] :sparkles: Implement symbol selection view model --- .../symbolselection/SelectedSymbolsBox.kt | 15 ++-- .../symbolselection/SymbolSelectionScreen.kt | 48 +++++------ .../viewmodel/SymbolSelectionViewModel.kt | 86 +++++++++++++++++++ 3 files changed, 118 insertions(+), 31 deletions(-) create mode 100644 frontend/app/src/main/java/com/example/speechbuddy/viewmodel/SymbolSelectionViewModel.kt diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SelectedSymbolsBox.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SelectedSymbolsBox.kt index d4cfb96f..8e3235b5 100644 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SelectedSymbolsBox.kt +++ b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SelectedSymbolsBox.kt @@ -48,12 +48,17 @@ fun SelectedSymbolsBox( ), contentAlignment = Alignment.CenterEnd ) { - LazyRow( - contentPadding = PaddingValues(10.dp), - horizontalArrangement = Arrangement.spacedBy(10.dp) + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.CenterStart ) { - items(selectedSymbols) { symbol -> - SelectedSymbolUi(symbol = symbol, onClear = {}) + LazyRow( + contentPadding = PaddingValues(10.dp), + horizontalArrangement = Arrangement.spacedBy(10.dp) + ) { + items(selectedSymbols) { symbol -> + SelectedSymbolUi(symbol = symbol, onClear = {}) + } } } diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSelectionScreen.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSelectionScreen.kt index d65b4cf3..4e9bfdb8 100644 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSelectionScreen.kt +++ b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSelectionScreen.kt @@ -15,29 +15,20 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import com.example.speechbuddy.R +import androidx.hilt.navigation.compose.hiltViewModel +import com.example.speechbuddy.compose.utils.CategoryUi import com.example.speechbuddy.compose.utils.SymbolUi +import com.example.speechbuddy.domain.models.Category import com.example.speechbuddy.domain.models.Symbol -import com.example.speechbuddy.ui.SpeechBuddyTheme +import com.example.speechbuddy.viewmodel.SymbolSelectionViewModel @OptIn(ExperimentalMaterial3Api::class) @Composable fun SymbolSelectionScreen( modifier: Modifier = Modifier, + viewModel: SymbolSelectionViewModel = hiltViewModel() ) { - /* TODO: ViewModel 연결 후 삭제 */ - val previewSymbol = Symbol( - id = 0, - text = "119에 전화해주세요", - imageResId = R.drawable.symbol_0, - categoryId = 0, - isFavorite = true, - isMine = false - ) - val selectedSymbols = List(size = 10, init = { previewSymbol }) - Surface(modifier = modifier.fillMaxSize()) { Column( modifier = Modifier @@ -46,9 +37,13 @@ fun SymbolSelectionScreen( verticalArrangement = Arrangement.spacedBy(20.dp) ) { /* TODO: ViewModel 연결 */ - SymbolSearchTextField(value = "검색어", onValueChange = {}) + SymbolSearchTextField( + value = viewModel.queryInput, + onValueChange = { viewModel.setQuery(it) }) - SelectedSymbolsBox(selectedSymbols = selectedSymbols, onClearAll = {}) + SelectedSymbolsBox( + selectedSymbols = viewModel.selectedSymbols, + onClearAll = { viewModel.clearAll() }) Box( modifier = Modifier @@ -64,19 +59,20 @@ fun SymbolSelectionScreen( verticalArrangement = Arrangement.spacedBy(16.dp), horizontalArrangement = Arrangement.spacedBy(16.dp) ) { - items(selectedSymbols) { symbol -> - SymbolUi(symbol = symbol, onSelect = {}, onFavoriteChange = {}) + items(viewModel.entries) { entry -> + when (entry) { + is Symbol -> SymbolUi( + symbol = entry, + onSelect = { viewModel.selectSymbol(entry) }, + onFavoriteChange = {}) + + is Category -> CategoryUi( + category = entry, + onSelect = { viewModel.selectCategory(entry) }) + } } } } } } -} - -@Preview -@Composable -fun SymbolSelectionScreenPreview() { - SpeechBuddyTheme { - SymbolSelectionScreen() - } } \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/viewmodel/SymbolSelectionViewModel.kt b/frontend/app/src/main/java/com/example/speechbuddy/viewmodel/SymbolSelectionViewModel.kt new file mode 100644 index 00000000..ee0032f5 --- /dev/null +++ b/frontend/app/src/main/java/com/example/speechbuddy/viewmodel/SymbolSelectionViewModel.kt @@ -0,0 +1,86 @@ +package com.example.speechbuddy.viewmodel + +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue +import androidx.lifecycle.ViewModel +import com.example.speechbuddy.R +import com.example.speechbuddy.domain.models.Category +import com.example.speechbuddy.domain.models.Entry +import com.example.speechbuddy.domain.models.Symbol +import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject + +@HiltViewModel +class SymbolSelectionViewModel @Inject internal constructor() : ViewModel() { + + var queryInput by mutableStateOf("") + private set + + var selectedSymbols by mutableStateOf(listOf()) + private set + + var entries by mutableStateOf(listOf()) + private set + + /* TODO: 나중에 삭제 */ + private val initialEntries = listOf( + Symbol( + id = 0, + text = "119에 전화해주세요", + imageResId = R.drawable.symbol_0, + categoryId = 0, + isFavorite = true, + isMine = false + ), + Symbol( + id = 0, + text = "119에 전화해주세요", + imageResId = R.drawable.symbol_0, + categoryId = 0, + isFavorite = true, + isMine = false + ) + ) + + private val secondaryEntries = listOf( + Symbol( + id = 0, + text = "119에 전화해주세요", + imageResId = R.drawable.symbol_0, + categoryId = 0, + isFavorite = true, + isMine = false + ), + Symbol( + id = 0, + text = "우와", + imageResId = R.drawable.symbol_0, + categoryId = 0, + isFavorite = true, + isMine = false + ) + ) + + init { + entries = initialEntries + } + + fun setQuery(input: String) { + queryInput = input + } + + fun clearAll() { + selectedSymbols = listOf() + entries = initialEntries + } + + fun selectSymbol(symbol: Symbol) { + selectedSymbols = selectedSymbols.plus(symbol) + entries = secondaryEntries + } + + fun selectCategory(category: Category) { + /* TODO */ + } +} \ No newline at end of file From 641ac13f3ff7bf6c3b7fed10bf5fcedef56e033c Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Wed, 1 Nov 2023 15:50:51 +0900 Subject: [PATCH 23/25] :card_file_box: Modify symnbol and category ids to start from 1 --- .github/pull_request_template.md | 27 --- .github/workflows/backend_CD.yml | 22 -- .github/workflows/backend_CI.yml | 39 ---- .gitignore | 143 ------------ README.md | 28 --- backend/config/__init__.py | 0 backend/config/asgi.py | 16 -- backend/config/exception_handler.py | 16 -- backend/config/settings.py | 212 ------------------ backend/config/urls.py | 9 - backend/config/utils.py | 4 - backend/config/wsgi.py | 16 -- backend/entry/__init__.py | 0 backend/entry/admin.py | 3 - backend/entry/apps.py | 6 - backend/entry/migrations/0001_initial.py | 43 ---- backend/entry/migrations/__init__.py | 0 backend/entry/models.py | 24 -- backend/entry/serializers.py | 30 --- backend/entry/tests.py | 3 - backend/entry/urls.py | 8 - backend/entry/views.py | 47 ---- backend/manage.py | 22 -- backend/requirements.txt | 13 -- backend/setup/__init__.py | 0 backend/setup/admin.py | 3 - backend/setup/apps.py | 6 - backend/setup/migrations/0001_initial.py | 26 --- backend/setup/migrations/__init__.py | 0 backend/setup/models.py | 20 -- backend/setup/serializers.py | 18 -- backend/setup/tests.py | 3 - backend/setup/urls.py | 8 - backend/setup/views.py | 43 ---- backend/user/__init__.py | 0 backend/user/admin.py | 3 - backend/user/apps.py | 6 - backend/user/backends.py | 15 -- backend/user/migrations/0001_initial.py | 70 ------ .../user/migrations/0002_emailverification.py | 22 -- backend/user/migrations/__init__.py | 0 backend/user/models.py | 60 ----- backend/user/serializers.py | 151 ------------- backend/user/test_views.py | 55 ----- backend/user/tests.py | 3 - backend/user/urls.py | 21 -- backend/user/utils.py | 30 --- backend/user/views.py | 185 --------------- frontend/app/build.gradle.kts | 120 ---------- frontend/app/proguard-rules.pro | 21 -- .../speechbuddy/ExampleInstrumentedTest.kt | 24 -- frontend/app/src/main/AndroidManifest.xml | 31 --- .../app/src/main/ic_launcher-playstore.png | Bin 64878 -> 0 bytes .../com/example/speechbuddy/MainActivity.kt | 28 --- .../example/speechbuddy/MainApplication.kt | 12 - .../speechbuddy/compose/SpeechBuddyApp.kt | 83 ------- .../EmailVerificationScreen.kt | 128 ----------- .../speechbuddy/compose/home/HomeScreen.kt | 151 ------------- .../compose/landing/LandingScreen.kt | 65 ------ .../speechbuddy/compose/login/LoginScreen.kt | 126 ----------- .../resetpassword/ResetPasswordScreen.kt | 113 ---------- .../compose/settings/SettingsScreen.kt | 66 ------ .../compose/signup/SignupScreen.kt | 126 ----------- .../symbolcreation/SymbolCreationScreen.kt | 66 ------ .../symbolselection/SelectedSymbolUi.kt | 112 --------- .../symbolselection/SelectedSymbolsBox.kt | 109 --------- .../symbolselection/SymbolSearchTextField.kt | 63 ------ .../symbolselection/SymbolSelectionScreen.kt | 78 ------- .../texttospeech/TextToSpeechScreen.kt | 137 ----------- .../speechbuddy/compose/utils/ButtonUi.kt | 125 ----------- .../speechbuddy/compose/utils/CategoryUi.kt | 91 -------- .../speechbuddy/compose/utils/SymbolUi.kt | 130 ----------- .../speechbuddy/compose/utils/TextFieldUi.kt | 118 ---------- .../speechbuddy/compose/utils/TitleUi.kt | 50 ----- .../speechbuddy/compose/utils/TopAppBarUi.kt | 59 ----- .../data/remote/AuthTokenRemoteSource.kt | 52 ----- .../data/remote/models/AuthTokenDto.kt | 10 - .../data/remote/models/AuthTokenDtoMapper.kt | 22 -- .../data/remote/requests/AuthRequest.kt | 22 -- .../example/speechbuddy/di/NetworkModule.kt | 47 ---- .../speechbuddy/domain/models/AuthToken.kt | 9 - .../speechbuddy/domain/models/Entry.kt | 27 --- .../speechbuddy/domain/utils/DomainMapper.kt | 9 - .../domain/utils/TokenSharedPreferences.kt | 32 --- .../speechbuddy/repository/AuthRepository.kt | 145 ------------ .../speechbuddy/service/AuthService.kt | 44 ---- .../java/com/example/speechbuddy/ui/Color.kt | 65 ------ .../java/com/example/speechbuddy/ui/Theme.kt | 112 --------- .../java/com/example/speechbuddy/ui/Type.kt | 101 --------- .../ui/models/EmailVerificationUiState.kt | 19 -- .../speechbuddy/ui/models/LoginUiState.kt | 17 -- .../speechbuddy/ui/models/SignupUiState.kt | 19 -- .../ui/models/TextToSpeechUiState.kt | 10 - .../example/speechbuddy/utils/Constants.kt | 11 - .../speechbuddy/utils/InputValidationUtil.kt | 17 -- .../example/speechbuddy/utils/Resources.kt | 23 -- .../viewmodel/EmailVerificationViewModel.kt | 198 ---------------- .../speechbuddy/viewmodel/LoginViewModel.kt | 145 ------------ .../speechbuddy/viewmodel/SignupViewModel.kt | 149 ------------ .../viewmodel/SymbolSelectionViewModel.kt | 86 ------- .../viewmodel/TextToSpeechViewModel.kt | 114 ---------- .../app/src/main/res/drawable/category_0.png | Bin 41416 -> 0 bytes .../res/drawable/outline_add_a_photo_24.xml | 5 - .../main/res/drawable/outline_settings_24.xml | 5 - .../res/drawable/outline_touch_app_24.xml | 5 - .../res/drawable/outline_volume_up_24.xml | 5 - .../main/res/drawable/speechbuddy_parrot.png | Bin 41959 -> 0 bytes .../app/src/main/res/drawable/stop_icon.png | Bin 3051 -> 0 bytes .../app/src/main/res/drawable/symbol_0.png | Bin 45603 -> 0 bytes .../src/main/res/drawable/top_app_bar_ic.png | Bin 3543 -> 0 bytes .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 - .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 - .../src/main/res/mipmap-hdpi/ic_launcher.webp | Bin 2220 -> 0 bytes .../mipmap-hdpi/ic_launcher_foreground.webp | Bin 3734 -> 0 bytes .../res/mipmap-hdpi/ic_launcher_round.webp | Bin 4170 -> 0 bytes .../src/main/res/mipmap-mdpi/ic_launcher.webp | Bin 1356 -> 0 bytes .../mipmap-mdpi/ic_launcher_foreground.webp | Bin 2156 -> 0 bytes .../res/mipmap-mdpi/ic_launcher_round.webp | Bin 2504 -> 0 bytes .../main/res/mipmap-xhdpi/ic_launcher.webp | Bin 3318 -> 0 bytes .../mipmap-xhdpi/ic_launcher_foreground.webp | Bin 5476 -> 0 bytes .../res/mipmap-xhdpi/ic_launcher_round.webp | Bin 6164 -> 0 bytes .../main/res/mipmap-xxhdpi/ic_launcher.webp | Bin 5570 -> 0 bytes .../mipmap-xxhdpi/ic_launcher_foreground.webp | Bin 9672 -> 0 bytes .../res/mipmap-xxhdpi/ic_launcher_round.webp | Bin 10368 -> 0 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.webp | Bin 8474 -> 0 bytes .../ic_launcher_foreground.webp | Bin 12996 -> 0 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.webp | Bin 15106 -> 0 bytes frontend/app/src/main/res/values/colors.xml | 6 - frontend/app/src/main/res/values/strings.xml | 53 ----- frontend/app/src/main/res/values/themes.xml | 5 - .../app/src/main/res/xml/backup_rules.xml | 13 -- .../main/res/xml/data_extraction_rules.xml | 19 -- .../example/speechbuddy/ExampleUnitTest.kt | 17 -- frontend/build.gradle.kts | 7 - frontend/gradle.properties | 23 -- frontend/gradle/wrapper/gradle-wrapper.jar | Bin 59203 -> 0 bytes .../gradle/wrapper/gradle-wrapper.properties | 6 - frontend/gradlew | 185 --------------- frontend/gradlew.bat | 89 -------- frontend/settings.gradle.kts | 17 -- 140 files changed, 5686 deletions(-) delete mode 100644 .github/pull_request_template.md delete mode 100644 .github/workflows/backend_CD.yml delete mode 100644 .github/workflows/backend_CI.yml delete mode 100644 .gitignore delete mode 100644 README.md delete mode 100644 backend/config/__init__.py delete mode 100644 backend/config/asgi.py delete mode 100644 backend/config/exception_handler.py delete mode 100644 backend/config/settings.py delete mode 100644 backend/config/urls.py delete mode 100644 backend/config/utils.py delete mode 100644 backend/config/wsgi.py delete mode 100644 backend/entry/__init__.py delete mode 100644 backend/entry/admin.py delete mode 100644 backend/entry/apps.py delete mode 100644 backend/entry/migrations/0001_initial.py delete mode 100644 backend/entry/migrations/__init__.py delete mode 100644 backend/entry/models.py delete mode 100644 backend/entry/serializers.py delete mode 100644 backend/entry/tests.py delete mode 100644 backend/entry/urls.py delete mode 100644 backend/entry/views.py delete mode 100755 backend/manage.py delete mode 100644 backend/requirements.txt delete mode 100644 backend/setup/__init__.py delete mode 100644 backend/setup/admin.py delete mode 100644 backend/setup/apps.py delete mode 100644 backend/setup/migrations/0001_initial.py delete mode 100644 backend/setup/migrations/__init__.py delete mode 100644 backend/setup/models.py delete mode 100644 backend/setup/serializers.py delete mode 100644 backend/setup/tests.py delete mode 100644 backend/setup/urls.py delete mode 100644 backend/setup/views.py delete mode 100644 backend/user/__init__.py delete mode 100644 backend/user/admin.py delete mode 100644 backend/user/apps.py delete mode 100644 backend/user/backends.py delete mode 100644 backend/user/migrations/0001_initial.py delete mode 100644 backend/user/migrations/0002_emailverification.py delete mode 100644 backend/user/migrations/__init__.py delete mode 100644 backend/user/models.py delete mode 100644 backend/user/serializers.py delete mode 100644 backend/user/test_views.py delete mode 100644 backend/user/tests.py delete mode 100644 backend/user/urls.py delete mode 100644 backend/user/utils.py delete mode 100644 backend/user/views.py delete mode 100644 frontend/app/build.gradle.kts delete mode 100644 frontend/app/proguard-rules.pro delete mode 100644 frontend/app/src/androidTest/java/com/example/speechbuddy/ExampleInstrumentedTest.kt delete mode 100644 frontend/app/src/main/AndroidManifest.xml delete mode 100644 frontend/app/src/main/ic_launcher-playstore.png delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/MainActivity.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/MainApplication.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/compose/SpeechBuddyApp.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/compose/emailverification/EmailVerificationScreen.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/compose/home/HomeScreen.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/compose/landing/LandingScreen.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/compose/login/LoginScreen.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/compose/resetpassword/ResetPasswordScreen.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/compose/settings/SettingsScreen.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/compose/signup/SignupScreen.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/compose/symbolcreation/SymbolCreationScreen.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SelectedSymbolUi.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SelectedSymbolsBox.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSearchTextField.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSelectionScreen.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/compose/texttospeech/TextToSpeechScreen.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/compose/utils/ButtonUi.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/compose/utils/CategoryUi.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/compose/utils/SymbolUi.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/compose/utils/TextFieldUi.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/compose/utils/TitleUi.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/compose/utils/TopAppBarUi.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/data/remote/AuthTokenRemoteSource.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/data/remote/models/AuthTokenDto.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/data/remote/models/AuthTokenDtoMapper.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/data/remote/requests/AuthRequest.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/di/NetworkModule.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/domain/models/AuthToken.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/domain/models/Entry.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/domain/utils/DomainMapper.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/domain/utils/TokenSharedPreferences.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/repository/AuthRepository.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/service/AuthService.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/ui/Color.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/ui/Theme.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/ui/Type.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/ui/models/EmailVerificationUiState.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/ui/models/LoginUiState.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/ui/models/SignupUiState.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/ui/models/TextToSpeechUiState.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/utils/Constants.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/utils/InputValidationUtil.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/utils/Resources.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/viewmodel/EmailVerificationViewModel.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/viewmodel/LoginViewModel.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/viewmodel/SignupViewModel.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/viewmodel/SymbolSelectionViewModel.kt delete mode 100644 frontend/app/src/main/java/com/example/speechbuddy/viewmodel/TextToSpeechViewModel.kt delete mode 100644 frontend/app/src/main/res/drawable/category_0.png delete mode 100644 frontend/app/src/main/res/drawable/outline_add_a_photo_24.xml delete mode 100644 frontend/app/src/main/res/drawable/outline_settings_24.xml delete mode 100644 frontend/app/src/main/res/drawable/outline_touch_app_24.xml delete mode 100644 frontend/app/src/main/res/drawable/outline_volume_up_24.xml delete mode 100644 frontend/app/src/main/res/drawable/speechbuddy_parrot.png delete mode 100644 frontend/app/src/main/res/drawable/stop_icon.png delete mode 100644 frontend/app/src/main/res/drawable/symbol_0.png delete mode 100644 frontend/app/src/main/res/drawable/top_app_bar_ic.png delete mode 100644 frontend/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml delete mode 100644 frontend/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml delete mode 100644 frontend/app/src/main/res/mipmap-hdpi/ic_launcher.webp delete mode 100644 frontend/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp delete mode 100644 frontend/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp delete mode 100644 frontend/app/src/main/res/mipmap-mdpi/ic_launcher.webp delete mode 100644 frontend/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp delete mode 100644 frontend/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp delete mode 100644 frontend/app/src/main/res/mipmap-xhdpi/ic_launcher.webp delete mode 100644 frontend/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp delete mode 100644 frontend/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp delete mode 100644 frontend/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp delete mode 100644 frontend/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp delete mode 100644 frontend/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp delete mode 100644 frontend/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp delete mode 100644 frontend/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp delete mode 100644 frontend/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp delete mode 100644 frontend/app/src/main/res/values/colors.xml delete mode 100644 frontend/app/src/main/res/values/strings.xml delete mode 100644 frontend/app/src/main/res/values/themes.xml delete mode 100644 frontend/app/src/main/res/xml/backup_rules.xml delete mode 100644 frontend/app/src/main/res/xml/data_extraction_rules.xml delete mode 100644 frontend/app/src/test/java/com/example/speechbuddy/ExampleUnitTest.kt delete mode 100644 frontend/build.gradle.kts delete mode 100644 frontend/gradle.properties delete mode 100644 frontend/gradle/wrapper/gradle-wrapper.jar delete mode 100644 frontend/gradle/wrapper/gradle-wrapper.properties delete mode 100755 frontend/gradlew delete mode 100644 frontend/gradlew.bat delete mode 100644 frontend/settings.gradle.kts diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md deleted file mode 100644 index e034bff3..00000000 --- a/.github/pull_request_template.md +++ /dev/null @@ -1,27 +0,0 @@ -### PR Title: [Descriptive title summarizing the change] - -#### Related Issue(s): -Link or reference any related issues or tickets. - -#### PR Description: -[Provide a brief summary of the changes made.] - -##### Changes Included: -- [ ] Added new feature(s) -- [ ] Fixed identified bug(s) -- [ ] Updated relevant documentation - -##### Notes for Reviewer: -Any specific instructions or points to be considered by the -reviewer. - -#### Reviewer Checklist: -- [ ] Code is written in clean, maintainable, and idiomatic form. -- [ ] Automated test coverage is adequate. -- [ ] All existing tests pass. -- [ ] Manual testing has been performed to ensure the PR works as expected. -- [ ] Code review comments have been addressed or clarified. - -#### Additional Comments: -Add any other comments or information that might be useful for the -review process. diff --git a/.github/workflows/backend_CD.yml b/.github/workflows/backend_CD.yml deleted file mode 100644 index 15508f3b..00000000 --- a/.github/workflows/backend_CD.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: SpeechBuddy Backend CD - -on: - push: - branches: [ "main" ] - -jobs: - deploy: - name: Deploy - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: SSH Remote Commands - uses: appleboy/ssh-action@v1.0.0 - with: - key: ${{ secrets.SSH_KEY }} - host: ${{ secrets.HOST }} - username: ${{ secrets.USERNAME }} - script: | - sh deploy.sh diff --git a/.github/workflows/backend_CI.yml b/.github/workflows/backend_CI.yml deleted file mode 100644 index 0e3910b2..00000000 --- a/.github/workflows/backend_CI.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: SpeechBuddy Backend CI - -on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] - -jobs: - build: - - runs-on: ubuntu-latest - strategy: - max-parallel: 4 - matrix: - python-version: [3.9] - - steps: - - uses: actions/checkout@v4 - - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v3 - with: - python-version: ${{ matrix.python-version }} - - - name: Install Dependencies - run: | - cd backend - python -m pip install --upgrade pip - pip install -r requirements.txt - - - name: Run Tests - run: | - cd backend - python manage.py test --no-input - env: - SECRET_KEY: ${{ secrets.SECRET_KEY }} - EMAIL_HOST_USER: ${{ secrets.EMAIL_HOST_USER }} - EMAIL_HOST_PASSWORD: ${{ secrets.EMAIL_HOST_PASSWORD }} diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 0998cb7c..00000000 --- a/.gitignore +++ /dev/null @@ -1,143 +0,0 @@ -.DS_Store - -backend/confidential.py -backend/secrets.json - -backend/.idea -backend/.DS_Store - -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class - -# C extensions -*.so - -# Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -pip-wheel-metadata/ -share/python-wheels/ -*.egg-info/ -.installed.cfg -*.egg -MANIFEST - -# PyInstaller -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.nox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*.cover -*.py,cover -.hypothesis/ -.pytest_cache/ - -# Translations -*.mo -*.pot - -# Django stuff: -*.log -local_settings.py -db.sqlite3 -db.sqlite3-journal - -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ - -# PyBuilder -target/ - -# Jupyter Notebook -.ipynb_checkpoints - -# IPython -profile_default/ -ipython_config.py - -# pyenv -.python-version - -# PEP 582; used by e.g. github.com/David-OConnor/pyflow -__pypackages__/ - -# Celery stuff -celerybeat-schedule -celerybeat.pid - -# SageMath parsed files -*.sage.py - -# Environments -.env -.venv -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site - -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json - -# Pyre type checker -.pyre/ - -*.iml -.idea -.DS_Store -local.properties - -frontend/.gradle -frontend/local.properties -frontend/.idea -frontend/.DS_Store -frontend/build -frontend/captures -frontend/.externalNativeBuild -frontend/.cxx -frontend/app/build \ No newline at end of file diff --git a/README.md b/README.md deleted file mode 100644 index 8c910924..00000000 --- a/README.md +++ /dev/null @@ -1,28 +0,0 @@ -# SNU-SWPP-Template - -You can use the README file to showcase and promote your mobile app. The template provided below is just a starting point. Feel free to craft your README as you see fit. - -Please note that the README doesn't affect your grade and is not included in documentation(Wiki). - -# [Your Application Name] - -[Short application description here] - -![Application Screenshot](path_to_screenshot.png) - -## Features - -- Feature 1: Brief description -- Feature 2: Brief description -- ... - -## Getting Started - -### Prerequisites - -- Android Studio [version, e.g., 4.2.1] -- Minimum Android SDK Version [e.g., 21] - -### Installation - -[Installation link here] diff --git a/backend/config/__init__.py b/backend/config/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/backend/config/asgi.py b/backend/config/asgi.py deleted file mode 100644 index 87078af4..00000000 --- a/backend/config/asgi.py +++ /dev/null @@ -1,16 +0,0 @@ -""" -ASGI config for config project. - -It exposes the ASGI callable as a module-level variable named ``application``. - -For more information on this file, see -https://docs.djangoproject.com/en/4.2/howto/deployment/asgi/ -""" - -import os - -from django.core.asgi import get_asgi_application - -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings") - -application = get_asgi_application() diff --git a/backend/config/exception_handler.py b/backend/config/exception_handler.py deleted file mode 100644 index b6449249..00000000 --- a/backend/config/exception_handler.py +++ /dev/null @@ -1,16 +0,0 @@ -from rest_framework.views import exception_handler - - -def custom_exception_handler(exc, context): - response = exception_handler(exc, context) - - if response is not None: - custom_response_data = { - "error": { - "code": response.status_code, - "message": response.data, - } - } - response.data = custom_response_data - - return response \ No newline at end of file diff --git a/backend/config/settings.py b/backend/config/settings.py deleted file mode 100644 index ad0a74fa..00000000 --- a/backend/config/settings.py +++ /dev/null @@ -1,212 +0,0 @@ -""" -Django settings for config project. - -Generated by 'django-admin startproject' using Django 4.2.5. - -For more information on this file, see -https://docs.djangoproject.com/en/4.2/topics/settings/ - -For the full list of settings and their values, see -https://docs.djangoproject.com/en/4.2/ref/settings/ -""" -import datetime -import json -import os -from pathlib import Path - -# Build paths inside the project like this: BASE_DIR / 'subdir'. -from django.core.exceptions import ImproperlyConfigured - -BASE_DIR = Path(__file__).resolve().parent.parent - -AUTH_USER_MODEL = 'user.User' - -AUTHENTICATION_BACKENDS = ['user.backends.EmailBackend'] - -# Quick-start development settings - unsuitable for production -# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/ - -if "GITHUB_ACTIONS" in os.environ: - # If running in GitHub Actions, use secrets from environment variables - secrets = { - "SECRET_KEY": os.environ.get("SECRET_KEY"), - "EMAIL_HOST_USER": os.environ.get("EMAIL_HOST_USER"), - "EMAIL_HOST_PASSWORD": os.environ.get("EMAIL_HOST_PASSWORD"), - } -else: - secret_file = os.path.join(BASE_DIR, 'secrets.json') # secrets.json 파일 위치를 명시 - with open(secret_file) as f: - secrets = json.loads(f.read()) - - -def get_secret(setting, secrets=secrets): - try: - return secrets[setting] - except KeyError: - error_msg = "Set the {} environment variable".format(setting) - raise ImproperlyConfigured(error_msg) - - -SECRET_KEY = get_secret("SECRET_KEY") - -EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' -EMAIL_HOST = 'smtp.gmail.com' -EMAIL_USE_TLS = True -EMAIL_PORT = 587 -EMAIL_HOST_USER = get_secret("EMAIL_HOST_USER") -EMAIL_HOST_PASSWORD = get_secret("EMAIL_HOST_PASSWORD") -DEFAULT_FROM_EMAIL = EMAIL_HOST_USER - -# SECURITY WARNING: don't run with debug turned on in production! -DEBUG = True - -ALLOWED_HOSTS = [ - 'ec2-54-180-112-72.ap-northeast-2.compute.amazonaws.com', - '54.180.112.72', - '127.0.0.1', - '10.0.2.2' -] - -# Application definition - -INSTALLED_APPS = [ - "django.contrib.admin", - "django.contrib.auth", - "django.contrib.contenttypes", - "django.contrib.sessions", - "django.contrib.messages", - "django.contrib.staticfiles", - 'rest_framework', - 'rest_framework_simplejwt', - 'rest_framework_simplejwt.token_blacklist', - 'rest_framework.authtoken', - 'user', - 'entry', - 'setup', -] - -MIDDLEWARE = [ - "django.middleware.security.SecurityMiddleware", - "django.contrib.sessions.middleware.SessionMiddleware", - "django.middleware.common.CommonMiddleware", - "django.middleware.csrf.CsrfViewMiddleware", - "django.contrib.auth.middleware.AuthenticationMiddleware", - "django.contrib.messages.middleware.MessageMiddleware", - "django.middleware.clickjacking.XFrameOptionsMiddleware", -] - -ROOT_URLCONF = "config.urls" - -TEMPLATES = [ - { - "BACKEND": "django.template.backends.django.DjangoTemplates", - "DIRS": [], - "APP_DIRS": True, - "OPTIONS": { - "context_processors": [ - "django.template.context_processors.debug", - "django.template.context_processors.request", - "django.contrib.auth.context_processors.auth", - "django.contrib.messages.context_processors.messages", - ], - }, - }, -] - -WSGI_APPLICATION = "config.wsgi.application" - -# Database -# https://docs.djangoproject.com/en/4.2/ref/settings/#databases - -# Local DB settings -# DATABASES = { -# 'default': { -# 'ENGINE': 'django.db.backends.sqlite3', -# 'NAME': os.path.join(BASE_DIR, 'sqlite3_for_dev'), -# } -# } - -# Remote DB settings -# Add your own confidential.py -if not ("GITHUB_ACTIONS" in os.environ): - import confidential - DATABASES = confidential.DATABASES - - -# Password validation -# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators - -AUTH_PASSWORD_VALIDATORS = [ - { - "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", - }, - { - "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", - }, - { - "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", - }, - { - "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", - }, -] - -# Internationalization -# https://docs.djangoproject.com/en/4.2/topics/i18n/ - -LANGUAGE_CODE = "en-us" - -TIME_ZONE = "Asia/Seoul" -# 변경된 한국 시간대를 사용하려면 naive datetime 개체인 datetime.datetime.now() 를 사용하는 대신 django.utils.timezone.now() 를 사용해야함 -# 혹시 한국 시간대가 반영이 안된다면 datetime을 사용하지 않았는지 체크해볼것 - -USE_I18N = True - -USE_TZ = True - -# Static files (CSS, JavaScript, Images) -# https://docs.djangoproject.com/en/4.2/howto/static-files/ - -STATIC_URL = "static/" - -# Default primary key field type -# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field - -DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" - -REST_FRAMEWORK = { - 'DEFAULT_PERMISSION_CLASSES': ( - 'rest_framework.permissions.IsAuthenticated', - ), - - 'DEFAULT_RENDERER_CLASSES': ( - 'rest_framework.renderers.JSONRenderer', - 'rest_framework.renderers.BrowsableAPIRenderer', - ), - - 'DEFAULT_AUTHENTICATION_CLASSES': ( - 'rest_framework.authentication.SessionAuthentication', - 'rest_framework.authentication.TokenAuthentication', - 'rest_framework_simplejwt.authentication.JWTAuthentication', - ), - 'EXCEPTION_HANDLER': 'config.exception_handler.custom_exception_handler', -} - -SIMPLE_JWT = { - 'ACCESS_TOKEN_LIFETIME': datetime.timedelta(minutes=10), - 'REFRESH_TOKEN_LIFETIME': datetime.timedelta(days=180), - - 'ALGORITHM': 'HS256', - 'SIGNING_KEY': SECRET_KEY, - - 'AUTH_HEADER_TYPES': ('Bearer',), - 'USER_ID_FIELD': 'id', - 'USER_ID_CLAIM': 'user_id', - 'USER_AUTHENTICATION_RULE': 'rest_framework_simplejwt.authentication.default_user_authentication_rule', - - 'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',), - 'TOKEN_TYPE_CLAIM': 'token_type', - - 'JTI_CLAIM': 'jti', - 'TOKEN_USER_CLASS': 'rest_framework_simplejwt.models.TokenUser', -} diff --git a/backend/config/urls.py b/backend/config/urls.py deleted file mode 100644 index 51671bd5..00000000 --- a/backend/config/urls.py +++ /dev/null @@ -1,9 +0,0 @@ -from django.urls import path, include -from django.contrib import admin - -urlpatterns = [ - path('admin/', admin.site.urls), - path('user/', include('user.urls')), - path('setting/', include('setup.urls', namespace='default')), - path('symbol/', include('entry.urls')), -] diff --git a/backend/config/utils.py b/backend/config/utils.py deleted file mode 100644 index 4e3999a4..00000000 --- a/backend/config/utils.py +++ /dev/null @@ -1,4 +0,0 @@ -from rest_framework_simplejwt.tokens import BlacklistMixin, AccessToken - -class AccessToken(BlacklistMixin, AccessToken): - pass diff --git a/backend/config/wsgi.py b/backend/config/wsgi.py deleted file mode 100644 index a9afbb3d..00000000 --- a/backend/config/wsgi.py +++ /dev/null @@ -1,16 +0,0 @@ -""" -WSGI config for config project. - -It exposes the WSGI callable as a module-level variable named ``application``. - -For more information on this file, see -https://docs.djangoproject.com/en/4.2/howto/deployment/wsgi/ -""" - -import os - -from django.core.wsgi import get_wsgi_application - -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings") - -application = get_wsgi_application() diff --git a/backend/entry/__init__.py b/backend/entry/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/backend/entry/admin.py b/backend/entry/admin.py deleted file mode 100644 index 8c38f3f3..00000000 --- a/backend/entry/admin.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.contrib import admin - -# Register your models here. diff --git a/backend/entry/apps.py b/backend/entry/apps.py deleted file mode 100644 index db982d9e..00000000 --- a/backend/entry/apps.py +++ /dev/null @@ -1,6 +0,0 @@ -from django.apps import AppConfig - - -class EntryConfig(AppConfig): - default_auto_field = 'django.db.models.BigAutoField' - name = 'entry' diff --git a/backend/entry/migrations/0001_initial.py b/backend/entry/migrations/0001_initial.py deleted file mode 100644 index 87c6a917..00000000 --- a/backend/entry/migrations/0001_initial.py +++ /dev/null @@ -1,43 +0,0 @@ -# Generated by Django 3.2.6 on 2023-10-13 16:16 - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ] - - operations = [ - migrations.CreateModel( - name='Category', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('text', models.CharField(max_length=15)), - ], - ), - migrations.CreateModel( - name='Symbol', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('text', models.CharField(max_length=15)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='symbols', to='entry.category')), - ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='symbols', to=settings.AUTH_USER_MODEL)), - ], - ), - migrations.CreateModel( - name='FavoriteSymbol', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('symbol', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='favorites', to='entry.symbol')), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='favorites', to=settings.AUTH_USER_MODEL)), - ], - ), - ] diff --git a/backend/entry/migrations/__init__.py b/backend/entry/migrations/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/backend/entry/models.py b/backend/entry/models.py deleted file mode 100644 index e9abf664..00000000 --- a/backend/entry/models.py +++ /dev/null @@ -1,24 +0,0 @@ -from django.db import models - -from user.models import User - - -# Create your models here. -class Symbol(models.Model): - text = models.CharField(max_length=15, null=False, blank=False) - category = models.ForeignKey('Category', related_name='symbols', on_delete=models.CASCADE) # Would it be better to use SET_NULL/DEFAULT? - # image = models.ImageField - created_by = models.ForeignKey('user.User', related_name='symbols', on_delete=models.CASCADE) - created_at = models.DateTimeField(auto_now_add=True) - - -class FavoriteSymbol(models.Model): - symbol = models.ForeignKey('Symbol', related_name='favorites', on_delete=models.CASCADE) - user = models.ForeignKey('user.User', related_name='favorites', on_delete=models.CASCADE) - created_at = models.DateTimeField(auto_now_add=True) - - -# Would it be better to remove this category table? -# doesn't seem so useful.. -class Category(models.Model): - text = models.CharField(max_length=15, null=False, blank=False) diff --git a/backend/entry/serializers.py b/backend/entry/serializers.py deleted file mode 100644 index 9d4e2119..00000000 --- a/backend/entry/serializers.py +++ /dev/null @@ -1,30 +0,0 @@ -from rest_framework import serializers -from rest_framework.exceptions import ValidationError - -from entry.models import FavoriteSymbol, Symbol - - -class FavoriteBackupSerializer(serializers.Serializer): - # symbol_id - id = serializers.IntegerField(source='symbol_id', required=True) - - def validate(self, data): - id = data.get('symbol_id') - # Symbol table에 저장된 마지막 symbol의 id - last_symbol_id = Symbol.objects.latest('id').id - - if id not in list(range(1, last_symbol_id+1)): - raise ValidationError({"id": ["Invalid symbol (no such symbol)"]}) - - return data - - def create(self, validated_data): - user = self.context['user'] - symbol_id = validated_data.get('symbol_id') - symbol = Symbol.objects.get(id=symbol_id) - - # if the symbol is not registered as favorite - if not FavoriteSymbol.objects.filter(user=user, symbol=symbol).exists(): - FavoriteSymbol.objects.create(user=user, symbol=symbol) - - diff --git a/backend/entry/tests.py b/backend/entry/tests.py deleted file mode 100644 index 7ce503c2..00000000 --- a/backend/entry/tests.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.test import TestCase - -# Create your tests here. diff --git a/backend/entry/urls.py b/backend/entry/urls.py deleted file mode 100644 index 73e209b5..00000000 --- a/backend/entry/urls.py +++ /dev/null @@ -1,8 +0,0 @@ -from django.urls import path -from . import views - - -app_name = 'entry' -urlpatterns = [ - path('favorite/backup/', views.FavoriteBackupView.as_view(), name='backup favorite symbol'), -] diff --git a/backend/entry/views.py b/backend/entry/views.py deleted file mode 100644 index f486c80a..00000000 --- a/backend/entry/views.py +++ /dev/null @@ -1,47 +0,0 @@ -from rest_framework import permissions, status -from rest_framework.response import Response -from rest_framework.views import APIView - -from entry.models import FavoriteSymbol, Symbol -from entry.serializers import FavoriteBackupSerializer - - -class FavoriteBackupView(APIView): - permission_classes = (permissions.IsAuthenticated,) - - def post(self, request): - user = request.user - data = request.data - - serializer = FavoriteBackupSerializer(data=data, context={'user': user}, many=True) - serializer.is_valid(raise_exception=True) - serializer.save() - - # Delete favorite-symbol if user undid favorite-symbol registration - # Load all the favorite symbols (id values) of the user - # symbol_ids ultimately contains symbols to delete - favorite_symbols = FavoriteSymbol.objects.filter(user=user).values('symbol_id') - symbol_ids = [item['symbol_id'] for item in favorite_symbols] - - # Remove symbols that user tries to backup from the symbol_ids list - try: - for item in serializer.validated_data: - symbol_ids.remove(item.get('symbol_id')) - except ValueError: - pass - - # Now, symbol_ids contains the symbol ids to delete - for id in symbol_ids: - symbol_to_delete = Symbol.objects.get(id=id) - FavoriteSymbol.objects.get(user=user, symbol=symbol_to_delete).delete() - - return Response(status=status.HTTP_200_OK) - - def get(self, request): - user = request.user - favorites = FavoriteSymbol.objects.filter(user=user) - response_data = FavoriteBackupSerializer(favorites, many=True).data - response_data = { - "results": response_data - } - return Response(response_data, status=status.HTTP_200_OK) diff --git a/backend/manage.py b/backend/manage.py deleted file mode 100755 index d28672ea..00000000 --- a/backend/manage.py +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env python -"""Django's command-line utility for administrative tasks.""" -import os -import sys - - -def main(): - """Run administrative tasks.""" - os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings") - try: - from django.core.management import execute_from_command_line - except ImportError as exc: - raise ImportError( - "Couldn't import Django. Are you sure it's installed and " - "available on your PYTHONPATH environment variable? Did you " - "forget to activate a virtual environment?" - ) from exc - execute_from_command_line(sys.argv) - - -if __name__ == "__main__": - main() diff --git a/backend/requirements.txt b/backend/requirements.txt deleted file mode 100644 index c167be97..00000000 --- a/backend/requirements.txt +++ /dev/null @@ -1,13 +0,0 @@ -asgiref==3.7.2 -cffi==1.15.1 -mysqlclient==2.2.0 -Django==4.2.5 -djangorestframework==3.14.0 -djangorestframework-simplejwt==5.3.0 -django-rest-authtoken==2.1.4 -docutils==0.20.1 -pycparser==2.21 -pytz==2023.3.post1 -six==1.16.0 -sqlparse==0.4.4 -PyJWT==2.8.0 \ No newline at end of file diff --git a/backend/setup/__init__.py b/backend/setup/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/backend/setup/admin.py b/backend/setup/admin.py deleted file mode 100644 index 8c38f3f3..00000000 --- a/backend/setup/admin.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.contrib import admin - -# Register your models here. diff --git a/backend/setup/apps.py b/backend/setup/apps.py deleted file mode 100644 index 13d6f446..00000000 --- a/backend/setup/apps.py +++ /dev/null @@ -1,6 +0,0 @@ -from django.apps import AppConfig - - -class SetupConfig(AppConfig): - default_auto_field = 'django.db.models.BigAutoField' - name = 'setup' diff --git a/backend/setup/migrations/0001_initial.py b/backend/setup/migrations/0001_initial.py deleted file mode 100644 index 1d530ea1..00000000 --- a/backend/setup/migrations/0001_initial.py +++ /dev/null @@ -1,26 +0,0 @@ -# Generated by Django 3.2.6 on 2023-10-13 16:16 - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ] - - operations = [ - migrations.CreateModel( - name='Setting', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('display_mode', models.IntegerField(choices=[(0, 'light'), (1, 'dark')], default=0)), - ('default_menu', models.IntegerField(choices=[(0, 'symbol'), (1, 'tts')], default=0)), - ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='settings', to=settings.AUTH_USER_MODEL)), - ], - ), - ] diff --git a/backend/setup/migrations/__init__.py b/backend/setup/migrations/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/backend/setup/models.py b/backend/setup/models.py deleted file mode 100644 index 34a41a00..00000000 --- a/backend/setup/models.py +++ /dev/null @@ -1,20 +0,0 @@ -from django.db import models - - -# Create your models here. -class Setting(models.Model): - DISPLAY_CHOICE = ( - (0, 'light'), - (1, 'dark'), - ) - - MENU_CHOICE = ( - (0, 'symbol'), - (1, 'tts'), - ) - - user = models.OneToOneField('user.User', related_name='settings', on_delete=models.CASCADE) - display_mode = models.IntegerField(null=False, default=0, choices=DISPLAY_CHOICE) - default_menu = models.IntegerField(null=False, default=0, choices=MENU_CHOICE) - - diff --git a/backend/setup/serializers.py b/backend/setup/serializers.py deleted file mode 100644 index de66b8bf..00000000 --- a/backend/setup/serializers.py +++ /dev/null @@ -1,18 +0,0 @@ -from rest_framework import serializers -from rest_framework.exceptions import ValidationError - -from setup.models import Setting - - -class SettingBackupSerializer(serializers.Serializer): - display_mode = serializers.IntegerField(required=True) - default_menu = serializers.IntegerField(required=True) - - def validate(self, data): - display_mode = data.get('display_mode') - default_menu = data.get('default_menu') - if display_mode not in [0, 1]: - raise ValidationError({"display_mode": ["invalid display_mode (not 0 or 1)"]}) - if default_menu not in [0, 1]: - raise ValidationError({"default_menu": ["invalid default_menu (not 0 or 1)"]}) - return data diff --git a/backend/setup/tests.py b/backend/setup/tests.py deleted file mode 100644 index 7ce503c2..00000000 --- a/backend/setup/tests.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.test import TestCase - -# Create your tests here. diff --git a/backend/setup/urls.py b/backend/setup/urls.py deleted file mode 100644 index 57ac9af4..00000000 --- a/backend/setup/urls.py +++ /dev/null @@ -1,8 +0,0 @@ -from django.urls import path -from . import views - - -app_name = 'setup' -urlpatterns = [ - path('backup/', views.SettingBackupView.as_view(), name='backup settings'), -] diff --git a/backend/setup/views.py b/backend/setup/views.py deleted file mode 100644 index 9e999935..00000000 --- a/backend/setup/views.py +++ /dev/null @@ -1,43 +0,0 @@ -from rest_framework import permissions, status -from rest_framework.response import Response -from rest_framework.views import APIView -from setup.models import Setting -from setup.serializers import SettingBackupSerializer - - -# Create your views here. -class SettingBackupView(APIView): - permission_classes = (permissions.IsAuthenticated,) - - def post(self, request): - user = request.user - - serializer = SettingBackupSerializer(data=request.data) - serializer.is_valid(raise_exception=True) - display_mode = serializer.validated_data['display_mode'] - default_menu = serializer.validated_data['default_menu'] - - if not Setting.objects.filter(user=user).exists(): - Setting.objects.create(display_mode=display_mode, default_menu=default_menu, user=user) - else: - curr_setting = Setting.objects.get(user=user) - curr_setting.display_mode = display_mode - curr_setting.default_menu = default_menu - curr_setting.save() - - return Response(status=status.HTTP_200_OK) - - def get(self, request): - user = request.user - - if not Setting.objects.filter(user=user).exists(): - response_data = { - "display_mode": 0, - "default_menu": 0 - } - else: - curr_setting = Setting.objects.get(user=user) - response_data = SettingBackupSerializer(curr_setting).data - - return Response(response_data, status=status.HTTP_200_OK) - diff --git a/backend/user/__init__.py b/backend/user/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/backend/user/admin.py b/backend/user/admin.py deleted file mode 100644 index 8c38f3f3..00000000 --- a/backend/user/admin.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.contrib import admin - -# Register your models here. diff --git a/backend/user/apps.py b/backend/user/apps.py deleted file mode 100644 index 36cce4c8..00000000 --- a/backend/user/apps.py +++ /dev/null @@ -1,6 +0,0 @@ -from django.apps import AppConfig - - -class UserConfig(AppConfig): - default_auto_field = 'django.db.models.BigAutoField' - name = 'user' diff --git a/backend/user/backends.py b/backend/user/backends.py deleted file mode 100644 index bd549da3..00000000 --- a/backend/user/backends.py +++ /dev/null @@ -1,15 +0,0 @@ -from django.contrib.auth import get_user_model -from django.contrib.auth.backends import ModelBackend - - -class EmailBackend(ModelBackend): - def authenticate(self, request, email=None, password=None, **kwargs): - UserModel = get_user_model() - try: - user = UserModel.objects.get(email=email) - except UserModel.DoesNotExist: - return None - else: - if user.check_password(password): - return user - return None \ No newline at end of file diff --git a/backend/user/migrations/0001_initial.py b/backend/user/migrations/0001_initial.py deleted file mode 100644 index 4a5d0512..00000000 --- a/backend/user/migrations/0001_initial.py +++ /dev/null @@ -1,70 +0,0 @@ -# Generated by Django 4.2.5 on 2023-10-06 01:58 - -from django.db import migrations, models -import user.models - - -class Migration(migrations.Migration): - initial = True - - dependencies = [ - ("auth", "0012_alter_user_first_name_max_length"), - ] - - operations = [ - migrations.CreateModel( - name="User", - fields=[ - ( - "id", - models.BigAutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ("password", models.CharField(max_length=128, verbose_name="password")), - ( - "last_login", - models.DateTimeField( - blank=True, null=True, verbose_name="last login" - ), - ), - ("email", models.EmailField(max_length=50, unique=True)), - ("nickname", models.CharField(max_length=15)), - ("is_active", models.BooleanField(default=True)), - ("is_superuser", models.BooleanField(default=False)), - ("updated_at", models.DateTimeField(null=True)), - ("created_at", models.DateTimeField(auto_now_add=True)), - ( - "groups", - models.ManyToManyField( - blank=True, - help_text="The groups this user belongs to. A user will get all permissions granted to each of their groups.", - related_name="user_set", - related_query_name="user", - to="auth.group", - verbose_name="groups", - ), - ), - ( - "user_permissions", - models.ManyToManyField( - blank=True, - help_text="Specific permissions for this user.", - related_name="user_set", - related_query_name="user", - to="auth.permission", - verbose_name="user permissions", - ), - ), - ], - options={ - "abstract": False, - }, - managers=[ - ("objects", user.models.CustomUserManager()), - ], - ), - ] diff --git a/backend/user/migrations/0002_emailverification.py b/backend/user/migrations/0002_emailverification.py deleted file mode 100644 index 33ec2b56..00000000 --- a/backend/user/migrations/0002_emailverification.py +++ /dev/null @@ -1,22 +0,0 @@ -# Generated by Django 3.2.6 on 2023-10-07 10:14 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('user', '0001_initial'), - ] - - operations = [ - migrations.CreateModel( - name='EmailVerification', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('email', models.EmailField(max_length=50, unique=True)), - ('code', models.CharField(max_length=6)), - ('created_at', models.DateTimeField(auto_now=True)), - ], - ), - ] diff --git a/backend/user/migrations/__init__.py b/backend/user/migrations/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/backend/user/models.py b/backend/user/models.py deleted file mode 100644 index 1c6c8dbd..00000000 --- a/backend/user/models.py +++ /dev/null @@ -1,60 +0,0 @@ -from django.contrib.auth.base_user import BaseUserManager, AbstractBaseUser -from django.contrib.auth.models import PermissionsMixin -from django.db import models - - -class CustomUserManager(BaseUserManager): - use_in_migrations = True - - def _create_user(self, nickname, email, password, **extra_fields): - if not email: - raise ValueError('이메일을 입력해주세요.') - if not nickname: - raise ValueError('닉네임을 입력해주세요.') - - email = self.normalize_email(email) - user = self.model(nickname=nickname, email=email, **extra_fields) - user.set_password(password) - user.save(force_insert=True, using=self._db) - return user - - def create_user(self, nickname, email, password, **extra_fields): - extra_fields.setdefault('is_superuser', False) - - return self._create_user(nickname, email, password, **extra_fields) - - def create_superuser(self, nickname, email, password, **extra_fields): - extra_fields.setdefault('is_superuser', True) - - if extra_fields.get('is_superuser') is not True: - raise ValueError('권한 설정이 잘못되었습니다.') - - return self._create_user(nickname, email, password, **extra_fields) - - -class User(AbstractBaseUser, PermissionsMixin): - objects = CustomUserManager() - - email = models.EmailField(max_length=50, unique=True, null=False, blank=False) - nickname = models.CharField(max_length=15, null=False) - is_active = models.BooleanField(default=True) - is_superuser = models.BooleanField(default=False) - updated_at = models.DateTimeField(null=True) - created_at = models.DateTimeField(auto_now_add=True) - - USERNAME_FIELD = 'email' - # python manage.py createsuperuser로 사용자를 만들 때 필수로 입력하게 되는 필드 리스트 - # USERNAME_FIELD와 password는 항상 입력이 요구됨 - REQUIRED_FIELDS = ['nickname'] - - def __str__(self): - return self.nickname - - def get_short_name(self): - return self.email - - -class EmailVerification(models.Model): - email = models.EmailField(max_length=50, unique=True, null=False, blank=False) - code = models.CharField(max_length=6, null=False, blank=False) - created_at = models.DateTimeField(auto_now=True) diff --git a/backend/user/serializers.py b/backend/user/serializers.py deleted file mode 100644 index 89dacc76..00000000 --- a/backend/user/serializers.py +++ /dev/null @@ -1,151 +0,0 @@ -from django.contrib.auth import get_user_model, authenticate -from rest_framework import serializers -from rest_framework.exceptions import ValidationError -from rest_framework_simplejwt.serializers import TokenObtainPairSerializer - -from user.models import EmailVerification -from user.utils import normalize_email - -User = get_user_model() - - -class UserSignUpSerializer(serializers.Serializer): - email = serializers.EmailField(required=True, max_length=50) - password = serializers.CharField(required=True) - nickname = serializers.CharField(required=True, max_length=15) - - def validate(self, data): - pw = data.get('password') - if len(pw) < 8: - raise ValidationError({"short_pw": ["password unavailable (short password)"]}) - - email = data.get('email') - - if User.objects.filter(email=email).exists(): - raise ValidationError({"already_taken": ["email address unavailable (already taken)"]}) - return data - - def create(self, validated_data): - email = validated_data.get('email') - password = validated_data.get('password') - nickname = validated_data.get('nickname') - user = User.objects.create_user(nickname, email, password) - return user - - -class EmailCheckSerializer(serializers.Serializer): - email = serializers.EmailField(required=True, max_length=50) - - def validate(self, data): - email = normalize_email(data.get('email')) - if User.objects.filter(email=email).exists(): - raise ValidationError({"already_taken": ["email address unavailable (already taken)"]}) - - return data - - -# Checks whether any user exists with a particular email -class UserCheckSerializer(serializers.Serializer): - email = serializers.EmailField(required=True, max_length=50) - - def validate(self, data): - email = normalize_email(data.get('email')) - if not User.objects.filter(email=email).exists(): - raise ValidationError({"no_user": ["no such user w/ the email"]}) - - return data - - -class CodeCheckSerializer(serializers.Serializer): - email = serializers.EmailField(required=True, max_length=50) - code = serializers.CharField(required=True, max_length=6) - - def validate(self, data): - email = normalize_email(data.get('email')) - code = data.get('code') - if not len(code) == 6: - raise ValidationError({"code": ["Invalid code length(should be 6)"]}) - - if not EmailVerification.objects.filter(email=email, code=code).exists(): - raise ValidationError({"fail": ["wrong code"]}) - else: - # successfully verified - verification = EmailVerification.objects.get(email=email, code=code) - verification.delete() - return data - - -class UserLoginSerializer(serializers.Serializer): - email = serializers.EmailField(required=True) - password = serializers.CharField(write_only=True) - token = serializers.CharField(max_length=255, read_only=True) - - def validate(self, data): - email = data.get('email', None) - if not User.objects.filter(email=email).exists(): - raise ValidationError({"wrong_email": ["wrong email address"]}) - - password = data.get('password', None) - user = authenticate(email=email, password=password) - if user is None: - raise ValidationError({"wrong_password": ["wrong password"]}) - - token = TokenObtainPairSerializer.get_token(user) - refresh = str(token) - access = str(token.access_token) - jwt_token = { - 'access': access, - 'refresh': refresh - } - - return { - 'token': jwt_token - } - - -class UserLogoutSerializer(serializers.Serializer): - refresh = serializers.CharField(required=True) - - -class UserProfileSerializer(serializers.ModelSerializer): - class Meta: - model = User - fields = ( - 'id', - 'email', - 'nickname', - 'updated_at', - ) - - -class PasswordUpdateSerializer(serializers.Serializer): - password = serializers.CharField(required=True) - - def validate(self, data): - password = data.get('password') - if len(password) < 8: - raise ValidationError({"short_pw": ["password unavailable (short password)"]}) - return data - - def update(self, user, validated_data): - password = validated_data.get('password') - user.set_password(password) - user.save() - return user - - -class NicknameUpdateSerializer(serializers.Serializer): - nickname = serializers.CharField(required=True, max_length=15) - - def validate(self, data): - user = self.context['user'] - nickname = data.get('nickname') - if user.nickname == nickname: - raise ValidationError({"same": ["The new nickname is the same as the original one"]}) - return data - - def update(self, user, validated_data): - nickname = validated_data.get('nickname') - user.nickname = nickname - user.save() - return user diff --git a/backend/user/test_views.py b/backend/user/test_views.py deleted file mode 100644 index dae0cad8..00000000 --- a/backend/user/test_views.py +++ /dev/null @@ -1,55 +0,0 @@ -from unittest import TestCase - - -class TestUserSignUpView(TestCase): - def test_post(self): - self.assertEqual(1, 1) - -# class TestSignUpEmailVerifySendView(TestCase): -# def test_post(self): -# self.fail() -# -# -# class TestPasswordEmailVerifySendView(TestCase): -# def test_post(self): -# self.fail() -# -# -# class TestSignUpEmailVerifyAcceptView(TestCase): -# def test_post(self): -# self.fail() -# -# -# class TestPasswordEmailVerifyAcceptView(TestCase): -# def test_post(self): -# self.fail() -# -# -# class TestUserLoginView(TestCase): -# def test_post(self): -# self.fail() -# -# -# class TestUserLogoutView(TestCase): -# def test_post(self): -# self.fail() -# -# -# class TestUserProfileView(TestCase): -# def test_get(self): -# self.fail() -# -# -# class TestPasswordUpdateView(TestCase): -# def test_patch(self): -# self.fail() -# -# -# class TestNicknameUpdateView(TestCase): -# def test_patch(self): -# self.fail() -# -# -# class TestUserWithdrawView(TestCase): -# def test_post(self): -# self.fail() diff --git a/backend/user/tests.py b/backend/user/tests.py deleted file mode 100644 index 7ce503c2..00000000 --- a/backend/user/tests.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.test import TestCase - -# Create your tests here. diff --git a/backend/user/urls.py b/backend/user/urls.py deleted file mode 100644 index e917f845..00000000 --- a/backend/user/urls.py +++ /dev/null @@ -1,21 +0,0 @@ -from django.urls import path -from rest_framework_simplejwt.views import TokenRefreshView - -from . import views - - -app_name='user' -urlpatterns = [ - path('signup/', views.UserSignUpView.as_view(), name='signup'), - path('validateemail/signup/send/', views.SignUpEmailVerifySendView.as_view(), name='send email verification code for signup'), - path('validateemail/pw/send/', views.PasswordEmailVerifySendView.as_view(), name='send email verification code for forgot-pw'), - path('validateemail/signup/accept/', views.SignUpEmailVerifyAcceptView.as_view(), name='accept email verification code for signup'), - path('validateemail/pw/accept/', views.PasswordEmailVerifyAcceptView.as_view(), name='accept email verification code for forgot-pw'), - path('login/', views.UserLoginView.as_view(), name='login'), - path('refresh/', TokenRefreshView.as_view(), name='token refresh'), - path('logout/', views.UserLogoutView.as_view(), name='logout'), - path('profile/', views.UserProfileView.as_view(), name='get profile'), - path('profile/nickname/', views.NicknameUpdateView.as_view(), name='change nickname'), - path('profile/password/', views.PasswordUpdateView.as_view(), name='change password'), - path('withdraw/', views.UserWithdrawView.as_view(), name='withdraw') -] diff --git a/backend/user/utils.py b/backend/user/utils.py deleted file mode 100644 index 872935e8..00000000 --- a/backend/user/utils.py +++ /dev/null @@ -1,30 +0,0 @@ -import string -import random - - -def normalize_email(email): - try: - email_name, domain_part = email.strip().rsplit("@", 1) - except ValueError: - pass - else: - email = email_name + "@" + domain_part.lower() - return email - - -def generate_code(): - LENGTH = 6 - seed = string.ascii_letters + string.digits - code = "" - - for i in range(LENGTH): - code += random.choice(seed) - - return code - - -def message(code): - return f"안녕하세요, 스피치버디입니다." \ - f"\n아래 인증번호를 앱에 입력하시면 이메일 인증이 완료됩니다." \ - f"\n\n인증번호: {code}" \ - f"\n\n감사합니다." diff --git a/backend/user/views.py b/backend/user/views.py deleted file mode 100644 index 1c20f8ee..00000000 --- a/backend/user/views.py +++ /dev/null @@ -1,185 +0,0 @@ -from django.contrib.auth import get_user_model -from django.core.mail import EmailMessage -from rest_framework import status, permissions -from rest_framework.views import APIView -from rest_framework.response import Response -from rest_framework_simplejwt.serializers import TokenObtainPairSerializer -from rest_framework_simplejwt.tokens import RefreshToken - -from config.utils import AccessToken -from .models import EmailVerification - -from .serializers import UserSignUpSerializer, UserLoginSerializer, UserLogoutSerializer, EmailCheckSerializer, \ - UserProfileSerializer, PasswordUpdateSerializer, NicknameUpdateSerializer, CodeCheckSerializer, UserCheckSerializer -from .utils import generate_code, message - -User = get_user_model() - - -class UserSignUpView(APIView): - permission_classes = (permissions.AllowAny,) - - def post(self, request): - serializer = UserSignUpSerializer(data=request.data) - serializer.is_valid(raise_exception=True) - serializer.save() - - return Response(status=status.HTTP_201_CREATED) - - -class SignUpEmailVerifySendView(APIView): - permission_classes = (permissions.AllowAny,) - - def post(self, request): - serializer = EmailCheckSerializer(data=request.data) - serializer.is_valid(raise_exception=True) - email = serializer.validated_data['email'] - code = generate_code() - message_data = message(code) - - mail_title = "Speech Buddy 회원가입 인증 메일입니다." - mail_to = email - EmailMessage(mail_title, message_data, to=[mail_to]).send() - - if not EmailVerification.objects.filter(email=email).exists(): - EmailVerification.objects.create(email=email, code=code) - else: - verification = EmailVerification.objects.get(email=email) - verification.code = code - verification.save() - - return Response(status=status.HTTP_200_OK) - - -# Would it be better to reduce duplication with the View above? -class PasswordEmailVerifySendView(APIView): - permission_classes = (permissions.AllowAny,) - - def post(self, request): - serializer = UserCheckSerializer(data=request.data) - serializer.is_valid(raise_exception=True) - email = serializer.validated_data['email'] - code = generate_code() - message_data = message(code) - - mail_title = "Speech Buddy 비밀번호 재설정 메일입니다." - mail_to = email - EmailMessage(mail_title, message_data, to=[mail_to]).send() - - if not EmailVerification.objects.filter(email=email).exists(): - EmailVerification.objects.create(email=email, code=code) - else: - verification = EmailVerification.objects.get(email=email) - verification.code = code - verification.save() - - return Response(status=status.HTTP_200_OK) - - -class SignUpEmailVerifyAcceptView(APIView): - permission_classes = (permissions.AllowAny,) - - def post(self, request): - serializer = CodeCheckSerializer(data=request.data) - serializer.is_valid(raise_exception=True) - return Response(status=status.HTTP_200_OK) - - -class PasswordEmailVerifyAcceptView(APIView): - permission_classes = (permissions.AllowAny,) - - def post(self, request): - serializer = CodeCheckSerializer(data=request.data) - serializer.is_valid(raise_exception=True) - - email = serializer.validated_data.get('email') - user = User.objects.get(email=email) - token = TokenObtainPairSerializer.get_token(user) - refresh = RefreshToken(str(token)) - access = str(token.access_token) - - # Blacklist refresh token - # That is, the user only gets access token (it means temporary-login so as to utilize password-update-view) - refresh.blacklist() - - access_token = { - 'access': access - } - - return Response(access_token, status=status.HTTP_200_OK) - - -class UserLoginView(APIView): - permission_classes = (permissions.AllowAny,) - - def post(self, request): - serializer = UserLoginSerializer(data=request.data) - serializer.is_valid(raise_exception=True) - - token = serializer.validated_data['token'] - - return Response(token, status=status.HTTP_200_OK) - - -class UserLogoutView(APIView): - permission_classes = (permissions.IsAuthenticated, ) - - def post(self, request): - serializer = UserLogoutSerializer(data=request.data) - serializer.is_valid(raise_exception=True) - - refresh_token = RefreshToken(serializer.validated_data['refresh']) - access_token = AccessToken(request.META.get('HTTP_AUTHORIZATION').split()[1]) - refresh_token.blacklist() - access_token.blacklist() - return Response(status=status.HTTP_200_OK) - - -class UserProfileView(APIView): - permission_classes = (permissions.IsAuthenticated,) - - def get(self, request): - user = request.user - serialized_user = UserProfileSerializer(user).data - response_data = {"user": serialized_user} - return Response(response_data, status=status.HTTP_200_OK) - - -class PasswordUpdateView(APIView): - permission_classes = (permissions.IsAuthenticated,) - - def patch(self, request): - user = request.user - data = request.data - password_serializer = PasswordUpdateSerializer(user, data=data, context={'user': user}) - password_serializer.is_valid(raise_exception=True) - password_serializer.save() - return Response(status=status.HTTP_200_OK) - - -class NicknameUpdateView(APIView): - permission_classes = (permissions.IsAuthenticated,) - - def patch(self, request): - user = request.user - data = request.data - nickname_serializer = NicknameUpdateSerializer(user, data=data, context={'user': user}) - nickname_serializer.is_valid(raise_exception=True) - nickname_serializer.save() - return Response(status=status.HTTP_200_OK) - - -class UserWithdrawView(APIView): - permission_classes = (permissions.IsAuthenticated, ) - - def post(self, request): - # Don't know why, but if we attempt to delete the user after blacklisting the token, - # the blacklisting doesn't work properly as expected - request.user.delete() - - serializer = UserLogoutSerializer(data=request.data) - serializer.is_valid(raise_exception=True) - refresh_token = RefreshToken(serializer.validated_data['refresh']) - refresh_token.blacklist() - - return Response(status=status.HTTP_200_OK) \ No newline at end of file diff --git a/frontend/app/build.gradle.kts b/frontend/app/build.gradle.kts deleted file mode 100644 index 2968081b..00000000 --- a/frontend/app/build.gradle.kts +++ /dev/null @@ -1,120 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") - id("com.google.dagger.hilt.android") - id("kotlin-parcelize") - id("com.google.devtools.ksp") - id("kotlin-kapt") -} - -android { - namespace = "com.example.speechbuddy" - compileSdk = 34 - - defaultConfig { - applicationId = "com.example.speechbuddy" - minSdk = 24 - targetSdk = 34 - versionCode = 1 - versionName = "1.0" - - testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" - vectorDrawables { - useSupportLibrary = true - } - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles( - getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" - ) - } - } - compileOptions { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 - } - kotlinOptions { - jvmTarget = JavaVersion.VERSION_17.toString() - } - buildFeatures { - compose = true - } - composeOptions { - kotlinCompilerExtensionVersion = "1.4.3" - } - packaging { - resources { - excludes += "/META-INF/{AL2.0,LGPL2.1}" - } - } -} - -dependencies { - implementation("androidx.core:core-ktx:1.12.0") - implementation("androidx.activity:activity-compose:1.8.0") - implementation(platform("androidx.compose:compose-bom:2023.03.00")) - implementation("androidx.compose.ui:ui") - implementation("androidx.compose.ui:ui-graphics") - implementation("androidx.compose.ui:ui-tooling-preview") - implementation("androidx.compose.material3:material3") - testImplementation("junit:junit:4.13.2") - androidTestImplementation("androidx.test.ext:junit:1.1.5") - androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") - androidTestImplementation(platform("androidx.compose:compose-bom:2023.03.00")) - androidTestImplementation("androidx.compose.ui:ui-test-junit4") - debugImplementation("androidx.compose.ui:ui-tooling") - debugImplementation("androidx.compose.ui:ui-test-manifest") - - // Lifecycle - val lifecycleVersion = "2.6.2" - implementation("androidx.lifecycle:lifecycle-common:$lifecycleVersion") - implementation("androidx.lifecycle:lifecycle-runtime-ktx:$lifecycleVersion") - implementation("androidx.lifecycle:lifecycle-livedata-ktx:$lifecycleVersion") - implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycleVersion") - - // LiveData - implementation("androidx.compose.runtime:runtime-livedata:1.5.4") - - // Coroutines - val coroutinesVersion = "1.7.1" - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion") - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutinesVersion") - - // Preference - implementation("androidx.preference:preference-ktx:1.2.1") - - // Moshi - val moshiVersion = "1.10.0" - implementation("com.squareup.moshi:moshi:$moshiVersion") - implementation("com.squareup.moshi:moshi-kotlin:$moshiVersion") - ksp("com.squareup.moshi:moshi-kotlin-codegen:$moshiVersion") - - // RetroFit - val retrofitVersion = "2.9.0" - implementation("com.squareup.retrofit2:retrofit:$retrofitVersion") - implementation("com.squareup.retrofit2:converter-moshi:$retrofitVersion") - implementation("com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.1") - - // Room - val roomVersion = "2.5.2" - implementation("androidx.room:room-ktx:$roomVersion") - implementation("androidx.room:room-runtime:$roomVersion") - ksp("androidx.room:room-compiler:$roomVersion") - - // Navigation - val navigationVersion = "2.7.4" - implementation("androidx.navigation:navigation-ui-ktx:$navigationVersion") - implementation("androidx.navigation:navigation-compose:$navigationVersion") - implementation("androidx.navigation:navigation-runtime-ktx:$navigationVersion") - implementation("androidx.navigation:navigation-fragment-ktx:$navigationVersion") - - // Hilt - val hiltVersion = "2.46.1" - implementation("com.google.dagger:hilt-android:$hiltVersion") - kapt("com.google.dagger:hilt-compiler:$hiltVersion") - - implementation("androidx.hilt:hilt-navigation-compose:1.0.0") -} \ No newline at end of file diff --git a/frontend/app/proguard-rules.pro b/frontend/app/proguard-rules.pro deleted file mode 100644 index 481bb434..00000000 --- a/frontend/app/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/frontend/app/src/androidTest/java/com/example/speechbuddy/ExampleInstrumentedTest.kt b/frontend/app/src/androidTest/java/com/example/speechbuddy/ExampleInstrumentedTest.kt deleted file mode 100644 index 90e1f823..00000000 --- a/frontend/app/src/androidTest/java/com/example/speechbuddy/ExampleInstrumentedTest.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.example.speechbuddy - -import androidx.test.platform.app.InstrumentationRegistry -import androidx.test.ext.junit.runners.AndroidJUnit4 - -import org.junit.Test -import org.junit.runner.RunWith - -import org.junit.Assert.* - -/** - * Instrumented test, which will execute on an Android device. - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -@RunWith(AndroidJUnit4::class) -class ExampleInstrumentedTest { - @Test - fun useAppContext() { - // Context of the app under test. - val appContext = InstrumentationRegistry.getInstrumentation().targetContext - assertEquals("com.example.speechbuddy", appContext.packageName) - } -} \ No newline at end of file diff --git a/frontend/app/src/main/AndroidManifest.xml b/frontend/app/src/main/AndroidManifest.xml deleted file mode 100644 index 6694b15c..00000000 --- a/frontend/app/src/main/AndroidManifest.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/frontend/app/src/main/ic_launcher-playstore.png b/frontend/app/src/main/ic_launcher-playstore.png deleted file mode 100644 index 1e4b5742ab3c91e500200b39927c166d92654098..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 64878 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 MW%%E(`wn6M2W4u - val source = backStackEntry.arguments?.getString("source") - EmailVerificationScreen( - source = source, - onBackClick = { - navController.navigateUp() - }, - navController = navController, - ) - } - composable("signup/{emailInput}") { backStackEntry -> - val emailInput = backStackEntry.arguments?.getString("emailInput") - SignupScreen( - onBackClick = { - navController.navigateUp() - }, - email = emailInput ?: "" - ) - } - composable("reset_password") { - ResetPasswordScreen( - onBackClick = { - navController.navigateUp() - }, - onNextClick = {} - ) - } - composable("home") { - HomeScreen() - } - } -} \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/emailverification/EmailVerificationScreen.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/emailverification/EmailVerificationScreen.kt deleted file mode 100644 index a9c90a07..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/emailverification/EmailVerificationScreen.kt +++ /dev/null @@ -1,128 +0,0 @@ -package com.example.speechbuddy.compose.emailverification - -import android.annotation.SuppressLint -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.navigation.NavHostController -import androidx.navigation.compose.rememberNavController -import com.example.speechbuddy.R -import com.example.speechbuddy.compose.utils.ButtonLevel -import com.example.speechbuddy.compose.utils.ButtonUi -import com.example.speechbuddy.compose.utils.TextFieldUi -import com.example.speechbuddy.compose.utils.TitleUi -import com.example.speechbuddy.compose.utils.TopAppBarUi -import com.example.speechbuddy.ui.SpeechBuddyTheme -import com.example.speechbuddy.ui.models.EmailVerificationErrorType -import com.example.speechbuddy.viewmodel.EmailVerificationViewModel - -@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun EmailVerificationScreen( - source: String?, - modifier: Modifier = Modifier, - onBackClick: () -> Unit, - navController: NavHostController, - viewModel: EmailVerificationViewModel = hiltViewModel() -) { - val uiState by viewModel.uiState.collectAsState() - val isEmailError = uiState.error?.type == EmailVerificationErrorType.EMAIL - val isVerifyCodeError = uiState.error?.type == EmailVerificationErrorType.VERIFY_CODE - val isError = isEmailError || isVerifyCodeError - - Surface( - modifier = modifier.fillMaxSize() - ) { - Scaffold( - topBar = { TopAppBarUi(onBackClick = onBackClick) } - ) { - Column( - modifier = Modifier - .fillMaxSize() - .padding(horizontal = 24.dp), - verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally - ) { - TitleUi( - title = when (source) { - "reset_password" -> stringResource(id = R.string.reset_password_title) - "signup" -> stringResource(id = R.string.verify_email_field) - else -> stringResource(id = R.string.verify_email_field) - }, - description = when (source) { - "reset_password" -> stringResource(id = R.string.reset_password_subtitle1) - "signup" -> stringResource(id = R.string.verify_email_explain) - else -> stringResource(id = R.string.verify_email_explain_default) - } - ) - - Spacer(modifier = Modifier.height(15.dp)) - - // Email Text Field - TextFieldUi( - value = viewModel.emailInput, - onValueChange = { viewModel.setEmail(it) }, - label = { Text(text = stringResource(id = R.string.email_field)) }, - supportingButton = { - ButtonUi( - text = stringResource(id = R.string.send_validation_code), - onClick = { viewModel.verifySend(source) }, - level = ButtonLevel.TERTIARY - ) - }, - supportingText = { - if (isEmailError) { - Text(stringResource(id = uiState.error!!.messageId)) - } else if(uiState.isSuccessfulSend) { - Text(stringResource(id = R.string.verification_code_sent)) - } - }, - isError = isError, - isValid = uiState.isValidEmail, - // If verification email is sent successfully, a user cannot change one's email input - isEnabled = !uiState.isSuccessfulSend - ) - - // Verify code Text Field - TextFieldUi( - value = viewModel.verifyCodeInput, - onValueChange = { viewModel.setVerifyCode(it) }, - label = { Text(text = stringResource(id = R.string.validation_code)) }, - supportingText = { - if (isVerifyCodeError) { - Text(stringResource(id = uiState.error!!.messageId)) - } - }, - isError = isError, - isValid = uiState.isValidVerifyCode, - isEnabled = uiState.isSuccessfulSend - ) - - Spacer(modifier = Modifier.height(15.dp)) - - ButtonUi( - text = stringResource(id = R.string.next), - onClick = { viewModel.verifyAccept(source, navController) }, - isEnabled = uiState.isSuccessfulSend - ) - } - } - } -} \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/home/HomeScreen.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/home/HomeScreen.kt deleted file mode 100644 index 55623c1c..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/home/HomeScreen.kt +++ /dev/null @@ -1,151 +0,0 @@ -package com.example.speechbuddy.compose.home - -import android.annotation.SuppressLint -import androidx.compose.foundation.layout.WindowInsets -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.size -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.NavigationBar -import androidx.compose.material3.NavigationBarItem -import androidx.compose.material3.NavigationBarItemDefaults -import androidx.compose.material3.Scaffold -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.navigation.NavController -import androidx.navigation.NavHostController -import androidx.navigation.compose.NavHost -import androidx.navigation.compose.composable -import androidx.navigation.compose.currentBackStackEntryAsState -import androidx.navigation.compose.rememberNavController -import com.example.speechbuddy.R -import com.example.speechbuddy.compose.settings.SettingsScreen -import com.example.speechbuddy.compose.symbolcreation.SymbolCreationScreen -import com.example.speechbuddy.compose.symbolselection.SymbolSelectionScreen -import com.example.speechbuddy.compose.texttospeech.TextToSpeechScreen -import com.example.speechbuddy.compose.utils.TopAppBarUi -import com.example.speechbuddy.ui.SpeechBuddyTheme - -data class BottomNavItem( - val route: String, - val nameResId: Int, - val iconResId: Int -) - -@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun HomeScreen( - -) { - val navController = rememberNavController() - val navItems = listOf( - BottomNavItem( - "symbol_selection", - R.string.symbol_selection, - R.drawable.outline_touch_app_24 - ), - BottomNavItem( - "text_to_speech", - R.string.text_to_speech, - R.drawable.outline_volume_up_24 - ), - BottomNavItem( - "symbol_creation", - R.string.symbol_creation, - R.drawable.outline_add_a_photo_24 - ), - BottomNavItem( - "settings", - R.string.settings, - R.drawable.outline_settings_24 - ) - ) - - Scaffold( - topBar = { - /* TODO: TopAppBar for HomeScreen */ - TopAppBarUi(onBackClick = { navController.navigateUp() }) - }, - bottomBar = { - BottomNavigationBar( - items = navItems, - navController = navController, - onItemClick = { - navController.navigate(it.route) - } - ) - } - ) { - HomeScreenNavHost( - navController = navController - ) - } -} - -@Composable -private fun BottomNavigationBar( - items: List, - navController: NavController, - onItemClick: (BottomNavItem) -> Unit -) { - val backStackEntry = navController.currentBackStackEntryAsState() - - NavigationBar( - modifier = Modifier.height(80.dp), - containerColor = MaterialTheme.colorScheme.secondaryContainer, - windowInsets = WindowInsets(top = 20.dp) - ) { - items.forEach { item -> - val selected = item.route == backStackEntry.value?.destination?.route - NavigationBarItem( - selected = selected, - onClick = { onItemClick(item) }, - icon = { - Icon( - painter = painterResource(id = item.iconResId), - contentDescription = stringResource(id = item.nameResId) - ) - }, - modifier = Modifier.size(40.dp), - colors = NavigationBarItemDefaults.colors( - selectedIconColor = MaterialTheme.colorScheme.onPrimaryContainer, - unselectedIconColor = MaterialTheme.colorScheme.outline - ) - ) - } - } -} - -@Composable -private fun HomeScreenNavHost( - navController: NavHostController -) { - NavHost(navController = navController, startDestination = "symbol_selection") { - composable("symbol_selection") { - SymbolSelectionScreen() - } - composable("text_to_speech") { - TextToSpeechScreen() - } - composable("symbol_creation") { - SymbolCreationScreen() - } - composable("settings") { - SettingsScreen() - } - } -} - -@Preview -@Composable -private fun HomeScreenPreview() { - SpeechBuddyTheme { - HomeScreen() - } -} \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/landing/LandingScreen.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/landing/LandingScreen.kt deleted file mode 100644 index 593a7a43..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/landing/LandingScreen.kt +++ /dev/null @@ -1,65 +0,0 @@ -package com.example.speechbuddy.compose.landing - -import androidx.compose.foundation.Image -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.example.speechbuddy.R -import com.example.speechbuddy.compose.utils.ButtonUi -import com.example.speechbuddy.ui.SpeechBuddyTheme - -@Composable -fun LandingScreen( - modifier: Modifier = Modifier, - onGuestClick: () -> Unit, - onLoginClick: () -> Unit, -) { - Surface( - modifier = modifier.fillMaxSize(), - color = MaterialTheme.colorScheme.primaryContainer - ) { - Box( - modifier = Modifier.size(200.dp), - contentAlignment = Alignment.Center - ) { - Image( - painter = painterResource(id = R.drawable.speechbuddy_parrot), - contentDescription = stringResource(id = R.string.app_name), - ) - } - Box( - modifier = Modifier.padding(horizontal = 24.dp, vertical = 64.dp), - contentAlignment = Alignment.BottomCenter - ) { - Column( - verticalArrangement = Arrangement.spacedBy(14.dp) - ) { - ButtonUi( - text = stringResource(id = R.string.guess_mode_action), - onClick = onGuestClick - ) - ButtonUi(text = stringResource(id = R.string.login_action), onClick = onLoginClick) - } - } - } -} - -@Preview -@Composable -private fun LandingScreenPreview() { - SpeechBuddyTheme { - LandingScreen(onGuestClick = {}, onLoginClick = {}) - } -} \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/login/LoginScreen.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/login/LoginScreen.kt deleted file mode 100644 index 3e33f77a..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/login/LoginScreen.kt +++ /dev/null @@ -1,126 +0,0 @@ -package com.example.speechbuddy.compose.login - -import android.annotation.SuppressLint -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.offset -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel -import com.example.speechbuddy.R -import com.example.speechbuddy.compose.utils.ButtonLevel -import com.example.speechbuddy.compose.utils.ButtonUi -import com.example.speechbuddy.compose.utils.TextFieldUi -import com.example.speechbuddy.compose.utils.TitleUi -import com.example.speechbuddy.compose.utils.TopAppBarUi -import com.example.speechbuddy.ui.models.LoginErrorType -import com.example.speechbuddy.viewmodel.LoginViewModel - -@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun LoginScreen( - modifier: Modifier = Modifier, - onBackClick: () -> Unit, - onResetPasswordClick: () -> Unit, - onSignupClick: () -> Unit, - viewModel: LoginViewModel = hiltViewModel() -) { - val uiState by viewModel.uiState.collectAsState() - val isEmailError = uiState.error?.type == LoginErrorType.EMAIL - val isPasswordError = uiState.error?.type == LoginErrorType.PASSWORD - val isError = isEmailError || isPasswordError - - Surface(modifier = modifier.fillMaxSize()) { - Scaffold( - topBar = { TopAppBarUi(onBackClick = onBackClick) } - ) { - Column( - modifier = Modifier - .padding(24.dp) - .fillMaxSize(), - verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally - ) { - TitleUi( - title = stringResource(id = R.string.login_text), - description = stringResource(id = R.string.login_explain) - ) - - Spacer(modifier = Modifier.height(15.dp)) - - // Email Text Field - TextFieldUi( - value = viewModel.emailInput, - onValueChange = { viewModel.setEmail(it) }, - label = { Text(stringResource(id = R.string.email_field)) }, - supportingText = { - if (isEmailError) { - Text(stringResource(id = uiState.error!!.messageId)) - } - }, - isError = isError, - isValid = uiState.isValidEmail - ) - - // Password Text Field - TextFieldUi( - value = viewModel.passwordInput, - onValueChange = { viewModel.setPassword(it) }, - label = { Text(stringResource(id = R.string.password_field)) }, - supportingText = { - if (isPasswordError) { - Text(stringResource(id = uiState.error!!.messageId)) - } - }, - isError = isError, - isValid = uiState.isValidPassword, - isHidden = true - ) - - Spacer(modifier = Modifier.height(20.dp)) - - // Login Button - ButtonUi( - text = stringResource(id = R.string.login_text), - onClick = { - viewModel.login() - }, - isEnabled = !isError, - isError = isError - ) - - Spacer(modifier = Modifier.height(10.dp)) - - // Forgot Password Button - ButtonUi( - text = stringResource(id = R.string.forgot_password), - onClick = onResetPasswordClick, - isError = isError, - level = ButtonLevel.SECONDARY - ) - - // Signup Button - ButtonUi( - text = stringResource(id = R.string.signup), - onClick = onSignupClick, - modifier = Modifier.offset(y = 160.dp), - ) - } - } - } -} - diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/resetpassword/ResetPasswordScreen.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/resetpassword/ResetPasswordScreen.kt deleted file mode 100644 index 41ee0d30..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/resetpassword/ResetPasswordScreen.kt +++ /dev/null @@ -1,113 +0,0 @@ -package com.example.speechbuddy.compose.resetpassword - -import android.annotation.SuppressLint -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.example.speechbuddy.R -import com.example.speechbuddy.compose.utils.ButtonLevel -import com.example.speechbuddy.compose.utils.ButtonUi -import com.example.speechbuddy.compose.utils.TextFieldUi -import com.example.speechbuddy.compose.utils.TitleUi -import com.example.speechbuddy.compose.utils.TopAppBarUi -import com.example.speechbuddy.ui.SpeechBuddyTheme - -@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun ResetPasswordScreen( - modifier: Modifier = Modifier, - onBackClick: () -> Unit, - onNextClick: () -> Unit, -) { - Surface( - modifier = modifier - .fillMaxSize() - ) { - Scaffold( - topBar = { - TopAppBarUi( - onBackClick = onBackClick - ) - } - ) { - val password = remember { mutableStateOf("") } - val passwordCheck = remember { mutableStateOf("") } - - Column( - modifier = Modifier - .padding(24.dp) - .fillMaxSize(), - verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally - ) { - TitleUi( - title = stringResource(id = R.string.reset_password_title), - description = stringResource(id = R.string.reset_password_subtitle2) - ) - - Spacer(modifier = Modifier.height(15.dp)) - - // Password Text Field - TextFieldUi( - value = password.value, - onValueChange = { password.value = it }, - label = { Text(stringResource(id = R.string.new_password_field)) }, - supportingText = { Text(stringResource(id = R.string.false_new_password)) }, - isError = false, - isValid = false, - isHidden = true - ) - - // Password Check Text Field - TextFieldUi( - value = passwordCheck.value, - onValueChange = { passwordCheck.value = it }, - label = { Text(stringResource(id = R.string.new_password_check_field)) }, - supportingText = { Text(stringResource(id = R.string.false_new_password_check)) }, - isError = false, - isValid = false, - isHidden = true - ) - - Spacer(modifier = Modifier.height(15.dp)) - - // Set password Button - ButtonUi( - text = stringResource(id = R.string.reset_password_next), - onClick = onNextClick, - isError = false, - isEnabled = true, - level = ButtonLevel.PRIMARY - ) - - } - } - } -} - -@Preview -@Composable -private fun ResetPasswordScreenPreview() { - SpeechBuddyTheme { - ResetPasswordScreen( - onBackClick = {}, - onNextClick = {} - ) - } -} \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/settings/SettingsScreen.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/settings/SettingsScreen.kt deleted file mode 100644 index 080d085c..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/settings/SettingsScreen.kt +++ /dev/null @@ -1,66 +0,0 @@ -package com.example.speechbuddy.compose.settings - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.defaultMinSize -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedTextField -import androidx.compose.material3.Surface -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.example.speechbuddy.compose.utils.TitleUi -import com.example.speechbuddy.ui.SpeechBuddyTheme - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun SettingsScreen( - -) { - Surface( - modifier = Modifier - .fillMaxSize() - ) { - Column( - modifier = Modifier - .padding(25.dp) - .fillMaxSize(), - verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally - ) { - TitleUi( - title = "설정", - description = "소개원실 드랍하고 싶어요" - ) - - Spacer(modifier = Modifier.height(20.dp)) - - OutlinedTextField( - value = "", - onValueChange = {}, - modifier = Modifier - .fillMaxWidth() - .defaultMinSize(minHeight = 300.dp), - textStyle = MaterialTheme.typography.bodyMedium, - shape = RoundedCornerShape(10.dp) - ) - } - } -} - -@Preview -@Composable -private fun SettingsScreenPreview() { - SpeechBuddyTheme { - SettingsScreen() - } -} \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/signup/SignupScreen.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/signup/SignupScreen.kt deleted file mode 100644 index da8383fe..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/signup/SignupScreen.kt +++ /dev/null @@ -1,126 +0,0 @@ -package com.example.speechbuddy.compose.signup - -import android.annotation.SuppressLint -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel -import com.example.speechbuddy.R -import com.example.speechbuddy.compose.utils.ButtonUi -import com.example.speechbuddy.compose.utils.TextFieldUi -import com.example.speechbuddy.compose.utils.TitleUi -import com.example.speechbuddy.compose.utils.TopAppBarUi -import com.example.speechbuddy.ui.models.SignupErrorType -import com.example.speechbuddy.viewmodel.SignupViewModel - - -@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun SignupScreen( - modifier: Modifier = Modifier, - onBackClick: () -> Unit, - email: String, - viewModel: SignupViewModel = hiltViewModel() -) { - val uiState by viewModel.uiState.collectAsState() - val isNicknameError = uiState.error?.type == SignupErrorType.NICKNAME - val isPasswordError = uiState.error?.type == SignupErrorType.PASSWORD - val isPasswordCheckError = uiState.error?.type == SignupErrorType.PASSWORD_CHECK - - - Surface(modifier = modifier.fillMaxSize()) { - Scaffold(topBar = { TopAppBarUi(onBackClick = onBackClick) }) { - Column( - modifier = Modifier - .fillMaxSize() - .padding(24.dp), - verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally - ) { - TitleUi( - title = stringResource(id = R.string.signup_text), - description = stringResource(id = R.string.signup_explain) - ) - - Spacer(modifier = Modifier.height(15.dp)) - - // Email Text Field - TextFieldUi( - value = email, - onValueChange = {}, - label = { Text(text = stringResource(id = R.string.email_field)) }, - isEnabled = false - ) - - // Nickname Text Field - TextFieldUi( - value = viewModel.nicknameInput, - onValueChange = { viewModel.setNickname(it) }, - label = { Text(text = stringResource(id = R.string.nickname)) }, - supportingText = { - if (isNicknameError) { - Text(stringResource(id = uiState.error!!.messageId)) - } - }, - isError = isNicknameError, - isValid = uiState.isValidNickname - ) - - // Password Text Field - TextFieldUi( - value = viewModel.passwordInput, - onValueChange = { viewModel.setPassword(it) }, - label = { Text(text = stringResource(id = R.string.password_field)) }, - supportingText = { - if (isPasswordError) { - Text(stringResource(id = uiState.error!!.messageId)) - } - }, - isError = isPasswordError, - isValid = uiState.isValidPassword, - isHidden = true - - ) - - // Password Check Text Field - TextFieldUi( - value = viewModel.passwordCheckInput, - onValueChange = { viewModel.setPasswordCheck(it) }, - label = { Text(text = stringResource(id = R.string.password_check_field)) }, - supportingText = { - if (isPasswordCheckError) { - Text(stringResource(id = uiState.error!!.messageId)) - } - }, - isError = isPasswordCheckError, - isValid = uiState.isValidPassword, - isHidden = true - ) - - Spacer(modifier = Modifier.height(15.dp)) - - ButtonUi( - text = stringResource(id = R.string.signup), - onClick = { - viewModel.signup(email) - }, - ) - } - } - } -} diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolcreation/SymbolCreationScreen.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolcreation/SymbolCreationScreen.kt deleted file mode 100644 index dd0aa215..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolcreation/SymbolCreationScreen.kt +++ /dev/null @@ -1,66 +0,0 @@ -package com.example.speechbuddy.compose.symbolcreation - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.defaultMinSize -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedTextField -import androidx.compose.material3.Surface -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.example.speechbuddy.compose.utils.TitleUi -import com.example.speechbuddy.ui.SpeechBuddyTheme - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun SymbolCreationScreen( - -) { - Surface( - modifier = Modifier - .fillMaxSize() - ) { - Column( - modifier = Modifier - .padding(25.dp) - .fillMaxSize(), - verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally - ) { - TitleUi( - title = "상징 추가하기", - description = "소개원실 좋아요" - ) - - Spacer(modifier = Modifier.height(20.dp)) - - OutlinedTextField( - value = "", - onValueChange = {}, - modifier = Modifier - .fillMaxWidth() - .defaultMinSize(minHeight = 300.dp), - textStyle = MaterialTheme.typography.bodyMedium, - shape = RoundedCornerShape(10.dp) - ) - } - } -} - -@Preview -@Composable -private fun SymbolCreationScreenPreview() { - SpeechBuddyTheme { - SymbolCreationScreen() - } -} \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SelectedSymbolUi.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SelectedSymbolUi.kt deleted file mode 100644 index 634bceb2..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SelectedSymbolUi.kt +++ /dev/null @@ -1,112 +0,0 @@ -package com.example.speechbuddy.compose.symbolselection - -import androidx.compose.foundation.BorderStroke -import androidx.compose.foundation.Image -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Clear -import androidx.compose.material3.Card -import androidx.compose.material3.CardDefaults -import androidx.compose.material3.ExperimentalMaterial3Api -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.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.example.speechbuddy.R -import com.example.speechbuddy.domain.models.Symbol -import com.example.speechbuddy.ui.SpeechBuddyTheme -import com.example.speechbuddy.utils.Constants - -@ExperimentalMaterial3Api -@Composable -fun SelectedSymbolUi( - symbol: Symbol, - modifier: Modifier = Modifier, - onClear: () -> Unit -) { - Card( - modifier = modifier.size(100.dp), - shape = RoundedCornerShape(10.dp), - colors = CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.background - ), - border = BorderStroke(width = 1.dp, color = MaterialTheme.colorScheme.onBackground) - ) { - Box(contentAlignment = Alignment.TopEnd) { - IconButton( - onClick = onClear, - modifier = Modifier - .size(22.dp) - .padding(5.dp) - ) { - Icon( - imageVector = Icons.Default.Clear, - contentDescription = stringResource(id = R.string.symbol_unselect) - ) - } - - Column( - modifier = Modifier.fillMaxSize(), - horizontalAlignment = Alignment.CenterHorizontally - ) { - Image( - painter = painterResource(id = symbol.imageResId), - contentDescription = symbol.text, - modifier = Modifier.height(65.dp), - contentScale = ContentScale.FillHeight - ) - - Box( - modifier = Modifier - .fillMaxWidth() - .height(35.dp) - .background(color = MaterialTheme.colorScheme.secondaryContainer) - .padding(horizontal = 8.dp), - contentAlignment = Alignment.Center - ) { - Text( - text = symbol.text, - textAlign = TextAlign.Center, - maxLines = Constants.MAXIMUM_LINES_FOR_SYMBOL_TEXT, - style = MaterialTheme.typography.labelSmall - ) - } - } - } - } -} - -@Preview(showBackground = true) -@ExperimentalMaterial3Api -@Composable -fun SelectedSymbolUiPreview() { - val previewSymbol = Symbol( - id = 0, - text = "119에 전화해주세요", - imageResId = R.drawable.symbol_0, - categoryId = 0, - isFavorite = true, - isMine = false - ) - - SpeechBuddyTheme { - SelectedSymbolUi(symbol = previewSymbol, onClear = {}) - } -} \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SelectedSymbolsBox.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SelectedSymbolsBox.kt deleted file mode 100644 index 8e3235b5..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SelectedSymbolsBox.kt +++ /dev/null @@ -1,109 +0,0 @@ -package com.example.speechbuddy.compose.symbolselection - -import androidx.compose.foundation.background -import androidx.compose.foundation.border -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.lazy.LazyRow -import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.Button -import androidx.compose.material3.ButtonDefaults -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.example.speechbuddy.R -import com.example.speechbuddy.domain.models.Symbol -import com.example.speechbuddy.ui.SpeechBuddyTheme - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun SelectedSymbolsBox( - selectedSymbols: List, - onClearAll: () -> Unit, - modifier: Modifier = Modifier -) { - Box( - modifier = modifier - .fillMaxWidth() - .height(120.dp) - .background(color = MaterialTheme.colorScheme.surface) - .border( - width = 1.dp, - color = MaterialTheme.colorScheme.surfaceVariant, - shape = RoundedCornerShape(10.dp) - ), - contentAlignment = Alignment.CenterEnd - ) { - Box( - modifier = Modifier.fillMaxSize(), - contentAlignment = Alignment.CenterStart - ) { - LazyRow( - contentPadding = PaddingValues(10.dp), - horizontalArrangement = Arrangement.spacedBy(10.dp) - ) { - items(selectedSymbols) { symbol -> - SelectedSymbolUi(symbol = symbol, onClear = {}) - } - } - } - - Box( - modifier = Modifier - .width(50.dp) - .background(color = MaterialTheme.colorScheme.background) - ) { - Button( - onClick = onClearAll, - modifier = Modifier - .fillMaxSize() - .padding(6.dp), - enabled = selectedSymbols.isNotEmpty(), - shape = RoundedCornerShape(5.dp), - colors = ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.tertiary, - contentColor = MaterialTheme.colorScheme.onTertiary, - ), - contentPadding = PaddingValues(2.dp) - ) { - Text( - text = stringResource(id = R.string.clear_all), - textAlign = TextAlign.Center, - style = MaterialTheme.typography.bodyMedium - ) - } - } - } -} - -@Preview -@Composable -fun SelectedSymbolsBoxPreview() { - val previewSymbol = Symbol( - id = 0, - text = "119에 전화해주세요", - imageResId = R.drawable.symbol_0, - categoryId = 0, - isFavorite = true, - isMine = false - ) - val selectedSymbols = List(size = 10, init = { previewSymbol }) - - SpeechBuddyTheme { - SelectedSymbolsBox(selectedSymbols = selectedSymbols, onClearAll = {}) - } -} \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSearchTextField.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSearchTextField.kt deleted file mode 100644 index 62954fb8..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSearchTextField.kt +++ /dev/null @@ -1,63 +0,0 @@ -package com.example.speechbuddy.compose.symbolselection - -import androidx.compose.foundation.layout.defaultMinSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Search -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedTextField -import androidx.compose.material3.Text -import androidx.compose.material3.TextFieldDefaults -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.example.speechbuddy.R -import com.example.speechbuddy.ui.SpeechBuddyTheme - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun SymbolSearchTextField( - value: String, - onValueChange: (String) -> Unit, - modifier: Modifier = Modifier -) { - OutlinedTextField( - value = value, - onValueChange = onValueChange, - modifier = modifier - .fillMaxWidth() - .defaultMinSize(minHeight = 48.dp), - textStyle = MaterialTheme.typography.bodyMedium, - placeholder = { Text(text = stringResource(id = R.string.search_box_placeholder)) }, - trailingIcon = { - Icon( - imageVector = Icons.Default.Search, - contentDescription = stringResource(id = R.string.search_box_placeholder) - ) - }, - singleLine = true, - shape = RoundedCornerShape(10.dp), - colors = TextFieldDefaults.outlinedTextFieldColors( - textColor = MaterialTheme.colorScheme.onSurface, - containerColor = MaterialTheme.colorScheme.surface, - focusedBorderColor = MaterialTheme.colorScheme.tertiary, - unfocusedBorderColor = MaterialTheme.colorScheme.surfaceVariant - ) - ) -} - -@Preview(showBackground = true) -@Composable -fun SymbolSearchTextFieldPreview() { - SpeechBuddyTheme { - SymbolSearchTextField( - value = "검색어", - onValueChange = {}, - ) - } -} \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSelectionScreen.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSelectionScreen.kt deleted file mode 100644 index 4e9bfdb8..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/symbolselection/SymbolSelectionScreen.kt +++ /dev/null @@ -1,78 +0,0 @@ -package com.example.speechbuddy.compose.symbolselection - -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.grid.GridCells -import androidx.compose.foundation.lazy.grid.LazyVerticalGrid -import androidx.compose.foundation.lazy.grid.items -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel -import com.example.speechbuddy.compose.utils.CategoryUi -import com.example.speechbuddy.compose.utils.SymbolUi -import com.example.speechbuddy.domain.models.Category -import com.example.speechbuddy.domain.models.Symbol -import com.example.speechbuddy.viewmodel.SymbolSelectionViewModel - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun SymbolSelectionScreen( - modifier: Modifier = Modifier, - viewModel: SymbolSelectionViewModel = hiltViewModel() -) { - Surface(modifier = modifier.fillMaxSize()) { - Column( - modifier = Modifier - .padding(start = 24.dp, top = 80.dp, end = 24.dp, bottom = 80.dp) - .fillMaxSize(), - verticalArrangement = Arrangement.spacedBy(20.dp) - ) { - /* TODO: ViewModel 연결 */ - SymbolSearchTextField( - value = viewModel.queryInput, - onValueChange = { viewModel.setQuery(it) }) - - SelectedSymbolsBox( - selectedSymbols = viewModel.selectedSymbols, - onClearAll = { viewModel.clearAll() }) - - Box( - modifier = Modifier - .fillMaxSize() - .background( - color = MaterialTheme.colorScheme.surfaceVariant, - shape = RoundedCornerShape(topStart = 20.dp, topEnd = 20.dp) - ) - .padding(16.dp) - ) { - LazyVerticalGrid( - columns = GridCells.Adaptive(140.dp), - verticalArrangement = Arrangement.spacedBy(16.dp), - horizontalArrangement = Arrangement.spacedBy(16.dp) - ) { - items(viewModel.entries) { entry -> - when (entry) { - is Symbol -> SymbolUi( - symbol = entry, - onSelect = { viewModel.selectSymbol(entry) }, - onFavoriteChange = {}) - - is Category -> CategoryUi( - category = entry, - onSelect = { viewModel.selectCategory(entry) }) - } - } - } - } - } - } -} \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/texttospeech/TextToSpeechScreen.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/texttospeech/TextToSpeechScreen.kt deleted file mode 100644 index c24caa37..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/texttospeech/TextToSpeechScreen.kt +++ /dev/null @@ -1,137 +0,0 @@ -package com.example.speechbuddy.compose.texttospeech - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.foundation.verticalScroll -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.PlayArrow -import androidx.compose.material3.Button -import androidx.compose.material3.ButtonDefaults -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedTextField -import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.material3.TextFieldDefaults -import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel -import com.example.speechbuddy.R -import com.example.speechbuddy.compose.utils.TitleUi -import com.example.speechbuddy.ui.models.ButtonStatusType -import com.example.speechbuddy.viewmodel.TextToSpeechViewModel - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun TextToSpeechScreen( - viewModel: TextToSpeechViewModel = hiltViewModel() -) { - val uiState by viewModel.uiState.collectAsState() - val context = LocalContext.current - - Surface( - modifier = Modifier - .fillMaxSize() - ) { - Column( - modifier = Modifier - .padding(24.dp) - .fillMaxSize(), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center, - ) { - TitleUi( - title = stringResource(id = R.string.tts_text), - description = stringResource(id = R.string.tts_explain) - ) - - Spacer(modifier = Modifier.height(20.dp)) - - OutlinedTextField( - value = viewModel.textInput, - onValueChange = { - viewModel.setText(it) - }, - modifier = Modifier - .fillMaxWidth() - .verticalScroll(rememberScrollState()) - .height(300.dp), - textStyle = MaterialTheme.typography.bodyMedium, - shape = RoundedCornerShape(10.dp), - colors = TextFieldDefaults.outlinedTextFieldColors( - focusedBorderColor = MaterialTheme.colorScheme.tertiary, - unfocusedBorderColor = MaterialTheme.colorScheme.outline - ) - ) - - Spacer(modifier = Modifier.height(20.dp)) - - TextToSpeechButton( - buttonStatus = uiState.buttonStatus, - onPlay = { viewModel.ttsStart(context) }, - onStop = { viewModel.ttsStop() } - ) - } - } -} - -@Composable -private fun TextToSpeechButton( - buttonStatus: ButtonStatusType, - onPlay: () -> Unit, - onStop: () -> Unit -) { - val textToSpeechButtonColors = ButtonDefaults.buttonColors( - containerColor = Color.Transparent, - contentColor = MaterialTheme.colorScheme.onBackground - ) - - when (buttonStatus) { - ButtonStatusType.PLAY -> Button( - onClick = onPlay, - colors = textToSpeechButtonColors - ) { - Text( - style = MaterialTheme.typography.headlineMedium, - text = stringResource(id = R.string.play_text) - ) - Icon( - Icons.Filled.PlayArrow, - contentDescription = stringResource(id = R.string.play_text), - modifier = Modifier.size(36.dp) - ) - } - - ButtonStatusType.STOP -> Button( - onClick = onStop, - colors = textToSpeechButtonColors - ) { - Text( - style = MaterialTheme.typography.headlineMedium, - text = stringResource(id = R.string.stop_text) - ) - Icon( - painterResource(R.drawable.stop_icon), - contentDescription = stringResource(id = R.string.stop_text), - modifier = Modifier.size(36.dp) - ) - } - } -} \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/ButtonUi.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/ButtonUi.kt deleted file mode 100644 index 64cd3906..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/ButtonUi.kt +++ /dev/null @@ -1,125 +0,0 @@ -package com.example.speechbuddy.compose.utils - -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.defaultMinSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.Button -import androidx.compose.material3.ButtonDefaults -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.example.speechbuddy.ui.SpeechBuddyTheme - -enum class ButtonLevel { - PRIMARY, SECONDARY, TERTIARY -} - -/** - * Custom UI designed for buttons. - * - * @param text displayed on the center of this button - * @param onClick called when this button is clicked - * @param modifier the Modifier to be applied to this button - * @param isEnabled controls the enabled state of this button. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services - * @param isError defines the color and the enabled state of this button. When true, this component will be disabled, and it will be displayed in error color - * @param level should be ButtonLevel.PRIMARY, ButtonLevel.SECONDARY, or ButtonLevel.TERTIARY. ButtonLevel.PRIMARY is the default value - */ -@Composable -fun ButtonUi( - text: String, - onClick: () -> Unit, - modifier: Modifier = Modifier, - isEnabled: Boolean = true, - isError: Boolean = false, - level: ButtonLevel = ButtonLevel.PRIMARY -) { - when (level) { - ButtonLevel.PRIMARY -> Button( - onClick = onClick, - modifier = modifier - .fillMaxWidth() - .height(48.dp), - enabled = isEnabled, - shape = RoundedCornerShape(10.dp), - colors = if (isError) { - ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.error, - contentColor = MaterialTheme.colorScheme.onError, - disabledContainerColor = MaterialTheme.colorScheme.error, - disabledContentColor = MaterialTheme.colorScheme.onError - ) - } else ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.primary, - contentColor = MaterialTheme.colorScheme.onPrimary - ) - ) { - Text(text = text, style = MaterialTheme.typography.titleMedium) - } - - ButtonLevel.SECONDARY -> Button( - onClick = onClick, - modifier = modifier - .fillMaxWidth() - .height(48.dp), - enabled = isEnabled, - shape = RoundedCornerShape(10.dp), - colors = if (isError) { - ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.errorContainer, - contentColor = MaterialTheme.colorScheme.onErrorContainer, - disabledContainerColor = MaterialTheme.colorScheme.errorContainer, - disabledContentColor = MaterialTheme.colorScheme.onErrorContainer - ) - } else ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.secondaryContainer, - contentColor = MaterialTheme.colorScheme.onSecondaryContainer, - ) - ) { - Text(text = text, style = MaterialTheme.typography.titleMedium) - } - - ButtonLevel.TERTIARY -> Button( - onClick = onClick, - modifier = modifier - .defaultMinSize( - minWidth = ButtonDefaults.MinWidth, minHeight = 32.dp - ) - .padding(horizontal = 8.dp, vertical = 0.dp), - enabled = isEnabled, - shape = RoundedCornerShape(5.dp), - colors = if (isError) { - ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.error, - contentColor = MaterialTheme.colorScheme.onError, - disabledContainerColor = MaterialTheme.colorScheme.error, - disabledContentColor = MaterialTheme.colorScheme.onError - ) - } else ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.tertiary, - contentColor = MaterialTheme.colorScheme.onTertiary, - ), - contentPadding = PaddingValues(8.dp) - ) { - Text(text = text, style = MaterialTheme.typography.bodyMedium) - } - } -} - -@Preview -@Composable -fun ButtonUiPreview() { - SpeechBuddyTheme { - ButtonUi( - text = "커스텀 버튼", - onClick = {}, - isError = true, - level = ButtonLevel.SECONDARY - ) - } -} \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/CategoryUi.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/CategoryUi.kt deleted file mode 100644 index f1f46e59..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/CategoryUi.kt +++ /dev/null @@ -1,91 +0,0 @@ -package com.example.speechbuddy.compose.utils - -import androidx.compose.foundation.Image -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.Card -import androidx.compose.material3.CardDefaults -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.example.speechbuddy.R -import com.example.speechbuddy.domain.models.Category -import com.example.speechbuddy.ui.SpeechBuddyTheme - -/** - * Custom UI designed for Category - * - * @param category data class Category to be passed to the UI - * @param modifier the Modifier to be applied to this outlined card - * @param onSelect called when this Category is clicked - */ -@ExperimentalMaterial3Api -@Composable -fun CategoryUi( - category: Category, modifier: Modifier = Modifier, onSelect: () -> Unit -) { - Card( - onClick = onSelect, - modifier = modifier.size(140.dp), - shape = RoundedCornerShape(10.dp), - colors = CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.background - ) - ) { - Box { - Column( - modifier = Modifier.fillMaxSize(), - horizontalAlignment = Alignment.CenterHorizontally - ) { - Image( - painter = painterResource(id = category.imageResId), - contentDescription = category.text, - modifier = Modifier.height(95.dp), - contentScale = ContentScale.FillHeight - ) - - Box( - modifier = Modifier - .fillMaxWidth() - .height(45.dp) - .background(color = MaterialTheme.colorScheme.tertiaryContainer) - .padding(horizontal = 10.dp), contentAlignment = Alignment.Center - ) { - Text( - text = category.text, - textAlign = TextAlign.Center, - style = MaterialTheme.typography.bodySmall - ) - } - } - } - } -} - -@Preview(showBackground = true, backgroundColor = 0) -@ExperimentalMaterial3Api -@Composable -fun CategoryUiPreview() { - val previewCategory = Category( - id = 0, text = "인사사회어", imageResId = R.drawable.category_0 - ) - - SpeechBuddyTheme { - CategoryUi(category = previewCategory, onSelect = {}) - } -} \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/SymbolUi.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/SymbolUi.kt deleted file mode 100644 index 5099d3d2..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/SymbolUi.kt +++ /dev/null @@ -1,130 +0,0 @@ -package com.example.speechbuddy.compose.utils - -import androidx.compose.foundation.Image -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Favorite -import androidx.compose.material.icons.filled.FavoriteBorder -import androidx.compose.material3.Card -import androidx.compose.material3.CardDefaults -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButtonDefaults -import androidx.compose.material3.IconToggleButton -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.example.speechbuddy.R -import com.example.speechbuddy.domain.models.Symbol -import com.example.speechbuddy.ui.SpeechBuddyTheme -import com.example.speechbuddy.utils.Constants.Companion.MAXIMUM_LINES_FOR_SYMBOL_TEXT - -/** - * Custom UI designed for Symbol - * - * @param symbol data class Symbol to be passed to the UI - * @param modifier the Modifier to be applied to this outlined card - * @param onSelect called when this Symbol is clicked - * @param onFavoriteChange called when the upper left icon of this Symbol is clicked - */ -@ExperimentalMaterial3Api -@Composable -fun SymbolUi( - symbol: Symbol, - modifier: Modifier = Modifier, - onSelect: () -> Unit, - onFavoriteChange: () -> Unit -) { - Card( - onClick = onSelect, - modifier = modifier.size(140.dp), - shape = RoundedCornerShape(10.dp), - colors = CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.background - ) - ) { - Box(contentAlignment = Alignment.TopEnd) { - IconToggleButton( - checked = symbol.isFavorite, - onCheckedChange = { onFavoriteChange() }, - modifier = Modifier - .size(24.dp) - .padding(4.dp), - colors = IconButtonDefaults.iconToggleButtonColors( - contentColor = MaterialTheme.colorScheme.onBackground, - checkedContentColor = MaterialTheme.colorScheme.error - ) - ) { - Icon( - imageVector = when (symbol.isFavorite) { - true -> Icons.Default.Favorite - false -> Icons.Default.FavoriteBorder - }, - contentDescription = stringResource(id = R.string.favorite) - ) - } - - Column( - modifier = Modifier.fillMaxSize(), - horizontalAlignment = Alignment.CenterHorizontally - ) { - Image( - painter = painterResource(id = symbol.imageResId), - contentDescription = symbol.text, - modifier = Modifier.height(95.dp), - contentScale = ContentScale.FillHeight - ) - - Box( - modifier = Modifier - .fillMaxWidth() - .height(45.dp) - .background(color = MaterialTheme.colorScheme.secondaryContainer) - .padding(horizontal = 10.dp), - contentAlignment = Alignment.Center - ) { - Text( - text = symbol.text, - textAlign = TextAlign.Center, - maxLines = MAXIMUM_LINES_FOR_SYMBOL_TEXT, - style = MaterialTheme.typography.bodySmall - ) - } - } - } - } -} - -@Preview(showBackground = true, backgroundColor = 0) -@ExperimentalMaterial3Api -@Composable -fun SymbolUiPreview() { - val previewSymbol = Symbol( - id = 0, - text = "119에 전화해주세요", - imageResId = R.drawable.symbol_0, - categoryId = 0, - isFavorite = true, - isMine = false - ) - - SpeechBuddyTheme { - SymbolUi(symbol = previewSymbol, onSelect = {}, onFavoriteChange = {}) - } -} \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/TextFieldUi.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/TextFieldUi.kt deleted file mode 100644 index d73f02ce..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/TextFieldUi.kt +++ /dev/null @@ -1,118 +0,0 @@ -package com.example.speechbuddy.compose.utils - -import androidx.compose.foundation.layout.defaultMinSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedTextField -import androidx.compose.material3.Text -import androidx.compose.material3.TextFieldColors -import androidx.compose.material3.TextFieldDefaults -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.text.input.PasswordVisualTransformation -import androidx.compose.ui.text.input.VisualTransformation -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.example.speechbuddy.ui.SpeechBuddyTheme - -/** - * Custom UI designed for text fields. - * - * @param value the input text to be shown in the text field - * @param onValueChange the callback that is triggered when the input service updates the text. An updated text comes as a parameter of the callback - * @param modifier the Modifier to be applied to this text field - * @param label the optional label to be displayed inside the text field container - * @param supportingText the optional supporting text to be displayed below the text field - * @param supportingButton the optional supporting button to be displayed on the right side of the text field. Using ButtonUi with ButtonLevel.TERTIARY is highly recommended - * @param isError indicates if the text field's current value is in error. If set to true, the style of this text field by default will be displayed in error color - * @param isValid indicates if the text field's current value is valid. If set to true, the style of this text field by default will be displayed in primary color - * @param isHidden controls the visual transformation of the text field's current value. If set to true, the value of this text field will be displayed as a series of dots - * @param isEnabled indicates if the text in the text field is modifiable - */ -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun TextFieldUi( - value: String, - onValueChange: (String) -> Unit, - modifier: Modifier = Modifier, - isEnabled: Boolean = true, - label: @Composable (() -> Unit)? = null, - supportingButton: @Composable (() -> Unit)? = null, - supportingText: @Composable (() -> Unit)? = null, - isError: Boolean = false, - isValid: Boolean = false, - isHidden: Boolean = false -) { - OutlinedTextField( - value = value, - onValueChange = onValueChange, - modifier = modifier - .fillMaxWidth() - .defaultMinSize(minHeight = 48.dp), - enabled = isEnabled, - textStyle = MaterialTheme.typography.bodyMedium, - label = label, - trailingIcon = supportingButton, - supportingText = supportingText, - isError = isError, - visualTransformation = if (isHidden) { - PasswordVisualTransformation() - } else { - VisualTransformation.None - }, - singleLine = true, - shape = RoundedCornerShape(10.dp), - colors = getTextFieldColors(isValid) - ) -} - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -private fun getTextFieldColors(isValid: Boolean): TextFieldColors { - if (isValid) return TextFieldDefaults.outlinedTextFieldColors( - textColor = MaterialTheme.colorScheme.onSurface, - containerColor = MaterialTheme.colorScheme.surface, - focusedBorderColor = MaterialTheme.colorScheme.primary, - unfocusedBorderColor = MaterialTheme.colorScheme.primary, - focusedLabelColor = MaterialTheme.colorScheme.primary, - unfocusedLabelColor = MaterialTheme.colorScheme.primary, - focusedSupportingTextColor = MaterialTheme.colorScheme.primary, - unfocusedSupportingTextColor = MaterialTheme.colorScheme.primary - ) - else return TextFieldDefaults.outlinedTextFieldColors( - textColor = MaterialTheme.colorScheme.onSurface, - containerColor = MaterialTheme.colorScheme.surface, - focusedBorderColor = MaterialTheme.colorScheme.tertiary, - unfocusedBorderColor = MaterialTheme.colorScheme.outline, - focusedLabelColor = MaterialTheme.colorScheme.tertiary, - unfocusedLabelColor = MaterialTheme.colorScheme.outline, - focusedSupportingTextColor = MaterialTheme.colorScheme.tertiary, - unfocusedSupportingTextColor = MaterialTheme.colorScheme.outline - ) -} - -@Preview(showBackground = true) -@Composable -fun TextFieldUiPreview() { - SpeechBuddyTheme { - TextFieldUi( - value = "wrongaddress@email.com", - onValueChange = {}, - label = { Text("이메일") }, - supportingButton = { - ButtonUi( - text = "인증번호 발송", - onClick = {}, - isError = true, - level = ButtonLevel.TERTIARY - ) - }, - supportingText = { Text("잘못된 이메일 주소입니다.") }, - isError = true, - isValid = false, - isHidden = false, - ) - } -} \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/TitleUi.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/TitleUi.kt deleted file mode 100644 index 7244355d..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/TitleUi.kt +++ /dev/null @@ -1,50 +0,0 @@ -package com.example.speechbuddy.compose.utils - -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import com.example.speechbuddy.R -import com.example.speechbuddy.ui.SpeechBuddyTheme - -/** - * Custom UI designed for titles. - * - * @param modifier the Modifier to be applied to this title - * @param title displayed on the top of this component. Default style is displayMedium - * @param description displayed on the bottom of this component. Default style is bodyMedium - */ -@Composable -fun TitleUi( - modifier: Modifier = Modifier, - title: String, - description: String, -) { - Column(modifier = modifier) { - Text( - modifier = Modifier.fillMaxWidth(), - text = title, - style = MaterialTheme.typography.displayMedium, - ) - Text( - modifier = Modifier.fillMaxWidth(), - text = description, - style = MaterialTheme.typography.bodyMedium, - ) - } -} - -@Preview(showBackground = true) -@Composable -fun TitleUiPreview() { - SpeechBuddyTheme { - TitleUi( - title = stringResource(id = R.string.signup_text), - description = stringResource(id = R.string.signup_explain) - ) - } -} \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/TopAppBarUi.kt b/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/TopAppBarUi.kt deleted file mode 100644 index 9e968908..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/compose/utils/TopAppBarUi.kt +++ /dev/null @@ -1,59 +0,0 @@ -package com.example.speechbuddy.compose.utils - -import androidx.compose.foundation.Image -import androidx.compose.foundation.layout.size -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.ArrowBack -import androidx.compose.material3.CenterAlignedTopAppBar -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.example.speechbuddy.R -import com.example.speechbuddy.ui.SpeechBuddyTheme - -/** - * Custom UI designed for top app bars. - * - * @param modifier the Modifier to be applied to this top app bar - * @param onBackClick called when the back icon of this top app bar is clicked - */ -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun TopAppBarUi( - modifier: Modifier = Modifier, - onBackClick: () -> Unit -) { - CenterAlignedTopAppBar( - modifier = modifier, - title = { - Image( - painter = painterResource(id = R.drawable.top_app_bar_ic), - contentDescription = "app logo", - contentScale = ContentScale.Fit, - modifier = Modifier.size(148.dp) - ) - }, - navigationIcon = { - IconButton(onClick = onBackClick) { - Icon( - imageVector = Icons.Default.ArrowBack, - contentDescription = "Go back to landing page" - ) - } - }, - ) -} - -@Preview -@Composable -fun TopAppBarUiPreview() { - SpeechBuddyTheme { - TopAppBarUi(onBackClick = {}) - } -} diff --git a/frontend/app/src/main/java/com/example/speechbuddy/data/remote/AuthTokenRemoteSource.kt b/frontend/app/src/main/java/com/example/speechbuddy/data/remote/AuthTokenRemoteSource.kt deleted file mode 100644 index 40a3b222..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/data/remote/AuthTokenRemoteSource.kt +++ /dev/null @@ -1,52 +0,0 @@ -package com.example.speechbuddy.data.remote - -import com.example.speechbuddy.data.remote.models.AuthTokenDto -import com.example.speechbuddy.data.remote.requests.AuthLoginRequest -import com.example.speechbuddy.data.remote.requests.AuthSignupRequest -import com.example.speechbuddy.data.remote.requests.AuthVerifyEmailAcceptRequest -import com.example.speechbuddy.data.remote.requests.AuthVerifyEmailSendRequest -import com.example.speechbuddy.service.AuthService -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flow -import retrofit2.Response -import javax.inject.Inject - -class AuthTokenRemoteSource @Inject constructor(private val authService: AuthService) { - - suspend fun signupAuthToken(authSignupRequest: AuthSignupRequest): Flow> = - flow { - val result = authService.signup(authSignupRequest) - emit(result) - } - - suspend fun loginAuthToken(authLoginRequest: AuthLoginRequest): Flow> = - flow { - val result = authService.login(authLoginRequest) - emit(result) - } - - suspend fun verifySendSignupAuthToken(authVerifyEmailSendRequest: AuthVerifyEmailSendRequest): Flow> = - flow { - val result = authService.verifySendSignup(authVerifyEmailSendRequest) - emit(result) - } - - suspend fun verifySendPWAuthToken(authVerifyEmailSendRequest: AuthVerifyEmailSendRequest): Flow> = - flow { - val result = authService.verifySendPW(authVerifyEmailSendRequest) - emit(result) - } - - suspend fun verifyAcceptSignupAuthToken(authVerifyEmailAcceptRequest: AuthVerifyEmailAcceptRequest): Flow> = - flow { - val result = authService.verifyAcceptSignup(authVerifyEmailAcceptRequest) - emit(result) - } - - suspend fun verifyAcceptPWAuthToken(authVerifyEmailAcceptRequest: AuthVerifyEmailAcceptRequest): Flow> = - flow { - val result = authService.verifyAcceptPW(authVerifyEmailAcceptRequest) - emit(result) - } - -} \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/data/remote/models/AuthTokenDto.kt b/frontend/app/src/main/java/com/example/speechbuddy/data/remote/models/AuthTokenDto.kt deleted file mode 100644 index d6a27110..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/data/remote/models/AuthTokenDto.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.example.speechbuddy.data.remote.models - -import com.squareup.moshi.Json -import com.squareup.moshi.JsonClass - -@JsonClass(generateAdapter = true) -data class AuthTokenDto( - @Json(name = "access") val accessToken: String? = null, - @Json(name = "refresh") val refreshToken: String? = null -) \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/data/remote/models/AuthTokenDtoMapper.kt b/frontend/app/src/main/java/com/example/speechbuddy/data/remote/models/AuthTokenDtoMapper.kt deleted file mode 100644 index 46fe3020..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/data/remote/models/AuthTokenDtoMapper.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.example.speechbuddy.data.remote.models - -import com.example.speechbuddy.domain.models.AuthToken -import com.example.speechbuddy.domain.utils.DomainMapper - -class AuthTokenDtoMapper : DomainMapper { - - override fun mapToDomainModel(model: AuthTokenDto): AuthToken { - return AuthToken( - accessToken = model.accessToken, - refreshToken = model.refreshToken - ) - } - - override fun mapFromDomainModel(domainModel: AuthToken): AuthTokenDto { - return AuthTokenDto( - accessToken = domainModel.accessToken, - refreshToken = domainModel.refreshToken - ) - } - -} \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/data/remote/requests/AuthRequest.kt b/frontend/app/src/main/java/com/example/speechbuddy/data/remote/requests/AuthRequest.kt deleted file mode 100644 index 78d33e84..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/data/remote/requests/AuthRequest.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.example.speechbuddy.data.remote.requests - -import com.squareup.moshi.JsonClass - -@JsonClass(generateAdapter = true) -data class AuthSignupRequest( - val email: String, val password: String, val nickname: String -) - -@JsonClass(generateAdapter = true) -data class AuthLoginRequest( - val email: String, val password: String -) - -@JsonClass(generateAdapter = true) -data class AuthVerifyEmailSendRequest( - val email: String -) -@JsonClass(generateAdapter = true) -data class AuthVerifyEmailAcceptRequest( - val email: String, val code: String -) \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/di/NetworkModule.kt b/frontend/app/src/main/java/com/example/speechbuddy/di/NetworkModule.kt deleted file mode 100644 index 7af23081..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/di/NetworkModule.kt +++ /dev/null @@ -1,47 +0,0 @@ -package com.example.speechbuddy.di - -import com.example.speechbuddy.data.remote.models.AuthTokenDtoMapper -import com.example.speechbuddy.service.AuthService -import com.example.speechbuddy.utils.Constants -import com.squareup.moshi.Moshi -import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent -import okhttp3.OkHttpClient -import okhttp3.logging.HttpLoggingInterceptor -import retrofit2.Retrofit -import retrofit2.converter.moshi.MoshiConverterFactory -import javax.inject.Singleton - -@InstallIn(SingletonComponent::class) -@Module -class NetworkModule { - - @Singleton - @Provides - fun provideRetrofit(): Retrofit { - val logger = HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BODY } - - val client = OkHttpClient.Builder().addInterceptor(logger).build() - - val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() - - return Retrofit.Builder().baseUrl(Constants.BASE_URL).client(client) - .addConverterFactory(MoshiConverterFactory.create(moshi)).build() - } - - @Singleton - @Provides - fun provideAuthService(retrofit: Retrofit): AuthService { - return retrofit.create(AuthService::class.java) - } - - @Singleton - @Provides - fun provideAuthTokenDtoMapper(): AuthTokenDtoMapper { - return AuthTokenDtoMapper() - } - -} \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/domain/models/AuthToken.kt b/frontend/app/src/main/java/com/example/speechbuddy/domain/models/AuthToken.kt deleted file mode 100644 index 81a8018e..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/domain/models/AuthToken.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.example.speechbuddy.domain.models - -import android.os.Parcelable -import kotlinx.parcelize.Parcelize - -@Parcelize -data class AuthToken( - val accessToken: String? = null, val refreshToken: String? = null -) : Parcelable \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/domain/models/Entry.kt b/frontend/app/src/main/java/com/example/speechbuddy/domain/models/Entry.kt deleted file mode 100644 index 84078cbc..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/domain/models/Entry.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.example.speechbuddy.domain.models - -import android.os.Parcelable -import kotlinx.parcelize.Parcelize - -interface Entry { - val id: Int - val text: String - val imageResId: Int -} - -@Parcelize -data class Category( - override val id: Int, - override val text: String, - override val imageResId: Int -) : Parcelable, Entry - -@Parcelize -data class Symbol( - override val id: Int, - override val text: String, - override val imageResId: Int, - val categoryId: Int, - val isFavorite: Boolean, - val isMine: Boolean -) : Parcelable, Entry \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/domain/utils/DomainMapper.kt b/frontend/app/src/main/java/com/example/speechbuddy/domain/utils/DomainMapper.kt deleted file mode 100644 index dc5f4b23..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/domain/utils/DomainMapper.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.example.speechbuddy.domain.utils - -interface DomainMapper { - - fun mapToDomainModel(model: T): DomainModel - - fun mapFromDomainModel(domainModel: DomainModel): T - -} \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/domain/utils/TokenSharedPreferences.kt b/frontend/app/src/main/java/com/example/speechbuddy/domain/utils/TokenSharedPreferences.kt deleted file mode 100644 index cf39ef06..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/domain/utils/TokenSharedPreferences.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.example.speechbuddy.domain.utils - -import android.content.Context - -class TokenSharedPreferences(context: Context) { - private val prefsFilename = "token_prefs" - private val prefs = context.getSharedPreferences(prefsFilename, Context.MODE_PRIVATE) - - fun setAccessToken(accessToken: String) { - prefs.edit().putString("accessToken", accessToken).apply() - } - - fun getAccessToken(): String? { - return prefs.getString("accessToken", null) - } - - fun clearAccessToken() { - prefs.edit().remove("accessToken").apply() - } - - fun setRefreshToken(refreshToken: String) { - prefs.edit().putString("refreshToken", refreshToken).apply() - } - - fun getRefreshToken(): String? { - return prefs.getString("refreshToken", null) - } - - fun clearRefreshToken() { - prefs.edit().remove("refreshToken").apply() - } -} \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/repository/AuthRepository.kt b/frontend/app/src/main/java/com/example/speechbuddy/repository/AuthRepository.kt deleted file mode 100644 index 21ccf773..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/repository/AuthRepository.kt +++ /dev/null @@ -1,145 +0,0 @@ -package com.example.speechbuddy.repository - -import com.example.speechbuddy.data.remote.AuthTokenRemoteSource -import com.example.speechbuddy.data.remote.models.AuthTokenDtoMapper -import com.example.speechbuddy.data.remote.requests.AuthLoginRequest -import com.example.speechbuddy.data.remote.requests.AuthSignupRequest -import com.example.speechbuddy.data.remote.requests.AuthVerifyEmailAcceptRequest -import com.example.speechbuddy.data.remote.requests.AuthVerifyEmailSendRequest -import com.example.speechbuddy.domain.models.AuthToken -import com.example.speechbuddy.utils.Resource -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.map -import org.json.JSONObject -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class AuthRepository @Inject constructor( - private val authTokenRemoteSource: AuthTokenRemoteSource, - private val authTokenDtoMapper: AuthTokenDtoMapper -) { - - suspend fun signup(authSignupRequest: AuthSignupRequest): Flow> { - return authTokenRemoteSource.signupAuthToken(authSignupRequest).map { response -> - if (response.isSuccessful && response.code() == 201) { - Resource.success(null) - } else { - response.errorBody()?.let { responseBody -> - val errorMessage = - JSONObject(responseBody.charStream().readText()).getString("error") - Resource.error( - errorMessage, - null - ) - } ?: Resource.error("Unknown Error", null) - } - } - } - - suspend fun login(authLoginRequest: AuthLoginRequest): Flow> { - return authTokenRemoteSource.loginAuthToken(authLoginRequest) - .map { response -> - if (response.isSuccessful && response.code() == 200) { - response.body()?.let { authTokenDto -> - authTokenDto.let { - Resource.success(authTokenDtoMapper.mapToDomainModel(authTokenDto)) - } - } ?: returnUnknownError() - } else { - response.errorBody()?.let { responseBody -> - val errorMessage = - JSONObject(responseBody.charStream().readText()).getString("error") - Resource.error( - errorMessage, - null - ) - } ?: returnUnknownError() - } - } - } - - suspend fun verifySendSignup(authVerifyEmailSendRequest: AuthVerifyEmailSendRequest): Flow> { - return authTokenRemoteSource.verifySendSignupAuthToken(authVerifyEmailSendRequest).map { response -> - if (response.isSuccessful && response.code() == 200) { - Resource.success(null) - } else { - response.errorBody()?.let { responseBody -> - val errorJson = JSONObject(responseBody.charStream().readText()) - val messageJson = errorJson.getJSONObject("error").getJSONObject("message") - val firstKeyOfMessage = messageJson.keys().next().toString() - Resource.error( - firstKeyOfMessage, - null - ) - } ?: Resource.error("Unknown Error", null) - } - } - } - - suspend fun verifySendPW(authVerifyEmailSendRequest: AuthVerifyEmailSendRequest): Flow> { - return authTokenRemoteSource.verifySendPWAuthToken(authVerifyEmailSendRequest).map { response -> - if (response.isSuccessful && response.code() == 200) { - Resource.success(null) - } else { - response.errorBody()?.let { responseBody -> - val errorJson = JSONObject(responseBody.charStream().readText()) - val messageJson = errorJson.getJSONObject("error").getJSONObject("message") - val firstKeyOfMessage = messageJson.keys().next().toString() - Resource.error( - firstKeyOfMessage, - null - ) - } ?: Resource.error("Unknown Error", null) - } - } - } - suspend fun verifyAcceptSignup(authVerifyEmailAcceptRequest: AuthVerifyEmailAcceptRequest): Flow> { - return authTokenRemoteSource.verifyAcceptSignupAuthToken(authVerifyEmailAcceptRequest).map { response -> - if (response.isSuccessful && response.code() == 200) { - Resource.success(null) - } else { - response.errorBody()?.let { responseBody -> - val errorJson = JSONObject(responseBody.charStream().readText()) - val messageJson = errorJson.getJSONObject("error").getJSONObject("message") - val firstKeyOfMessage = messageJson.keys().next().toString() - Resource.error( - firstKeyOfMessage, - null - ) - } ?: Resource.error("Unknown Error", null) - } - } - } - - suspend fun verifyAcceptPW(authVerifyEmailAcceptRequest: AuthVerifyEmailAcceptRequest): Flow> { - return authTokenRemoteSource.verifyAcceptPWAuthToken(authVerifyEmailAcceptRequest) - .map { response -> - if (response.isSuccessful && response.code() == 200) { - response.body()?.let { authTokenDto -> - authTokenDto.let { - Resource.success(authTokenDtoMapper.mapToDomainModel(authTokenDto)) - } - } ?: returnUnknownError() - } else { - response.errorBody()?.let { responseBody -> - val errorJson = JSONObject(responseBody.charStream().readText()) - val messageJson = errorJson.getJSONObject("error").getJSONObject("message") - val firstKeyOfMessage = messageJson.keys().next().toString() - Resource.error( - firstKeyOfMessage, - null - ) - } ?: returnUnknownError() - } - } - } - - private fun returnUnknownError(): Resource { - return Resource.error( - "Unknown error", - null - ) - } - -} \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/service/AuthService.kt b/frontend/app/src/main/java/com/example/speechbuddy/service/AuthService.kt deleted file mode 100644 index 6547c1cf..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/service/AuthService.kt +++ /dev/null @@ -1,44 +0,0 @@ -package com.example.speechbuddy.service - -import com.example.speechbuddy.data.remote.models.AuthTokenDto -import com.example.speechbuddy.data.remote.requests.AuthLoginRequest -import com.example.speechbuddy.data.remote.requests.AuthSignupRequest -import com.example.speechbuddy.data.remote.requests.AuthVerifyEmailAcceptRequest -import com.example.speechbuddy.data.remote.requests.AuthVerifyEmailSendRequest -import retrofit2.Response -import retrofit2.http.Body -import retrofit2.http.POST - -interface AuthService { - - @POST("/user/signup/") - suspend fun signup( - @Body signupRequest: AuthSignupRequest - ): Response - - @POST("/user/login/") - suspend fun login( - @Body loginRequest: AuthLoginRequest - ): Response - - @POST("/user/validateemail/signup/send/") - suspend fun verifySendSignup( - @Body verifyEmailSendRequest: AuthVerifyEmailSendRequest - ): Response - - @POST("/user/validateemail/pw/send/") - suspend fun verifySendPW( - @Body verifyEmailSendRequest: AuthVerifyEmailSendRequest - ): Response - - @POST("/user/validateemail/signup/accept/") - suspend fun verifyAcceptSignup( - @Body verifyEmailAcceptRequest: AuthVerifyEmailAcceptRequest - ): Response - - @POST("/user/validateemail/pw/accept/") - suspend fun verifyAcceptPW( - @Body verifyEmailAcceptRequest: AuthVerifyEmailAcceptRequest - ): Response - -} \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/ui/Color.kt b/frontend/app/src/main/java/com/example/speechbuddy/ui/Color.kt deleted file mode 100644 index dc20e4d3..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/ui/Color.kt +++ /dev/null @@ -1,65 +0,0 @@ -package com.example.speechbuddy.ui - -import androidx.compose.ui.graphics.Color - -val seed = Color(0xFFAACAAC) - -val md_theme_light_primary = Color(0xFF0D6D35) -val md_theme_light_onPrimary = Color(0xFFFFFFFF) -val md_theme_light_primaryContainer = Color(0xFF9EF6AF) -val md_theme_light_onPrimaryContainer = Color(0xFF00210B) -val md_theme_light_secondary = Color(0xFF506352) -val md_theme_light_onSecondary = Color(0xFFFFFFFF) -val md_theme_light_secondaryContainer = Color(0xFFD3E8D2) -val md_theme_light_onSecondaryContainer = Color(0xFF0E1F12) -val md_theme_light_tertiary = Color(0xFF39656E) -val md_theme_light_onTertiary = Color(0xFFFFFFFF) -val md_theme_light_tertiaryContainer = Color(0xFFBDEAF4) -val md_theme_light_onTertiaryContainer = Color(0xFF001F25) -val md_theme_light_error = Color(0xFFBA1A1A) -val md_theme_light_onError = Color(0xFFFFFFFF) -val md_theme_light_errorContainer = Color(0xFFFFDAD6) -val md_theme_light_onErrorContainer = Color(0xFF410002) -val md_theme_light_outline = Color(0xFF717970) -val md_theme_light_background = Color(0xFFFCFDF7) -val md_theme_light_onBackground = Color(0xFF191C19) -val md_theme_light_surface = Color(0xFFF9FAF4) -val md_theme_light_onSurface = Color(0xFF191C19) -val md_theme_light_surfaceVariant = Color(0xFFDDE5DA) -val md_theme_light_onSurfaceVariant = Color(0xFF414941) -val md_theme_light_inverseSurface = Color(0xFF2E312E) -val md_theme_light_inverseOnSurface = Color(0xFFF0F1EC) -val md_theme_light_inversePrimary = Color(0xFF83D995) -val md_theme_light_surfaceTint = Color(0xFF0D6D35) -val md_theme_light_outlineVariant = Color(0xFFC1C9BE) -val md_theme_light_scrim = Color(0xFF000000) - -val md_theme_dark_primary = Color(0xFF83D995) -val md_theme_dark_onPrimary = Color(0xFF003918) -val md_theme_dark_primaryContainer = Color(0xFF005225) -val md_theme_dark_onPrimaryContainer = Color(0xFF9EF6AF) -val md_theme_dark_secondary = Color(0xFFB7CCB7) -val md_theme_dark_onSecondary = Color(0xFF233426) -val md_theme_dark_secondaryContainer = Color(0xFF394B3B) -val md_theme_dark_onSecondaryContainer = Color(0xFFD3E8D2) -val md_theme_dark_tertiary = Color(0xFFA2CED8) -val md_theme_dark_onTertiary = Color(0xFF00363E) -val md_theme_dark_tertiaryContainer = Color(0xFF204D55) -val md_theme_dark_onTertiaryContainer = Color(0xFFBDEAF4) -val md_theme_dark_error = Color(0xFFFFB4AB) -val md_theme_dark_onError = Color(0xFF690005) -val md_theme_dark_errorContainer = Color(0xFF93000A) -val md_theme_dark_onErrorContainer = Color(0xFFFFDAD6) -val md_theme_dark_outline = Color(0xFF8B9389) -val md_theme_dark_background = Color(0xFF191C19) -val md_theme_dark_onBackground = Color(0xFFE2E3DE) -val md_theme_dark_surface = Color(0xFF111411) -val md_theme_dark_onSurface = Color(0xFFC5C7C2) -val md_theme_dark_surfaceVariant = Color(0xFF414941) -val md_theme_dark_onSurfaceVariant = Color(0xFFC1C9BE) -val md_theme_dark_inverseSurface = Color(0xFFE2E3DE) -val md_theme_dark_inverseOnSurface = Color(0xFF191C19) -val md_theme_dark_inversePrimary = Color(0xFF0D6D35) -val md_theme_dark_surfaceTint = Color(0xFF83D995) -val md_theme_dark_outlineVariant = Color(0xFF414941) -val md_theme_dark_scrim = Color(0xFF000000) diff --git a/frontend/app/src/main/java/com/example/speechbuddy/ui/Theme.kt b/frontend/app/src/main/java/com/example/speechbuddy/ui/Theme.kt deleted file mode 100644 index 32bf4f76..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/ui/Theme.kt +++ /dev/null @@ -1,112 +0,0 @@ -package com.example.speechbuddy.ui - -import android.app.Activity -import android.os.Build -import androidx.compose.foundation.isSystemInDarkTheme -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.darkColorScheme -import androidx.compose.material3.dynamicDarkColorScheme -import androidx.compose.material3.dynamicLightColorScheme -import androidx.compose.material3.lightColorScheme -import androidx.compose.runtime.Composable -import androidx.compose.runtime.SideEffect -import androidx.compose.ui.graphics.toArgb -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.platform.LocalView -import androidx.core.view.WindowCompat - -private val _lightColorScheme = lightColorScheme( - primary = md_theme_light_primary, - onPrimary = md_theme_light_onPrimary, - primaryContainer = md_theme_light_primaryContainer, - onPrimaryContainer = md_theme_light_onPrimaryContainer, - secondary = md_theme_light_secondary, - onSecondary = md_theme_light_onSecondary, - secondaryContainer = md_theme_light_secondaryContainer, - onSecondaryContainer = md_theme_light_onSecondaryContainer, - tertiary = md_theme_light_tertiary, - onTertiary = md_theme_light_onTertiary, - tertiaryContainer = md_theme_light_tertiaryContainer, - onTertiaryContainer = md_theme_light_onTertiaryContainer, - error = md_theme_light_error, - onError = md_theme_light_onError, - errorContainer = md_theme_light_errorContainer, - onErrorContainer = md_theme_light_onErrorContainer, - outline = md_theme_light_outline, - background = md_theme_light_background, - onBackground = md_theme_light_onBackground, - surface = md_theme_light_surface, - onSurface = md_theme_light_onSurface, - surfaceVariant = md_theme_light_surfaceVariant, - onSurfaceVariant = md_theme_light_onSurfaceVariant, - inverseSurface = md_theme_light_inverseSurface, - inverseOnSurface = md_theme_light_inverseOnSurface, - inversePrimary = md_theme_light_inversePrimary, - surfaceTint = md_theme_light_surfaceTint, - outlineVariant = md_theme_light_outlineVariant, - scrim = md_theme_light_scrim, -) - -private val _darkColorScheme = darkColorScheme( - primary = md_theme_dark_primary, - onPrimary = md_theme_dark_onPrimary, - primaryContainer = md_theme_dark_primaryContainer, - onPrimaryContainer = md_theme_dark_onPrimaryContainer, - secondary = md_theme_dark_secondary, - onSecondary = md_theme_dark_onSecondary, - secondaryContainer = md_theme_dark_secondaryContainer, - onSecondaryContainer = md_theme_dark_onSecondaryContainer, - tertiary = md_theme_dark_tertiary, - onTertiary = md_theme_dark_onTertiary, - tertiaryContainer = md_theme_dark_tertiaryContainer, - onTertiaryContainer = md_theme_dark_onTertiaryContainer, - error = md_theme_dark_error, - onError = md_theme_dark_onError, - errorContainer = md_theme_dark_errorContainer, - onErrorContainer = md_theme_dark_onErrorContainer, - outline = md_theme_dark_outline, - background = md_theme_dark_background, - onBackground = md_theme_dark_onBackground, - surface = md_theme_dark_surface, - onSurface = md_theme_dark_onSurface, - surfaceVariant = md_theme_dark_surfaceVariant, - onSurfaceVariant = md_theme_dark_onSurfaceVariant, - inverseSurface = md_theme_dark_inverseSurface, - inverseOnSurface = md_theme_dark_inverseOnSurface, - inversePrimary = md_theme_dark_inversePrimary, - surfaceTint = md_theme_dark_surfaceTint, - outlineVariant = md_theme_dark_outlineVariant, - scrim = md_theme_dark_scrim, -) - -@Composable -fun SpeechBuddyTheme( - darkTheme: Boolean = isSystemInDarkTheme(), - // Dynamic color is available on Android 12+ - dynamicColor: Boolean = false, - content: @Composable () -> Unit -) { - val colorScheme = when { - dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { - val context = LocalContext.current - if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) - } - - darkTheme -> _darkColorScheme - else -> _lightColorScheme - } - val view = LocalView.current - if (!view.isInEditMode) { - SideEffect { - val window = (view.context as Activity).window - window.statusBarColor = colorScheme.primary.toArgb() - WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme - } - } - - MaterialTheme( - colorScheme = colorScheme, - typography = Typography, - content = content - ) -} \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/ui/Type.kt b/frontend/app/src/main/java/com/example/speechbuddy/ui/Type.kt deleted file mode 100644 index e9a80441..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/ui/Type.kt +++ /dev/null @@ -1,101 +0,0 @@ -package com.example.speechbuddy.ui - -import androidx.compose.material3.Typography -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.font.FontFamily -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.sp - -// Set of Material typography styles to start with -val Typography = Typography( - displayLarge = TextStyle( - fontFamily = FontFamily.Default, - fontWeight = FontWeight.Bold, - fontSize = 57.sp, - lineHeight = 64.sp, - ), - displayMedium = TextStyle( - fontFamily = FontFamily.Default, - fontWeight = FontWeight.Bold, - fontSize = 45.sp, - lineHeight = 52.sp, - ), - displaySmall = TextStyle( - fontFamily = FontFamily.Default, - fontWeight = FontWeight.Bold, - fontSize = 36.sp, - lineHeight = 44.sp, - ), - headlineLarge = TextStyle( - fontFamily = FontFamily.Default, - fontWeight = FontWeight.Medium, - fontSize = 32.sp, - lineHeight = 40.sp, - ), - headlineMedium = TextStyle( - fontFamily = FontFamily.Default, - fontWeight = FontWeight.Medium, - fontSize = 28.sp, - lineHeight = 36.sp, - ), - headlineSmall = TextStyle( - fontFamily = FontFamily.Default, - fontWeight = FontWeight.Medium, - fontSize = 24.sp, - lineHeight = 32.sp, - ), - titleLarge = TextStyle( - fontFamily = FontFamily.Default, - fontWeight = FontWeight.Medium, - fontSize = 22.sp, - lineHeight = 28.sp, - ), - titleMedium = TextStyle( - fontFamily = FontFamily.Default, - fontWeight = FontWeight.Medium, - fontSize = 16.sp, - lineHeight = 24.sp, - ), - titleSmall = TextStyle( - fontFamily = FontFamily.Default, - fontWeight = FontWeight.Medium, - fontSize = 14.sp, - lineHeight = 20.sp, - ), - bodyLarge = TextStyle( - fontFamily = FontFamily.Default, - fontWeight = FontWeight.Normal, - fontSize = 16.sp, - lineHeight = 24.sp, - ), - bodyMedium = TextStyle( - fontFamily = FontFamily.Default, - fontWeight = FontWeight.Normal, - fontSize = 14.sp, - lineHeight = 20.sp, - ), - bodySmall = TextStyle( - fontFamily = FontFamily.Default, - fontWeight = FontWeight.Normal, - fontSize = 12.sp, - lineHeight = 16.sp, - ), - labelLarge = TextStyle( - fontFamily = FontFamily.Default, - fontWeight = FontWeight.Medium, - fontSize = 14.sp, - lineHeight = 20.sp, - ), - labelMedium = TextStyle( - fontFamily = FontFamily.Default, - fontWeight = FontWeight.Medium, - fontSize = 12.sp, - lineHeight = 16.sp, - ), - labelSmall = TextStyle( - fontFamily = FontFamily.Default, - fontWeight = FontWeight.Normal, - fontSize = 10.sp, - lineHeight = 12.sp, - ), -) diff --git a/frontend/app/src/main/java/com/example/speechbuddy/ui/models/EmailVerificationUiState.kt b/frontend/app/src/main/java/com/example/speechbuddy/ui/models/EmailVerificationUiState.kt deleted file mode 100644 index 3998faef..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/ui/models/EmailVerificationUiState.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.example.speechbuddy.ui.models - -data class EmailVerificationUiState( - val isValidEmail: Boolean = false, - val isValidVerifyCode: Boolean = false, - // whether verification email send API was successful - val isSuccessfulSend: Boolean = false, - val error: EmailVerificationError? = null -) - -data class EmailVerificationError( - val type: EmailVerificationErrorType, - val messageId: Int -) - -enum class EmailVerificationErrorType { - EMAIL, - VERIFY_CODE -} \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/ui/models/LoginUiState.kt b/frontend/app/src/main/java/com/example/speechbuddy/ui/models/LoginUiState.kt deleted file mode 100644 index 20c459d0..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/ui/models/LoginUiState.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.example.speechbuddy.ui.models - -data class LoginUiState( - val isValidEmail: Boolean = false, - val isValidPassword: Boolean = false, - val error: LoginError? = null -) - -data class LoginError( - val type: LoginErrorType, - val messageId: Int -) - -enum class LoginErrorType { - EMAIL, - PASSWORD -} \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/ui/models/SignupUiState.kt b/frontend/app/src/main/java/com/example/speechbuddy/ui/models/SignupUiState.kt deleted file mode 100644 index 622fd979..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/ui/models/SignupUiState.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.example.speechbuddy.ui.models - -data class SignupUiState( - val isValidEmail: Boolean = false, - val isValidNickname: Boolean = false, - val isValidPassword: Boolean = false, - val error: SignupError? = null -) - -data class SignupError( - val type: SignupErrorType, - val messageId: Int -) - -enum class SignupErrorType { - NICKNAME, - PASSWORD, - PASSWORD_CHECK -} \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/ui/models/TextToSpeechUiState.kt b/frontend/app/src/main/java/com/example/speechbuddy/ui/models/TextToSpeechUiState.kt deleted file mode 100644 index ec920cf2..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/ui/models/TextToSpeechUiState.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.example.speechbuddy.ui.models - -data class TextToSpeechUiState( - val buttonStatus: ButtonStatusType = ButtonStatusType.PLAY -) - -enum class ButtonStatusType { - PLAY, - STOP -} \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/utils/Constants.kt b/frontend/app/src/main/java/com/example/speechbuddy/utils/Constants.kt deleted file mode 100644 index 8ed2752c..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/utils/Constants.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.example.speechbuddy.utils - -class Constants { - companion object { - const val BASE_URL = "http://54.180.112.72:8000/" - const val MINIMUM_PASSWORD_LENGTH = 8 - const val MAXIMUM_NICKNAME_LENGTH = 15 - const val CODE_LENGTH = 6 - const val MAXIMUM_LINES_FOR_SYMBOL_TEXT = 2 - } -} \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/utils/InputValidationUtil.kt b/frontend/app/src/main/java/com/example/speechbuddy/utils/InputValidationUtil.kt deleted file mode 100644 index 41185e2a..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/utils/InputValidationUtil.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.example.speechbuddy.utils - -import android.util.Patterns -import com.example.speechbuddy.utils.Constants.Companion.CODE_LENGTH -import com.example.speechbuddy.utils.Constants.Companion.MINIMUM_PASSWORD_LENGTH - -fun isValidEmail(input: String): Boolean { - return input.isNotBlank() && Patterns.EMAIL_ADDRESS.matcher(input).matches() -} - -fun isValidPassword(input: String): Boolean { - return input.length >= MINIMUM_PASSWORD_LENGTH -} - -fun isValidVerifyCode(input: String): Boolean{ - return input.length == CODE_LENGTH -} \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/utils/Resources.kt b/frontend/app/src/main/java/com/example/speechbuddy/utils/Resources.kt deleted file mode 100644 index f77d66db..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/utils/Resources.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.example.speechbuddy.utils - -data class Resource(val status: Status, val data: T?, val message: String?) { - companion object { - fun success(data: T?): Resource { - return Resource(Status.SUCCESS, data, null) - } - - fun error(msg: String, data: T?): Resource { - return Resource(Status.ERROR, data, msg) - } - - fun loading(data: T?): Resource { - return Resource(Status.LOADING, data, null) - } - } -} - -enum class Status { - SUCCESS, - ERROR, - LOADING -} \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/viewmodel/EmailVerificationViewModel.kt b/frontend/app/src/main/java/com/example/speechbuddy/viewmodel/EmailVerificationViewModel.kt deleted file mode 100644 index 9eba7b31..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/viewmodel/EmailVerificationViewModel.kt +++ /dev/null @@ -1,198 +0,0 @@ -package com.example.speechbuddy.viewmodel - -import android.util.Log -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.setValue -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import androidx.navigation.NavHostController -import com.example.speechbuddy.MainApplication.Companion.token_prefs -import com.example.speechbuddy.R -import com.example.speechbuddy.data.remote.requests.AuthVerifyEmailAcceptRequest -import com.example.speechbuddy.data.remote.requests.AuthVerifyEmailSendRequest -import com.example.speechbuddy.domain.models.AuthToken -import com.example.speechbuddy.repository.AuthRepository -import com.example.speechbuddy.ui.models.EmailVerificationError -import com.example.speechbuddy.ui.models.EmailVerificationErrorType -import com.example.speechbuddy.ui.models.EmailVerificationUiState -import com.example.speechbuddy.utils.Resource -import com.example.speechbuddy.utils.Status -import com.example.speechbuddy.utils.isValidEmail -import com.example.speechbuddy.utils.isValidVerifyCode -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.flow.update -import kotlinx.coroutines.launch -import javax.inject.Inject - -@HiltViewModel -class EmailVerificationViewModel @Inject internal constructor( - private val repository: AuthRepository -): ViewModel() { - - private val _uiState = MutableStateFlow(EmailVerificationUiState()) - val uiState: StateFlow = _uiState.asStateFlow() - - var emailInput by mutableStateOf("") - private set - - var verifyCodeInput by mutableStateOf("") - private set - - fun setEmail(input: String) { - emailInput = input - if (_uiState.value.error?.type == EmailVerificationErrorType.EMAIL) validateEmail() - } - - fun setVerifyCode(input: String) { - verifyCodeInput = input - if (_uiState.value.error?.type == EmailVerificationErrorType.VERIFY_CODE) validateVerifyCode() - } - - private fun clearVerifyCodeInput() { - verifyCodeInput = "" - } - - private fun validateEmail() { - if (isValidEmail(emailInput)) { - _uiState.update { currentState -> - currentState.copy( - isValidEmail = true, - error = null - ) - } - } - } - - private fun validateVerifyCode() { - if (isValidVerifyCode(verifyCodeInput)) { - _uiState.update { currentState -> - currentState.copy( - isValidVerifyCode = true, - error = null - ) - } - } - } - - fun verifySend(source:String?) { - // What function(ultimately, API call) to use - val verifySendFunction = if (source=="signup"){ - repository::verifySendSignup - } else{ // source == "reset_password" - repository::verifySendPW - } - - // Prior validation of email input - if (!isValidEmail(emailInput)){ - _uiState.update { currentState -> - currentState.copy( - isValidEmail = false, - error = EmailVerificationError( - type = EmailVerificationErrorType.EMAIL, - messageId = R.string.false_email - ) - ) - } - } - - viewModelScope.launch { - verifySendFunction( - AuthVerifyEmailSendRequest( - email = emailInput - ) - ).collect { result -> - when(result.status){ - Status.SUCCESS-> { - _uiState.update { currentState -> - currentState.copy( - isSuccessfulSend = true, - error = null - ) - } - } - Status.ERROR-> { - val messageId = when(result.message) { - "email"-> R.string.false_email - "already_taken"-> R.string.email_already_taken - "no_user" -> R.string.no_such_user - else -> R.string.false_email - } - _uiState.update { currentState -> - currentState.copy( - isValidEmail = false, - error = EmailVerificationError( - type = EmailVerificationErrorType.EMAIL, - messageId = messageId - ) - ) - } - } - Status.LOADING -> { - } - } - } - } - } - - fun verifyAccept(source: String?, navController: NavHostController) { - val verifyAcceptFunction = if (source=="signup"){ - repository::verifyAcceptSignup - } else{ // source == "reset_password" - repository::verifyAcceptPW - } - - if (!isValidVerifyCode(verifyCodeInput)){ - _uiState.update { currentState -> - currentState.copy( - isValidVerifyCode = false, - error = EmailVerificationError( - type = EmailVerificationErrorType.VERIFY_CODE, - messageId = R.string.false_validation_code - ) - ) - } - } - - viewModelScope.launch { - verifyAcceptFunction( - AuthVerifyEmailAcceptRequest( - email = emailInput, - code = verifyCodeInput - ) - ).collect { result -> - when(result.status){ - Status.SUCCESS-> { - if (source=="signup"){ - navController.navigate("signup/$emailInput") - } else { - val authToken = result.data as AuthToken - token_prefs.setAccessToken(authToken.accessToken!!) - navController.navigate("reset_password") - } - } - Status.ERROR-> { - // All error cases from this API call can - // boil down to 'false_validation_code' - _uiState.update { currentState -> - currentState.copy( - isValidVerifyCode = false, - error = EmailVerificationError( - type = EmailVerificationErrorType.VERIFY_CODE, - messageId = R.string.false_validation_code - ) - ) - } - } - Status.LOADING -> { - } - } - } - } - clearVerifyCodeInput() - } -} - diff --git a/frontend/app/src/main/java/com/example/speechbuddy/viewmodel/LoginViewModel.kt b/frontend/app/src/main/java/com/example/speechbuddy/viewmodel/LoginViewModel.kt deleted file mode 100644 index b6aec871..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/viewmodel/LoginViewModel.kt +++ /dev/null @@ -1,145 +0,0 @@ -package com.example.speechbuddy.viewmodel - -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.setValue -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.example.speechbuddy.R -import com.example.speechbuddy.data.remote.requests.AuthLoginRequest -import com.example.speechbuddy.domain.models.AuthToken -import com.example.speechbuddy.repository.AuthRepository -import com.example.speechbuddy.ui.models.LoginError -import com.example.speechbuddy.ui.models.LoginErrorType -import com.example.speechbuddy.ui.models.LoginUiState -import com.example.speechbuddy.utils.Resource -import com.example.speechbuddy.utils.Status -import com.example.speechbuddy.utils.isValidEmail -import com.example.speechbuddy.utils.isValidPassword -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.flow.update -import kotlinx.coroutines.launch -import javax.inject.Inject - -@HiltViewModel -class LoginViewModel @Inject internal constructor( - private val repository: AuthRepository -) : ViewModel() { - - private val _uiState = MutableStateFlow(LoginUiState()) - val uiState: StateFlow = _uiState.asStateFlow() - - var emailInput by mutableStateOf("") - private set - - var passwordInput by mutableStateOf("") - private set - - private var _loginResult = MutableLiveData>() - val loginResult: LiveData> = _loginResult - - fun setEmail(input: String) { - emailInput = input - if (_uiState.value.error?.type == LoginErrorType.EMAIL) validateEmail() - } - - fun setPassword(input: String) { - passwordInput = input - if (_uiState.value.error?.type == LoginErrorType.PASSWORD) validatePassword() - } - - private fun clearInputs() { - emailInput = "" - passwordInput = "" - } - - private fun validateEmail() { - if (isValidEmail(emailInput)) { - _uiState.update { currentState -> - currentState.copy( - isValidEmail = true, - error = null - ) - } - } - } - - private fun validatePassword() { - if (isValidPassword(passwordInput)) { - _uiState.update { currentState -> - currentState.copy( - isValidPassword = true, - error = null - ) - } - } - } - - fun login() { - if (!isValidEmail(emailInput)) { - _uiState.update { currentState -> - currentState.copy( - isValidEmail = false, - error = LoginError( - type = LoginErrorType.EMAIL, - messageId = R.string.false_email - ) - ) - } - } else if (!isValidPassword(passwordInput)) { - _uiState.update { currentState -> - currentState.copy( - isValidPassword = false, - error = LoginError( - type = LoginErrorType.PASSWORD, - messageId = R.string.false_password - ) - ) - } - } else { - viewModelScope.launch { - repository.login( - AuthLoginRequest( - email = emailInput, - password = passwordInput - ) - ).collect { - if (it.status == Resource(Status.SUCCESS, "", "").status) { // 200 - _loginResult.postValue(it) - } else { // status:error - // when password is wrong - if (it.message?.contains("password", ignoreCase = true) == true) { - _uiState.update { currentState -> - currentState.copy( - isValidPassword = false, - error = LoginError( - type = LoginErrorType.PASSWORD, - messageId = R.string.false_password - ) - ) - } - } else if (it.message?.contains("email", ignoreCase = true) == true - ) { // email is wrong - _uiState.update { currentState -> - currentState.copy( - isValidEmail = false, - error = LoginError( - type = LoginErrorType.EMAIL, - messageId = R.string.false_email - ) - ) - } - } - _loginResult.postValue(it) - } - } - } - } - //clearInputs() - } -} \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/viewmodel/SignupViewModel.kt b/frontend/app/src/main/java/com/example/speechbuddy/viewmodel/SignupViewModel.kt deleted file mode 100644 index b4d7d619..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/viewmodel/SignupViewModel.kt +++ /dev/null @@ -1,149 +0,0 @@ -package com.example.speechbuddy.viewmodel - -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.setValue -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.example.speechbuddy.R -import com.example.speechbuddy.data.remote.requests.AuthSignupRequest -import com.example.speechbuddy.repository.AuthRepository -import com.example.speechbuddy.ui.models.SignupError -import com.example.speechbuddy.ui.models.SignupErrorType -import com.example.speechbuddy.ui.models.SignupUiState -import com.example.speechbuddy.utils.Constants -import com.example.speechbuddy.utils.Resource -import com.example.speechbuddy.utils.isValidPassword -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.flow.update -import kotlinx.coroutines.launch -import javax.inject.Inject - -@HiltViewModel -class SignupViewModel @Inject internal constructor( - private val repository: AuthRepository -) : ViewModel() { - - private val _uiState = MutableStateFlow(SignupUiState()) - val uiState: StateFlow = _uiState.asStateFlow() - - var nicknameInput by mutableStateOf("") - private set - - var passwordInput by mutableStateOf("") - private set - - var passwordCheckInput by mutableStateOf("") - private set - - private val _signupResult = MutableLiveData>() - val signupResult: LiveData> = _signupResult - - fun setNickname(input: String) { - nicknameInput = input - if (_uiState.value.error?.type == SignupErrorType.NICKNAME) validateNickname() - } - - fun setPassword(input: String) { - passwordInput = input - if (_uiState.value.error?.type == SignupErrorType.PASSWORD) validatePassword() - } - - fun setPasswordCheck(input: String) { - passwordCheckInput = input - if (_uiState.value.error?.type == SignupErrorType.PASSWORD_CHECK) validatePasswordCheck() - } - - private fun validateNickname() { - if (nicknameInput.isNotEmpty() && nicknameInput.length <= Constants.MAXIMUM_NICKNAME_LENGTH) { - _uiState.update { currentSate -> - currentSate.copy( - isValidNickname = true, - error = null - ) - } - } - } - - // Check password length - private fun validatePassword() { - if (isValidPassword(passwordInput)) { - _uiState.update { currentState -> - currentState.copy( - isValidPassword = true, - error = null - ) - } - } - } - - // Check password equality - private fun validatePasswordCheck() { - if (passwordInput == passwordCheckInput) { - _uiState.update { currentState -> - currentState.copy( - isValidEmail = true, - error = null - ) - } - } - } - - fun clearInputs() { - nicknameInput = "" - passwordInput = "" - passwordCheckInput = "" - } - - fun signup(emailInput: String) { - if (nicknameInput.isBlank() || nicknameInput.length > Constants.MAXIMUM_NICKNAME_LENGTH) { // Check nickname - _uiState.update { currentState -> - currentState.copy( - isValidNickname = false, - error = SignupError( - type = SignupErrorType.NICKNAME, - messageId = R.string.nickname_length_error - ) - ) - } - } else if (!isValidPassword(passwordInput)) { // Check password length - _uiState.update { currentState -> - currentState.copy( - isValidPassword = false, - error = SignupError( - type = SignupErrorType.PASSWORD, - messageId = R.string.false_new_password - ) - ) - } - } else if (passwordInput != passwordCheckInput) { // Check password equality - _uiState.update { currentState -> - currentState.copy( - isValidEmail = false, - error = SignupError( - type = SignupErrorType.PASSWORD_CHECK, - messageId = R.string.false_new_password_check - ) - ) - } - } else { - viewModelScope.launch { - repository.signup( - AuthSignupRequest( - email = emailInput, - nickname = nicknameInput, - password = passwordInput - ) - ).collect { - _signupResult.postValue(it) - } - } - //clearInputs() - } - } -} \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/viewmodel/SymbolSelectionViewModel.kt b/frontend/app/src/main/java/com/example/speechbuddy/viewmodel/SymbolSelectionViewModel.kt deleted file mode 100644 index ee0032f5..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/viewmodel/SymbolSelectionViewModel.kt +++ /dev/null @@ -1,86 +0,0 @@ -package com.example.speechbuddy.viewmodel - -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.setValue -import androidx.lifecycle.ViewModel -import com.example.speechbuddy.R -import com.example.speechbuddy.domain.models.Category -import com.example.speechbuddy.domain.models.Entry -import com.example.speechbuddy.domain.models.Symbol -import dagger.hilt.android.lifecycle.HiltViewModel -import javax.inject.Inject - -@HiltViewModel -class SymbolSelectionViewModel @Inject internal constructor() : ViewModel() { - - var queryInput by mutableStateOf("") - private set - - var selectedSymbols by mutableStateOf(listOf()) - private set - - var entries by mutableStateOf(listOf()) - private set - - /* TODO: 나중에 삭제 */ - private val initialEntries = listOf( - Symbol( - id = 0, - text = "119에 전화해주세요", - imageResId = R.drawable.symbol_0, - categoryId = 0, - isFavorite = true, - isMine = false - ), - Symbol( - id = 0, - text = "119에 전화해주세요", - imageResId = R.drawable.symbol_0, - categoryId = 0, - isFavorite = true, - isMine = false - ) - ) - - private val secondaryEntries = listOf( - Symbol( - id = 0, - text = "119에 전화해주세요", - imageResId = R.drawable.symbol_0, - categoryId = 0, - isFavorite = true, - isMine = false - ), - Symbol( - id = 0, - text = "우와", - imageResId = R.drawable.symbol_0, - categoryId = 0, - isFavorite = true, - isMine = false - ) - ) - - init { - entries = initialEntries - } - - fun setQuery(input: String) { - queryInput = input - } - - fun clearAll() { - selectedSymbols = listOf() - entries = initialEntries - } - - fun selectSymbol(symbol: Symbol) { - selectedSymbols = selectedSymbols.plus(symbol) - entries = secondaryEntries - } - - fun selectCategory(category: Category) { - /* TODO */ - } -} \ No newline at end of file diff --git a/frontend/app/src/main/java/com/example/speechbuddy/viewmodel/TextToSpeechViewModel.kt b/frontend/app/src/main/java/com/example/speechbuddy/viewmodel/TextToSpeechViewModel.kt deleted file mode 100644 index 2807cd97..00000000 --- a/frontend/app/src/main/java/com/example/speechbuddy/viewmodel/TextToSpeechViewModel.kt +++ /dev/null @@ -1,114 +0,0 @@ -package com.example.speechbuddy.viewmodel - -import android.content.Context -import android.os.Bundle -import android.speech.tts.TextToSpeech -import android.speech.tts.UtteranceProgressListener -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.setValue -import androidx.lifecycle.ViewModel -import com.example.speechbuddy.ui.models.ButtonStatusType -import com.example.speechbuddy.ui.models.TextToSpeechUiState -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.flow.update -import java.util.Locale -import javax.inject.Inject - -@HiltViewModel -class TextToSpeechViewModel @Inject internal constructor( -) : ViewModel() { - - private val _uiState = MutableStateFlow(TextToSpeechUiState()) - val uiState: StateFlow = _uiState.asStateFlow() - - private var textToSpeech: TextToSpeech? = null - - var textInput by mutableStateOf("") - private set - - fun setText(input: String) { - textInput = input - } - -private fun clearText() { - textInput = "" -} - - fun ttsStop() { - textToSpeech?.stop() - } - - fun ttsStart(context: Context) { - // disable button - _uiState.update { currentState -> - currentState.copy( - buttonStatus = ButtonStatusType.STOP - ) - } - - textToSpeech = TextToSpeech(context) { - if (it == TextToSpeech.SUCCESS) { - textToSpeech?.let { txtToSpeech -> - txtToSpeech.language = Locale.KOREAN - txtToSpeech.setSpeechRate(1.0f) - - val params = Bundle() - params.putString(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "") - txtToSpeech.setOnUtteranceProgressListener(object : - UtteranceProgressListener() { - override fun onStart(utteranceId: String?) { - // Speech has started, button is already disabled - } - - override fun onStop(utteranceId: String?, interrupted: Boolean) { - _uiState.update { currentState -> - currentState.copy( - buttonStatus = ButtonStatusType.PLAY - ) - } - } - - override fun onDone(utteranceId: String?) { - // Speech has finished, re-enable the button - _uiState.update { currentState -> - currentState.copy( - buttonStatus = ButtonStatusType.PLAY - ) - } - clearText() - } - - @Deprecated("Deprecated in Java") - override fun onError(utteranceId: String?) { - // There was an error, re-enable the button - _uiState.update { currentState -> - currentState.copy( - buttonStatus = ButtonStatusType.PLAY - ) - } - } - }) - - txtToSpeech.speak( - textInput, - TextToSpeech.QUEUE_ADD, - params, - "UniqueID" - ) - } - } else { - // Initialization failed, re-enable the button - _uiState.update { currentState -> - currentState.copy( - buttonStatus = ButtonStatusType.PLAY - ) - } - } - } - } - -} \ No newline at end of file diff --git a/frontend/app/src/main/res/drawable/category_0.png b/frontend/app/src/main/res/drawable/category_0.png deleted file mode 100644 index 3c22c2b704a41cd939be809d07740d7b88413636..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41416 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 diff --git a/frontend/app/src/main/res/drawable/outline_add_a_photo_24.xml b/frontend/app/src/main/res/drawable/outline_add_a_photo_24.xml deleted file mode 100644 index a2f3f7a4..00000000 --- a/frontend/app/src/main/res/drawable/outline_add_a_photo_24.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/frontend/app/src/main/res/drawable/outline_settings_24.xml b/frontend/app/src/main/res/drawable/outline_settings_24.xml deleted file mode 100644 index 5b2b2822..00000000 --- a/frontend/app/src/main/res/drawable/outline_settings_24.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/frontend/app/src/main/res/drawable/outline_touch_app_24.xml b/frontend/app/src/main/res/drawable/outline_touch_app_24.xml deleted file mode 100644 index c8fb1d23..00000000 --- a/frontend/app/src/main/res/drawable/outline_touch_app_24.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/frontend/app/src/main/res/drawable/outline_volume_up_24.xml b/frontend/app/src/main/res/drawable/outline_volume_up_24.xml deleted file mode 100644 index d61164f9..00000000 --- a/frontend/app/src/main/res/drawable/outline_volume_up_24.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/frontend/app/src/main/res/drawable/speechbuddy_parrot.png b/frontend/app/src/main/res/drawable/speechbuddy_parrot.png deleted file mode 100644 index a61beac3cd1a62211d6045a2495a4fb7c741865d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41959 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 diff --git a/frontend/app/src/main/res/drawable/stop_icon.png b/frontend/app/src/main/res/drawable/stop_icon.png deleted file mode 100644 index 2800abf6c5741bdabd5c3c0a7f2b36cf0c2afb7f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3051 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 diff --git a/frontend/app/src/main/res/drawable/top_app_bar_ic.png b/frontend/app/src/main/res/drawable/top_app_bar_ic.png deleted file mode 100644 index ddff62c6fb73072d643034808623e320b16849d7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3543 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 diff --git a/frontend/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/frontend/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 061b2b53..00000000 --- a/frontend/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/frontend/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/frontend/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 061b2b53..00000000 --- a/frontend/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/frontend/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/frontend/app/src/main/res/mipmap-hdpi/ic_launcher.webp deleted file mode 100644 index d2ace946cf0b3065532e5af4f6f28e696f6f78f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2220 zcmV;d2vhe`Nk&Gb2mkZJ2~V?Cvs%h~(&xC|9_# ztvyb@UIc_b^3W3v5RrTDy@ycVd#NY<|L^=CF8oG?;?t!HRYFP!j3Od7-3ll|ozM#z z9c;*`4!nn22zRJ}h99f?Ee=@!EJ5k zc4kk<&ixK|cXxMpcXxMpcXxMpcXxMMaQ06L6hQ%mzl_W}xC{w5q7!%TfG+4@bHa%z zfC8)v>YxllB2rQ)gN$$=GH-!0AaqhK!MRit0DxsAWo_HGZQI`0;bq%v+qP}nwv9=L zYa5bn+cs@yJlnSaDlDd@mZELjRok|0J7@2sYaZUS`>(cb8-~u5z1={Y@8*DX0E5z& z1am`05mG5Bdqj3ChYxFpq<;9YZsf3@&`y4C_V|;c=-fJC^K-}?de8;&>0z_8qZEfT zTSOuAiylyXP|}^!4S=F8mJIoKujnxarI736abaAkN*N{q(rw$NrE=)uky|E>2 zk;V#=Sil@(sb3}802s4kf<;zGQeLMyEYcLuNGcm1Q^X9=l04f43$Ynn6JppK5hCR)6MI3K?IQjz%&7pjC=Taux$@=K@Lt+*5t;E;{$;&vrudOdiu$ z5$OYk22F|X0sxp{2n|{RY^MQ21I1D4zUf~y5u86ta{5q-*}NAQ#> zh2i(2$P%TzUKM{MpeRkS^%(-<4^%ts6srPm7VUC`c93L#7yJ{M)p~tx&XM2za{Zu8ioA3agmm? z0kGM((s}$n`e$*?ldRAdeq}rRZUTV^MmGWe4t54+6pcijsGyk-0KY||R|>fH+5gfP z2efJ@fNCSIsw(14`Rj|)a_lDD!2i~#Iw|Z@tXW@}?*Ugni_Ifh9ApS$Yh`h5=B>Yw zsPBQ3yHH@sZ2)!>tuhRlgI0)?zb;T%U3uA>t_%xV*ClR8&*-gvBR7u!2sXL&5@9=kovS47We*)bHzk?ZpYD4Tml+)~X z@me9${D9j2gYABfH2*jJqQm!*A_=`7=PRwZ9XBf#u^QS+#`Jqxs+YKxQO(f(FvDEX zsYBv|?`x+s6iV^R<86-%bX@+>ggu4C}k7VGs1OL}w14|CWWi>(^!w8{}E(;`>CxdUe?SNj3>0wHPSmHKUUzLhojR#xX*^`sWx@;EH#+%vu}AhXq+_HT8pDR&Jq zhW``C>r7+e$kF=0rt1Elx{;))&v>^Mvn$&}`d~;G6d~9_&ojPmQ!C@`ChO@c@8d2V z_AGNs-YVcN=Lb>L`p(Ke<2C+I6b&DVQ_*9AtHU(P_cB9}0T?g_XUc_Jffe~(P(%xG zUhpy2k}9_^dQG>Nxkj3_T4GuDh8<%o@fTxSe-r9Iuqw_9dXhK23LG)3S2_)FGw>Ji zmpCW(YGDk-|71rf+&{X62P(L7No=fqTstihiTE#7ggeRM&tNA}y_AI`;)~)RravkX zD~q==c|~_%qmhl!1gksmol=Qfiv6TOms>&|jLC!a`^n8p^e$)IPo_FZ7AM#ppipc$ zfBRZzQcUp-r@Y}Yoq2|LuMO34%VSgw@$Sc-RAxL~sjn$=&>R@9G^Y!-Wvr*$fMuBj z5`YGX%%*%-H5nmI?JxZcAbz+-tj5Qh1~AJ1KR=xM*RRh7Re1k)1$s;WF1hd0cg@r= z#IDLZ0U!#HtG>2IU7L>0eLl71-fyX6uvkm!gLpi#^v+m7>N1Je()-7k*XIYtA(1%V uib|0H!T#H|R}d@yprF@Pt$$G=mO)Eh#yiHZP@M<|K_ diff --git a/frontend/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp b/frontend/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp deleted file mode 100644 index 5c1a5dc2f80b4574e744afa1c6786db820c6e519..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3734 zcmV;H4r%dHNk&GF4gdgGMM6+kP&iD14gdfzp+G1QRoS)v|Fo^=yVlyaxz^fizqW1L zwr$(CZQHhO+qUmu&AkujY|k8T#R~||1;qAla}g^#BTgzOo!w=mmRUbPu&JCos(`BTxFW?`n6I<2GU7a#4Z5wUIsZ#3#_8DnYv3+e{L2R{I zT~waxj9fxS+85P(0V$meFiVzujF-EM%Gav7uOK&IlrL@}PDD9!=o0`7>Eu&6|S6iO+bNZyXiI$Sm)YeRkz+o4Ew z0loq)xCW3MxGz${ek?weQXi)U82KaCKqMwq#Blawa9oVU7~mIBmRkT3fXyNiHiMy* zQXiZC_?tnpkUQiG$$&XPglP&6(-CU{+yvrt3ZT`2%`#D3LTN1j7@;ZX75V_p^sPbi zAciGdcEA_t!6krbz&(i`vSuiy)crCB&e%YUpwaXI%|NH1=>}4OFg61bs{@<@!g2_p z9kJ>HRd(G%sLY`^(DV!$fGI=^?Sf{zMqucPo*BSzUj)rHL2>%0o23i84H~|n6m=eZ$Ih4`57fPDx_ueghsUs*ENWAKAY1O5_ zwq1KsS7oz+RQvgsIf zvJ(9TcmgEj0zgLKfAf4Ov-3K_`Ij=#aOj0ntrg!KJ0=@5-BQ$kstL!Dl*+PPg8*IG4@d=kG0VpN8XhUGV3vVClm(lgz7q&Y6wJi`D9?AX zGQ3xaTmLO$L60buzfzmsbZWJ_2AkOkFq-{7N?PgM|tFT^(07Kai7!xX_XQ{^ zcHIUdhN~}Pq?$q|%fbGHODj~q(}3f6>OxHSB0yu-1Hu4XZYe*4r&M<1*wKeef%YMB zFcbZw@_^ZHc*B7!^j}D>{v8sx`a7C)9wG_N7d;F}%W^=%L4i|CH*kS^ej>-Y?B4)V zgj7IRg!@+YM~qNY$Rs&A9P^@uolHa+#IE)}BS8mXI}nc5whA;j8QH&~H+C`tfl}!n zOcH<)LSoTfQ&O!s@X`V_c{iYz@$4!9KL$V*x@_2@R^hE>XL-Z^$O+`hi z&u;~z5bpT`)&p__-}Fq7H9`ZYteqX1Wib(@6YW!&&%=OhY!~uFUXHV&fz@R_{+9Jn zN~zm%gfII76!bFg9Bca7?7k7gd4da%LHb2$}xwKqAW8 zU~oH)@Ld9QV>6)D!p!qoISq`0aTp>2aXtE+!v ztYUE4g0u;KhqVUeEc}{4uj)@q) z`PQxI6z_jg@w%g`Tz!byum2IH%gCS5Mt?e`d+uc|ON%FBy-fhco)}CzawNv&)7DD;wrxtEUNIm4SNB-$gpjVU#2VR zTwO}%>TvWT9gJS&`dv%r7;d=Xnw+s-&W9d~;l;Nczx>Jl-OrM|^}fRQUDf!kjjlgj zZHssLqgWB){4NhMFCr{uT)7}?LC=JHu7|aNNcSYMKl#$~hf{80%4&rixUSWSD-7px z=dyW<-F?Z&EWSl0f1=c94IFvj=nT93tza_<0u10;8>l}sh_LIW{epRHKgZ>|rIyqCxLclh8mheQ@Pc$7`c^CvNWoe_ zSYVIYkEpZ`R*?LU_yK{_VQOUT2P)aB2|F^=p z*8SKHaO5lObt;nI+B&t42-H0|q0XTRB20dF z7&h_SABg7F_a+c4Le^hm(rT|zgREW6l0eM&3a!?>ggJ$zpa{!!{@|_vN$$DiN97O7j4a}W_XY&=2+&9{WqW*EXqQL{{8a${Z%1>qXK$ST4DfWukpl!0bm9h#;oI z|3stuIVbTi%!L0k7W{7+%h;5K=x=i6??tcrsmDgA^@(zQm#8Xerc})C6A8j#b|4gs z4GFXdKHfR?)*9(H)Qaj+ktm)NNcdd2+}AX_Z}o$6sveqC{ET+eR|N=p*8Xoo$QurK zxCR`?+i?xHbJS=v+mRb`7^g|65gKzCC4P-J845cT?zUB3VPo7PTCGn3-+#bfQvfS~ zKenIZ@>TQ4ONgi|3A?IXl2NfdrMxjod8}#@$Mq6MzoW+K=dFs%P{jqL4H$)@0~P>Lc+LnE27cIl zipzaXlgcC+&!|L}R^iB$a>gbVHor|8Ej6UC@`)4?UhBC1wkhr3bvs7BEDTr-gyp#- zFqouxsLFdvnieR0UYi^@G)Ve*g~*>2n2t#Fc+QPRr*xueZe-xh%(Jh8=a4@DUaZjI zPlUmrsJ~CB+yD2jzk55@B!Dj}ABoZ6t?3?Cl;15itQCqfwdN zh3@>NBmci*OF4tPySux)ySux)ySux)yYt4~r{%pJu$Zaod%N#BJsbGfOG!@=5l%?m z=xt(T0cfM?cu2?sJem}DB6sItBTJYNm+_R$A#%&O5f)CB#TG$zy%2YY$ej_~_2rE> z?(VP$iqN5Jv_na?tu1?VGR!zJlaheC>bwT308P|D4AA%8hd%h3d96x}WLveWNu78| zf&@qazTC66oO9(ocacjbkM}m)&c- zFVOM-|J3D-@!;S-Joh;q+qP}nwr$(CZQHhORh}hWod0w8F!gjZ{nYd8$EckHqf z|BBo;QoM{O`U8*>9VlA#Zy!`AG!0@R+AKf|4|Ee0kWM1zbm_JZ4(56NW%<1PNQm#L z=<{ak$6mZZ3i-*XEz<@7p+cOua24FEMANt^{T8KpQQ8yC&IRduk3@pm-tVIH`yubP zRBoIU0BloD*%|=fjM9R6x+uL6rENii!J9!5!+2g)d49tC0Gh4Z7CL}n#a3)>$h*~n zVKAXBgfqLdc(Xg98Hh)a_!6FgMJ&tBm@(gviv#GUI;{ZS8eBx_qbR{(i&!4!5|6bA zW5(+sotz4fRR_U}s$hCZ4Q9C+CT@!{#oeBOXa_@ID5X_bgUk_6Ok1ylhmZCLoNMJTZ3-kWM zkhQAOC`eb~(|y3kF7vG-D6^PqSd5ntzEw2*jp@A1%gI$VgOd=-!Vk-Ah#F?_1*vz# zjAA>lhq;%E>?DIlK+&R_UCr602}Y+5{M#QP!L($Md2gh$>}Ocs24OBl5~@Oo zWN>4t?*5Ks;Ub`9k=&N2cZtGXXuRna;of>&_O>A_Xyz?+&$>yn9idvN2wz5 z2!;MgiES1p{4D~C?y`-OiU@rOQsKxY%vIRi2yfw^pen&c9FI)6VMeI}o{S@HlH+s3 zaUsc4;N5TY1j(!bTX{$TPJ@adT`&)cM&d%Hc9KdBq0a!Islgp5J%L%kWS|M)o(qLH zEO(>XdQ{~6(g^Ms(^qJM@)!%8{61mc2PxmbO?4H*Yk+@*+K{@yTA&4x1h}{Z;79>S zV#LSiKNRW85fOs)7cwrr5H~7K)A=_Baw?_8USE8hBFCf0_%ZkKsR76&6+xgqRR1%!)EMkp>_oaMr1D%rIAA6d4Bm@yAMF z3=j}>Vetb~)F(_=A2(iYN_>Iq;Yh_OW{{0KG@?7E@2eA-@_H2W0m59Wy%{sn5cWD| z_*alllm*rSFE0gZ0wzqAMzR|wsZE-$KJLdJ^7EZD#^=n0Jj>#hJ}#^35Nv3YyxAV} zkSY6Kn(!3<1!h3oj1N|p09Pyo5`j43G+c1}&m?+$gvzYx>f=VMOb@{Ic8qa`!cM|O z><=~X3eF#a4H0E&hR_Uz%!eWsnOIci1LnAU$nD4ntN`W%0T~)ul#i9y+3A(|e@{E!B&Y6jT62=6O;y=xij7%pqh@^8YW8@ccD*zRk#$btr7 zLI?|2gJ>@UFeCkbh7cDl9BmsnSOV;I@L22$qhifDVT<{ol?(4AABaXMl-o{lW?%}h z?qw5K^M|2;?&t}fSxHpyiy5)V1zb-I%ka-R3q%6<09`*aIrbkMfz(K(h9LDAQxGrR z<(Y11O}E-ok|u)rI3v*U3Gn&T>2rwn9O54X{3~oQ2g$RW`T_ZnW|=MWei~C+5FwyN zG5sXa^SO7^j&-2VAeQ!gW|9X8Z(#32rW1o$xCH$mdu9AZz|=Gin$p0IW}0RA`>M4W zGjKNUepSqG3QyFv09dPQ2uv{tB83tlN(fdlU*o(Bf)?Y|9daC{IN3ISMG7M zYv{W0MKy0TLht*du|q?xw`$ScPjD+w5mMR);56L;%w;U>PR&5*)dPS3$sJ@ID8gI> z0N8uHAC^=cj1;;N+T*mx-9ZoZ7-2mePO?$Ww=p#kDKE5&Lq(x4z&(II1rZ|-#6{cA zS+Iw_fht$j{ASAgkD|SLXPZF|>;c%r-UJWgr4hIgT8NCDwoVrn&@?Cy1f$4iSpe3X zf4`^AX!MtFnLjx#YsnQpp5)=vc+XzSHJYjtR8?S+kV4f^AHTGoJe2C*BYXd}16AnL z0093K!*P^a@}7j=D2V4m86YM}L%<8~{)<^y{XVE>tmm(1G;AE+xoc3*-qGzlCbn#y zQNN+$i8J9oe+u>OYo=RwJC5xi-nBdBy~or+(;-+ib=&~(>P?zPoU+uBZDtv>XZ}YZ zB;_UoPRNK!Jl$yjzl3}DX@1Sx<>f18*R3yp_G02k&t}!F|JW>y?ARIg)jKyhyQ@{Z z+=)W~XK{}?MrkQ&4zdzjmT9X!%3%W72$-{0Z7?jHF*7`&6#B8(-A|hjTqxkTUrx3w z-aa{9ZzTKo?)!L2#mb@Gdvag7;cUx{d}ny5$6log^cjRVz^m^v*CEpJ{IGe0`6`dG;pE zyB|KjXM?_Q6rSveaccyoVY!>TgYbe|t!-4L&|Hn$n{f##3tfJY=^XWkG+t?GT3KzB zBb#mD1YYaur@cdkzgux|Kz84N?Ea?pJ#DJ|E$Vy)r`yw>9F=Qf?1e3AeIcHC6>1i0 z4)zusZr|`A76Z-MsJs<_42_ov4V<~v*mkd#MgxGy5D16xc!|@I@-P?q?y#@FZe8t5 zd1e%|-CAg>{p-%9fvzQiHr2j7^JAUv+c9qpM__NVi8+sc3^EIaf&{0VpNzzXBx6RV z$@&3-h?E1^2)I*ptq5aRKcC>|ovU_xPvOb-pwGQ7aZYNtHS5Zl=5@Y?&AtLN?VCv| z_C*Bq7a~^hP{CZa%s`WpC4o0=`mfq*Eg~5c#I}&jhMV@99VZ3`fK)}mXl{4VjTFA) zvN{NDJ(BkI1o8Gp&{^5##WlYV6f!G(v==NJ&V|E?A#U2wlV=0lq7yp~0$$;t=w?C1cuwEBER@oJ=m#z`;*0uH zcgRtA(BG({zgB&JgR1@}8- zX(#z56{Ysl9I+Cb`|_&o_wc*iWi>2eL>HK7Xb)FePPQJ{v7hBWpn&2Ov%BhM+%=^c z^vUq5&3$bO23r>nwJ08_-q@e$bi09M$Go7XI7cO^)9+_J{VF+QO1NT`;8e$zGyDW&u7riUOUSuK1^ zQ};CAB%a#?FhEXIz(yc9b61~dk*(jJ-{xe^;rFH2^G6S}V^@e;{@0JfJw|xLZ)d24 z_0c~|R>ZsC7MOTwZZU%w>oq zc&Jy|iXV?iM(yI2dD7(W;Ck**|Gwy;L|4GRVf1ls*+`J?m@|Db6`5322Eg70&f=e8 zx&-EcM}}IX^{AEWSu)2Oa@xCZXdgJBC%aytkwVeg`; zLnbFtNyW~qVadu#FuRRrh6%^I2c*F^{7}NS$tWo+C zsN^Ro|2ru2>l@`iywLe(hncHFjUO92SH@|J+f#6n!@xByFIGYb6ndR+(n7fthfUFs zXykN8E&p$*|9C<7t1V`(grGufh#*kucisy_x)T~dixw+) ztUM}|viQ=gdRc8svp2ThisCo`0&49b>es`1n-L`ZmOd%$-<{Ro9jg&3 UufMFOG_a3&dHXHWkUmlX08d^N#{d8T diff --git a/frontend/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/frontend/app/src/main/res/mipmap-mdpi/ic_launcher.webp deleted file mode 100644 index c588ab6d283835769584347a103bdee7a72ce15c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1356 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 diff --git a/frontend/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/frontend/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp deleted file mode 100644 index 3766b106c018a236aa32a27f71cf18868f2c2fdd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2504 zcmV;(2{-mqNk&G%2><|BMM6+kP&iDp2><{uFTe{BHHU(<4Vc!y>>UjeF#&7^46jNz z`~O99^DjYE1g2^LJ7CP1DP(45W@gqg-~3lh_2AHU@O>r{wj)pMkR4wETfkM|cw;EppW^Nl$dM!|l0x;9=VW1ePiJOzFEj54jsSp#q|xeZ+o)`GwryLT z%?H@NFW6Z3qxx(k2?Mu{6eV-a)V(*zjkRsrl+0Z|_iq<>cXxMpcXxMpcXxMpcX#c8 zp@(1I`HG>7{|!kgU_;z#210VH;O~RzK|1(i!p(3>(QtEy5;od!BdQ_X=r3W1HmGBZ zAZDmQ5&(c@BxP;ewrv|v+qP}nwtcp3+jmWG)2?mFk!@SGs)@V1YqN+5=>V~0q+~R} z-QC^!?t0HHzt7)0Pwz31wvB%y6L2nXBZ}O%ZP-0eK^_53mjgZq$hosOfeVH1&#nzG zT|Rjs!hynSm;L=|&2=;9ZuU119mi@@{a%mpR4yL360S^f0HiI%#NExZ5 z68lk;kzoTA03a|7BBG`PP}x~3B&kU_+TBJ>(|6vcs%4SY5buH=gLgJ4JzxFJp!HBN z)~$d4EnY%lb}Ld&iFY&f?M4M~kA zJfHBvC_7pe`a1tN`g|7kcj2&{r4#*E_!Zok!f&+lalNyM%(GTK?V^_1IWnvW{UQxN)pTRvz=?iHLvZW3xLS+NGLM$)@RH- z;r@(pyG&Tx-Et_D-wX5A$YT0{jpdbS0)@eqlkZBlQ(cAipxnDb3veA63%B9hV{6so zXBXj-Ssl-OF|JF?lEhXh(laO@V5IBf1GxL4{(8U)C|FnFIf!KOui1y@(x z)Y%baW|UAwaD=aP-0K5_w`@^Fv|2dE*^gSRhC&7!i5r92c*RZvZk~|eL4TQyO+pIKd1|p;y8*q{OJ_~mue!V< z5pLtJKz<91zf+BfbmH)&lIR{_Jvcjk93a)-Z9IX_t=q&ZHySL&b;Ux>CYjZs)uN~D z%ST-E}-zn3We;|46thBS;HUki!?goJ;@) zqA=H)I_sbiZ!4q3i&v|fr;Hq(k^kL0CyK_MJz6|rPS>;i+M*N2nVsFNJ}IA zL4Gv34k-f-gah?pX0Anbe&%>tq1uHi#U3QpIA1E)lX7h@9~eD6tM2VPd7q}_c~*_l z&nMhMfbuvI?NC*-x-2@7`RRuk8+GsVw!qIWnyi;zancJp zO4dRl&stp9&Q`rz+vLAjBkqqfLu)&XDeu&3utnmprQ8hj5M}u5li=elBO)?N;|SA6 zOoJjxzzhq&R@-d?(FmyJfP;ZnuysI&f=^vZSF(Qv(!8#c{ZXxk1MM_^HAY$+|ctD4}7)U2<{i?7PT^T6 z=#k(P?N+O{2dS%bAn*NZ9U5WeIWP=aG9jhWV7q&Ls`^yC*enKB89E^kI||Oh*LubC z>%kagvRK9-!)Rn0j|}fo{t#13XLCMocCw&JWgzacTC^u}8(M}R(ye9`xY?l6Y>V`- zYD8cvMx@}0cn6G?ui<*o9ZlKz%oFYVyyt$ZJjWQAPcNmEEuJ)ID7zNsB&h_S3t)#7 zRW7UVyiHRBgT~cTGqA##=_@IZRbS1+E;-8n5&r;IKq2o*4Bdrr=`rXWB_UtZNW%1A zQ`?AXHA8a!lt1n>e7!*c$cuqqr}c8^iN~A&{U5Yh^H70`{1VJCeC&LscOw?yI?z=7 zA4l1!)p|MhMXE~97Xgxi#lSY!L%06>KmUsRVUl%D1g)&>6mg>oQ>e!F?NhHl-#WV4 zR%=I+8Q6~|o%?iVF|OA#WzMh$3IG~UKMg0HXW+m z?S8Jwc00hpt$EpG20qbyL4(9?ChMY;9U0yf1Z{HJGPee{+4eUxc!&( zMk64+`*UF+V4(BgYbSHOpFa5>w}|}LTjYi7Kc0N;ze~xfet4<<&Y1syVM1~e15F0n S&+ke~PMAA;6TG8+5C8!753Kb7 diff --git a/frontend/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/frontend/app/src/main/res/mipmap-xhdpi/ic_launcher.webp deleted file mode 100644 index 69330e2bead844670cbbbfc70bd4ee5e9a4a01c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3318 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 diff --git a/frontend/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp b/frontend/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp deleted file mode 100644 index b150f9d9780148c5c016458e1354375d2dcd20fb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5476 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 diff --git a/frontend/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/frontend/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp deleted file mode 100644 index d3acb5e3cd5b96fcd6c2856c4260f241de2b069a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5570 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 QCr|b~l3`{DqQfXf0iHn+Jpcdz diff --git a/frontend/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp b/frontend/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp deleted file mode 100644 index 743100b32318045687a805b4387478fc9bf3f12a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9672 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 I-X?Yt0A!Z?VE_OC diff --git a/frontend/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp b/frontend/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp deleted file mode 100644 index cecb8e63d69230193d32c47b1103719403fa98d1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12996 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 E2RL-7WdHyG diff --git a/frontend/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/frontend/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp deleted file mode 100644 index 2feeee7489d5465768d52b522963d1cc6064f268..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15106 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 - - #FF000000 - #FFFFFFFF - #FFAACAAC - \ No newline at end of file diff --git a/frontend/app/src/main/res/values/strings.xml b/frontend/app/src/main/res/values/strings.xml deleted file mode 100644 index d2a47da8..00000000 --- a/frontend/app/src/main/res/values/strings.xml +++ /dev/null @@ -1,53 +0,0 @@ - - SpeechBuddy - 게스트 모드로 시작하기 - 로그인하기 - 비밀번호를 잊으셨나요? - 회원가입 - SpeechBuddy에 오신 것을 환영합니다! - 로그인 - 로그인해 SpeechBuddy의 많은 기능을 사용해보세요 - 닉네임 - 등록되지 않은 이메일입니다 - 이메일 주소가 올바르지 않습니다 - 비밀번호가 올바르지 않습니다 - 닉네임이 올바르지 않습니다 - 이메일 - 비밀번호 - 회원가입하기 - 이메일 인증 - 이메일 인증을 진행해주세요 - 인증번호 - 인증번호가 잘못되었습니다 - 회원가입을 위해 이메일 인증을 진행해주세요 - 인증번호 발송 - 비밀번호 확인 - 다음 - 새 비밀번호 설정 - 이메일 인증을 통해 비밀번호를 재설정 할 수 있습니다 - 인증번호를 발송하였습니다 - 인증번호 - 다음 - 비밀번호를 잊으셨다면 새로운 비밀번호로 바꿔주세요 - 새 비밀번호 - 새 비밀번호 확인 - 8자 이상 입력해주세요 - 비밀번호가 일치하지 않습니다 - 상징으로 말하기 - 음성으로 말하기 - 새 상징 만들기 - 설정 - 다른 사용자가 이미 사용하고 있는 이메일입니다 - 해당 이메일로 가입된 계정이 없습니다 - 닉네임을 입력해주세요 - 로그인 오류 - 회원가입 오류 - 검색어를 입력하세요 - 즐겨찾기 - 상징 선택 취소 - 전체 삭제 - 소리로 말해보아요 - 키보드로 텍스트를 입력해주세요 - 재생하기 - 정지 - \ No newline at end of file diff --git a/frontend/app/src/main/res/values/themes.xml b/frontend/app/src/main/res/values/themes.xml deleted file mode 100644 index 7ee61f35..00000000 --- a/frontend/app/src/main/res/values/themes.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - -