From 3c07c4786edeee2d7e4579cd6d59c119f1695777 Mon Sep 17 00:00:00 2001 From: Sangjin Kim Date: Fri, 18 Jul 2025 01:01:52 +0900 Subject: [PATCH 1/3] =?UTF-8?q?12=EC=A3=BC=EC=B0=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/.name | 1 + .idea/AndroidProjectSystem.xml | 6 ++ .idea/compiler.xml | 6 ++ .idea/deploymentTargetSelector.xml | 10 +++ .idea/gradle.xml | 19 ++++ .idea/kotlinc.xml | 6 ++ .idea/migrations.xml | 10 +++ .idea/misc.xml | 7 ++ .idea/runConfigurations.xml | 17 ++++ .idea/vcs.xml | 6 ++ app/build.gradle.kts | 14 +++ app/src/main/AndroidManifest.xml | 3 + .../bcsd_android_2025_1/AddEditActivity.kt | 52 +++++++++++ .../bcsd_android_2025_1/MainActivity.kt | 72 ++++++++++++++- .../bcsd_android_2025_1/WordAdapter.kt | 35 ++++++++ .../example/bcsd_android_2025_1/WordDao.kt | 20 +++++ .../bcsd_android_2025_1/WordDatabase.kt | 26 ++++++ .../bcsd_android_2025_1/WordListData.kt | 12 +++ .../bcsd_android_2025_1/WordRepository.kt | 11 +++ .../bcsd_android_2025_1/WordViewModel.kt | 24 +++++ app/src/main/res/drawable/delete_icon.png | Bin 0 -> 7553 bytes app/src/main/res/drawable/edit_icon.png | Bin 0 -> 6206 bytes app/src/main/res/layout/activity_add_edit.xml | 50 +++++++++++ app/src/main/res/layout/activity_main.xml | 83 ++++++++++++++---- app/src/main/res/layout/item_word.xml | 34 +++++++ app/src/main/res/values/strings.xml | 4 + gradle/libs.versions.toml | 11 +++ settings.gradle.kts | 1 + 28 files changed, 521 insertions(+), 19 deletions(-) create mode 100644 .idea/.name create mode 100644 .idea/AndroidProjectSystem.xml create mode 100644 .idea/compiler.xml create mode 100644 .idea/deploymentTargetSelector.xml create mode 100644 .idea/gradle.xml create mode 100644 .idea/kotlinc.xml create mode 100644 .idea/migrations.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/runConfigurations.xml create mode 100644 .idea/vcs.xml create mode 100644 app/src/main/java/com/example/bcsd_android_2025_1/AddEditActivity.kt create mode 100644 app/src/main/java/com/example/bcsd_android_2025_1/WordAdapter.kt create mode 100644 app/src/main/java/com/example/bcsd_android_2025_1/WordDao.kt create mode 100644 app/src/main/java/com/example/bcsd_android_2025_1/WordDatabase.kt create mode 100644 app/src/main/java/com/example/bcsd_android_2025_1/WordListData.kt create mode 100644 app/src/main/java/com/example/bcsd_android_2025_1/WordRepository.kt create mode 100644 app/src/main/java/com/example/bcsd_android_2025_1/WordViewModel.kt create mode 100644 app/src/main/res/drawable/delete_icon.png create mode 100644 app/src/main/res/drawable/edit_icon.png create mode 100644 app/src/main/res/layout/activity_add_edit.xml create mode 100644 app/src/main/res/layout/item_word.xml diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..c4e4683 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +BCSD_Android_2025-1 \ No newline at end of file diff --git a/.idea/AndroidProjectSystem.xml b/.idea/AndroidProjectSystem.xml new file mode 100644 index 0000000..4a53bee --- /dev/null +++ b/.idea/AndroidProjectSystem.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..b86273d --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml new file mode 100644 index 0000000..b268ef3 --- /dev/null +++ b/.idea/deploymentTargetSelector.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..639c779 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,19 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml new file mode 100644 index 0000000..c224ad5 --- /dev/null +++ b/.idea/kotlinc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/migrations.xml b/.idea/migrations.xml new file mode 100644 index 0000000..f8051a6 --- /dev/null +++ b/.idea/migrations.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..02a7102 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 0000000..16660f1 --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,17 @@ + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 5791375..7272f8a 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,6 +1,7 @@ plugins { alias(libs.plugins.android.application) alias(libs.plugins.kotlin.android) + id("kotlin-kapt") } android { @@ -17,6 +18,14 @@ android { testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } + buildFeatures { + dataBinding = true + } + + kapt { + correctErrorTypes = true + } + buildTypes { release { isMinifyEnabled = false @@ -42,6 +51,11 @@ dependencies { implementation(libs.material) implementation(libs.androidx.activity) implementation(libs.androidx.constraintlayout) + implementation(libs.androidx.lifecycle.viewmodel.ktx) + implementation(libs.kotlinx.coroutines.android) + implementation(libs.androidx.room.runtime) + implementation(libs.androidx.room.ktx) + kapt(libs.androidx.room.compiler) testImplementation(libs.junit) androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.espresso.core) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 4c80941..1819965 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -12,6 +12,9 @@ android:supportsRtl="true" android:theme="@style/Theme.BCSD_Android_20251" tools:targetApi="31"> + diff --git a/app/src/main/java/com/example/bcsd_android_2025_1/AddEditActivity.kt b/app/src/main/java/com/example/bcsd_android_2025_1/AddEditActivity.kt new file mode 100644 index 0000000..e205f6b --- /dev/null +++ b/app/src/main/java/com/example/bcsd_android_2025_1/AddEditActivity.kt @@ -0,0 +1,52 @@ +package com.example.bcsd_android_2025_1 + +import android.app.Activity +import android.content.Intent +import android.os.Bundle +import androidx.activity.viewModels +import androidx.appcompat.app.AppCompatActivity +import com.example.bcsd_android_2025_1.databinding.ActivityAddEditBinding + + +class AddEditActivity : AppCompatActivity(){ + private lateinit var binding: ActivityAddEditBinding + private val viewModel:WordViewModel by viewModels() + + private var wordId: Int?= null + + override fun onCreate(savedInstanceState: Bundle?) { + + super.onCreate(savedInstanceState) + binding = ActivityAddEditBinding.inflate(layoutInflater) + setContentView(binding.root) + + val editWordText = intent.getStringExtra("word_text") + val editMeaning = intent.getStringExtra("word_meaning") + wordId = intent.getIntExtra("word_id", -1).takeIf { it != -1 } + + binding.wordEdittext.setText(editWordText) + binding.meaningEdittext.setText(editMeaning) + + binding.addButton.setOnClickListener { + val wordText = binding.wordEdittext.text.toString() + val meaning = binding.meaningEdittext.text.toString() + if (wordText.isNotBlank() && meaning.isNotBlank()) { + val word = WordListData(wordId ?: 0, wordText, meaning) + if (wordId != null) { + viewModel.update(word) + binding.wordEdittext.setText("") + binding.meaningEdittext.setText("") + val resultIntent = Intent() + resultIntent.putExtra("edited_word", word.word) + resultIntent.putExtra("edited_meaning", word.meaning) + setResult(Activity.RESULT_OK, resultIntent) + finish() + + } else { + viewModel.insert(word) + } + finish() + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/bcsd_android_2025_1/MainActivity.kt b/app/src/main/java/com/example/bcsd_android_2025_1/MainActivity.kt index 3ffa0eb..51ef211 100644 --- a/app/src/main/java/com/example/bcsd_android_2025_1/MainActivity.kt +++ b/app/src/main/java/com/example/bcsd_android_2025_1/MainActivity.kt @@ -1,14 +1,78 @@ package com.example.bcsd_android_2025_1 +import android.app.Activity +import android.content.Intent import android.os.Bundle -import androidx.activity.enableEdgeToEdge +import androidx.activity.result.ActivityResultLauncher +import androidx.activity.result.contract.ActivityResultContracts +import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity -import androidx.core.view.ViewCompat -import androidx.core.view.WindowInsetsCompat +import androidx.recyclerview.widget.LinearLayoutManager +import com.example.bcsd_android_2025_1.databinding.ActivityMainBinding + class MainActivity : AppCompatActivity() { + + private lateinit var binding: ActivityMainBinding + private val viewModel: WordViewModel by viewModels() + private lateinit var editActivityLauncher: ActivityResultLauncher + + + private val adapter by lazy { + WordAdapter(onTopClick = { viewModel.setTopWord(it) }) + } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.activity_main) + binding = ActivityMainBinding.inflate(layoutInflater) + setContentView(binding.root) + + editActivityLauncher = + registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> + if (result.resultCode == Activity.RESULT_OK) { + val data = result.data + val editedWord = data?.getStringExtra("edited_word") ?: "" + val editedMeaning = data?.getStringExtra("edited_meaning") ?: "" + + // 상단 TextView 업데이트 + binding.wordTextview.text = editedWord + binding.meaningTextview.text = editedMeaning + } + } + + binding.recyclerView.adapter = adapter + binding.recyclerView.layoutManager = LinearLayoutManager(this) + + binding.editButton.setOnClickListener { + viewModel.topWord.value?.let { + val intent = Intent(this, AddEditActivity::class.java).apply { + putExtra("word_id", it.id) + putExtra("word_text", it.word) + putExtra("word_meaning", it.meaning) + } + editActivityLauncher.launch(intent) + } + } + + binding.deleteButton.setOnClickListener { + viewModel.topWord.value?.let { + viewModel.delete(it) + binding.wordTextview.text = "" + binding.meaningTextview.text = "" + } + } + + viewModel.allWords.observe(this) { + adapter.submitList(it) + } + + viewModel.topWord.observe(this) { + binding.wordTextview.text = it?.word ?: "단어 선택 필요" + binding.meaningTextview.text = it?.meaning ?: "" + } + + binding.floatingButton.setOnClickListener { + startActivity(Intent(this, AddEditActivity::class.java)) + } } } \ No newline at end of file diff --git a/app/src/main/java/com/example/bcsd_android_2025_1/WordAdapter.kt b/app/src/main/java/com/example/bcsd_android_2025_1/WordAdapter.kt new file mode 100644 index 0000000..3b83e9b --- /dev/null +++ b/app/src/main/java/com/example/bcsd_android_2025_1/WordAdapter.kt @@ -0,0 +1,35 @@ +package com.example.bcsd_android_2025_1 + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter +import androidx.recyclerview.widget.RecyclerView +import com.example.bcsd_android_2025_1.databinding.ItemWordBinding + +class WordAdapter ( + private val onTopClick: (WordListData) ->Unit +) : ListAdapter(DiffCallback()){ + + inner class WordViewHolder(private val binding: ItemWordBinding): RecyclerView.ViewHolder(binding.root) { + fun bind(word: WordListData) { + binding.word = word + binding.root.setOnClickListener { onTopClick(word) } + binding.executePendingBindings() + } + } + + override fun onCreateViewHolder(parent:ViewGroup, viewType: Int):WordViewHolder{ + val binding = ItemWordBinding.inflate(LayoutInflater.from(parent.context), parent, false) + return WordViewHolder(binding) + } + + override fun onBindViewHolder(holder: WordViewHolder, position:Int){ + holder.bind(getItem(position)) + } + + class DiffCallback: DiffUtil.ItemCallback(){ + override fun areItemsTheSame(oldItem:WordListData, newItem:WordListData):Boolean = oldItem.id ==newItem.id + override fun areContentsTheSame(oldItem: WordListData, newItem: WordListData): Boolean = oldItem == newItem + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/bcsd_android_2025_1/WordDao.kt b/app/src/main/java/com/example/bcsd_android_2025_1/WordDao.kt new file mode 100644 index 0000000..27eb462 --- /dev/null +++ b/app/src/main/java/com/example/bcsd_android_2025_1/WordDao.kt @@ -0,0 +1,20 @@ +package com.example.bcsd_android_2025_1 + +import androidx.lifecycle.LiveData +import androidx.room.* + +@Dao +interface WordDao { + @Query("SELECT * FROM word_table ORDER BY id DESC") + fun getAllwords(): LiveData> + + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun insert(word: WordListData) + + @Update + suspend fun update(word: WordListData) + + @Delete + suspend fun delete(wordListData: WordListData) + +} \ No newline at end of file diff --git a/app/src/main/java/com/example/bcsd_android_2025_1/WordDatabase.kt b/app/src/main/java/com/example/bcsd_android_2025_1/WordDatabase.kt new file mode 100644 index 0000000..17839db --- /dev/null +++ b/app/src/main/java/com/example/bcsd_android_2025_1/WordDatabase.kt @@ -0,0 +1,26 @@ +package com.example.bcsd_android_2025_1 + +import android.content.Context +import androidx.room.Room +import androidx.room.Database +import androidx.room.RoomDatabase + +@Database(entities = [WordListData::class], version = 1, exportSchema = false) +abstract class WordDatabase : RoomDatabase() { + abstract fun wordDao(): WordDao + + companion object{ + @Volatile private var INSTANCE: WordDatabase?=null + + fun getDatabase(context: Context): WordDatabase{ + return INSTANCE ?: synchronized(this){ + val instance = Room.databaseBuilder( + context.applicationContext, WordDatabase::class.java, + "word_database" + ).build() + INSTANCE = instance + instance + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/bcsd_android_2025_1/WordListData.kt b/app/src/main/java/com/example/bcsd_android_2025_1/WordListData.kt new file mode 100644 index 0000000..76faa77 --- /dev/null +++ b/app/src/main/java/com/example/bcsd_android_2025_1/WordListData.kt @@ -0,0 +1,12 @@ +package com.example.bcsd_android_2025_1 + +import androidx.room.PrimaryKey +import androidx.room.Entity + +@Entity(tableName = "word_table") +data class WordListData ( + @PrimaryKey(autoGenerate = true) + val id: Int = 0, + var word: String, + var meaning: String +) \ No newline at end of file diff --git a/app/src/main/java/com/example/bcsd_android_2025_1/WordRepository.kt b/app/src/main/java/com/example/bcsd_android_2025_1/WordRepository.kt new file mode 100644 index 0000000..6235632 --- /dev/null +++ b/app/src/main/java/com/example/bcsd_android_2025_1/WordRepository.kt @@ -0,0 +1,11 @@ +package com.example.bcsd_android_2025_1 + +import androidx.lifecycle.LiveData + +class WordRepository(private val wordDao: WordDao) { + val allWords: LiveData> = wordDao.getAllwords() + + suspend fun insert(word: WordListData) = wordDao.insert(word) + suspend fun update(word: WordListData) = wordDao.update(word) + suspend fun delete(word: WordListData) = wordDao.delete(word) +} \ No newline at end of file diff --git a/app/src/main/java/com/example/bcsd_android_2025_1/WordViewModel.kt b/app/src/main/java/com/example/bcsd_android_2025_1/WordViewModel.kt new file mode 100644 index 0000000..18d445c --- /dev/null +++ b/app/src/main/java/com/example/bcsd_android_2025_1/WordViewModel.kt @@ -0,0 +1,24 @@ +package com.example.bcsd_android_2025_1 + +import android.app.Application +import androidx.lifecycle.* +import kotlinx.coroutines.launch + + +class WordViewModel(application: Application) : AndroidViewModel(application) { + private val repository: WordRepository + val allWords: LiveData> + private val _topWord = MutableLiveData() + val topWord: LiveData get() = _topWord + + init { + val wordDao = WordDatabase.getDatabase(application).wordDao() + repository = WordRepository(wordDao) + allWords = repository.allWords + } + + fun insert(word:WordListData) = viewModelScope.launch { repository.insert(word)} + fun update(word:WordListData) = viewModelScope.launch { repository.update(word)} + fun delete(word:WordListData) = viewModelScope.launch { repository.delete(word)} + fun setTopWord(word: WordListData) {_topWord.value = word} +} \ No newline at end of file diff --git a/app/src/main/res/drawable/delete_icon.png b/app/src/main/res/drawable/delete_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..6f673769b460be906d0f422b96784ed876e8fa29 GIT binary patch literal 7553 zcmcI}dpK3w*Z*AGmTMwkmk!cp+0MzeRFbeyC00bG&}FkFIljvM(so^)ipsU6+-=SY zC32}#qOf(Lom?WJTq--c3p;E!-bqLA^ZP#Md4GSr&%2+;W34ehW6n9o9CM5@$GW`V z!eqJVPoe;T<(TR2g8-1=BMAsEga5c^-%P`QA|9qkyaAASy6}foyWctqiK~2!ZGEiV zPx<&ecsT)oe}7FEH&<^*2M;GrcQ5CZ;T=B#pd^9q{`Jt=)S(X71~=y;%3tT}TvXc- zfv_HGopF*x=0)KvA})S8LY$0?@2>1R+$)slJNV{+=h1B6qt4rJOi)+d)Um#EW5`GH z^wl-3(N=ZWML)0EdN2cByM|p?r`Kjel+8E{O$|Q{Jj--e%D?}1e5N*!Egp0>Ke%Et z@XmZ-*W^*l1$F+XU#gppFH#uQfw}D+Ya!YR&Rw*A?^x7z<4W1prgx3l2AE+oXBIPz z=a@PjD3n3)jisB}F)F-KG~r(@q%(t-W6A{Iiztw7A!#4|LgC%SBvkc=y=r^6r*br~ zI+4f=GN9^{mI|*Pv)fM-=JqyWA=>OOxnc+$>Z~U*ncdbEUJ|Iy&TULxfo~##W;bkX z2Aen}M-m87XV=8>9emg3X(9OD1Qp&Pq9#}D9BGDVPvp2ZUo2$S-PXkK`}z@Gms5-e z1{zWK7(;U@>6i`fre5B@Qu_zvQKLgN@&H>F$Y`2+i%#F}-$^IWsk3!e^=xUv1J6Z) zObF^W_w|~yDkIoeDo+`~MGJB@!JeuS^7(s$tOiZX@x6yWN^jkf#CeHMTFX6|Zn&`O zU5#UBWnZ1e_#@=}>r1QN-DwtNnesa5`yT-LcQhSnu)ess6fC|CdOn%pM{CPFLnN(85WM%4z$J_AnR$9tfA9;T?T}CoN4Df9B8Q;5fhLE z@=rSZN%RwNIu>69h*vTx>eVCSWzzo-Lyv6Qm2WZjxqlt~_xz|XrGS%yczIb~DM-9k z)-0&)P6EOA5=3%GAMGk2gXsrw)qgYUK!fVcd_&#+QT^SPd4Ipa2@~N~8MZyW;K!GE zt#Ax*KM$hz`@D|$uGMy!L`ycX3!1Rw}C2DIU>bK{IfA;n98{bmw$#y zq92w+d0()Q^>aU+`-4VsMksA*oE3394jhxP;z+Kk39wGC8kfeHwBus2?Fp1i6&e!4 zcgYAobe!l33pFMZvUz?L38-Gd-Jj`JCIr7=voqO{=m{hbn~hPO4n(%RA+dBR4C7?? z7o}_2zAhH&Bl+s0_5Z*%JecL?3T88H^ey;tauj`KH zNgc;v@vq96CA^ufdLX<1cho4BLr<>WV&W8ud{AxNQMak5Sp?WV%SXGCIHQ}j_9;Xa zb)2+MIn{OYv@b$csBTJiR;X>+9@Doc(3dcZHV6eheSe^#dh7M%w`Grz&bqeqk;DRL zl-JU1yu(Rd4Rj@QVs1wO90_vW^OcDg<$=c~r2xpks6QkZ8|f(cA<3nj^<*Fju@y3D z3aZ}QH@P{|LGZ(M&v7AoaB2eQQEr6%F7WXFf=nxPzA8!Jc1sh0WfT0xmwf0`V3}XA zFXAW+EDIJn%bNuwKmLMuHwyylxyHb+^40+0=R^P~3?l1uU;cj%Ymg_guJ)4vogRK$4C;0^b5XY&aM5c)`(YXY;)BtPy3H+eYd?xP#YG@(3Zx^?TC23AlQmcCLzJJvsIswW+q zcMaxdK31W_41mW^%fh=}ZA+L8j>0HAe~?B7+`*w$m9<8zTI}0xD7@2zGdzyK;H)-# zxl3Kyb%h#HDiO4Wtq`YJ04Lh+r_NT`M5KfgsWckP#W0;ShZfvgU~sLlkb9+<;-WMF z%2sVuj|=jzx^Iktn(a)Ea~wanf2W0RkHX-j3NLD#G+=EuNIcaRdM&0jrca#J*O}H+ z_)H%r3tUCf()-wYs;k1V zBV6N-Upr~(un&0qtYLR!!+X5~iTNbX3L+@0FdLHw@%|P>iweVvICjMqv30JF3qsiy zmSgWR<}D59qh$Q^V@-CwD#OBeElB+ofprp`wC0QE7eQfS4Z;66VRKlH#CqUnc5mmS zg3{O`Y2Y{U37y}~k&A7N=Nx9Jp#HDQ;`3C5V#@W`9##d4Z4!~L`uwj$tI z-~nPq)#VU8XL~H?t*uDwHBeYm6Bo3OeGeKq<9b1M+sm?IIJRDHDSmbO+e4nftIF$G z$eq$l8&`rl?ljtE1>GWz;gnqcQ17w^Zk3k6@y7Du_Tv^E*EuCvv~0`9pR9q!H~&vP zE3{2uh^g#fSG5~#YfiZ>1~PPwj?!3(t)x~D8lex5eTGeoY6*0WjfJGb%1R@gHv^rw zYA0y@It1Oh;ZedNIc-@IE9}c*IY1qO2b-==#+TdJEWG94hHr|b(}R1*PxtCU8#LtJ z!2E3FHZHRUTjj-YUekc3wq#T{CSfgyP)E4a(ol58;y|l&z7JHsVI_TT`0p2rAdBDk zO;s2u5{=5{$O!#BhG>Td%!-g$%i>7%x$mP%ge?Jo-9TOhb_o`K zs>z{x$7#>xZIM=(!Jal7gNBswPd)Qr$hcLT0?d*Ib0~?GGq@aim9RQ=CGz1A zMTiyDH>xTHESwm^^m6W0oG`fg&IX?Nve(^~>p<$uG0A^G5E4j_S&Y$T;ISc2U{UO> z%-0;hEQZ+|#)4ULZn)U-LLS3yEhKr|hJKl=Ny6)fB2wmmA>%qn){zpG%Vsx|SV`t9 zao+3qmg_+(+i@KjzfqjN2W*SGCai4~FyjKDN$3wEM*0Wh`R_tiDWKjbgxIy9agG=q z<%uXONkWy8St<;+k9)N9>(_wOb#_v$px(X|NwC$qK$vdG5+a|Ha4MAbb%gj}Q+g`oaDb$iG6u)G)DT9p{I@XCYw7m*4}9I*)-=nt+lpL!~O zLFld%ks#Yrs|#-SmcTur>1Klaub?#<6VMJ0;K`ElJ4d#X5)I3O#7L~S6ARAc`kjnL z{lEsV$NQRUilI`qnaCoxll<_$Se)W5XlLsQ6xNx~$}&3rmS%HU7(f871pK&Ol^hGq#ZwqY=M6u3ZOsu ze+xYpJsaq(qDOF2`*#A{m(rM@s-88B0&pRnMd(a!1faW2KCcZuMq<^euSLvbI?DtQ zy0gSpu=IEkWpR5u^d*7csg*zY6sdn8N)Z1k^p(O&8^XrU!epcV`A<~nc7(i+8qn95 zL;!v7YUp~=Wc+!n87Wc1AP_0%oZ2`^;br%)d)w}ab*3y_HsUz>=!*2Ic})v18X<== zju1B4N9G*QkGfV*?W-w=Rc4GosyDo$WEdNpY)XA@`-X`cF)0rZx7Y`-GU_glZqfJS z|5EvTXZ*BCnOn<8)F{C(6r)|^q-XK=e(4X58BKZX#Lo^cJ9935g*r$1X2{Nhru#34I^u3Vd%-SYU>+?AC{nIDn2&kQ2+svqxwj{brc{5c zdLE))cy9!Qm~hunVnB|cl=mrlbNKn&^J!J?sSs2DZA>tf;#%v7M~v>tnF}^xPpX#O zsIH&#B3iQB;?fklTcSr(rW1Rk)3n-YchWIyi%2WG8~}Am-oadYD>>y zR)n7ZzJD7%DveDF=r<7CRp#mGPt<2I`~oE+?e(kN?U?2|RSS8*?*Wh-6aO zstMm3SYtlH(_3^GXG)m$9JjwDgFg@6UYkN3wcq;w4aqedQOw+Nt}F{GMu8Tn+{5bqQwN?pfFAHrmFJA^8g4 z>)b`EDAmZ&YN{>t_|y_Z3dlmZ1?a6#yO`ebMW<`mcYz|o!ZirplSDOIt-&8O5jA?G zR#l+XtqZRSO9HQ-)H9zdw0&O~w_i{MM8s`Csw@laVnN}yoRxI`cVeJ=?Y&1JvgzEL z$1M&7Osb~wpxcQT3M03dxh6i^cq3sAP_GsRth0Tu%_Kp*qZbmHu(}M!cs+{TKM*An z!4khwa8_f3F3tY5EQ>XMuQiE3!n4TfRix*!BbY-$c(3dHW&Ki?g z{eybQo2CdG6cRH9ZrzkCFa@@0PO5l7z~~h+-aNEW$(Nly43X;kKah8Sh-X?XA(MQ- zH|{5y!xhWC`z6ql!qQ8ZbD8I@LS=FnqsRL{dMnlLks6|#ZUW!Ic^J6=a_keyh+f_P zJ7|bz3+*>q;r1)|t$IwFs$}p`5Xn$-2B5#UQbQOFnWh6@?gv>i?l)+Jym@{8m?U_& zk+;OP4I$mSAymA7RyHq3Uzhz+_~4mC^_4jlmlsb<_P|-911q7Q?;rij+L!SRm&>OAt3qIF(Ur7p-Ivyl(EenP&fd-|REU@&L^RJB1 zfHNj!d^qtMm~C>^Uk7}uGs(T_cJHN-41J0Ub)Ne!8fxLGEx3d<&00hroc-yQUfXrf zexd`;ZvIU%bvoBJY9V|cjYdn>RNaxb2BqFR*ya7}z^Oslr|{ncdgHU;f_jUTR)W&c z9-`DxZmWa{=pZbR=^NF4rjXATX;3zJu!}@3Hn&(pI(d<}CNV>?pg}|E5LiO`ls+C8 zH42o_Ij`GfiL3#Rq4of}C64F+*OdRl7y!3w*j5Zu>r zOrHWJP+DCsas1HNl0f3|;}71CPVwJu3~6%kz3)h(PQs`;h>fimOrLq0DzqsFfGDs)j-ERQsHB>IQ|3Cz%RKiA0`zG9T6z=vd%APxFDBLanh?shUiIeo*ErRm4yeIupvNmX=<=xZ zuknYbJ&zIa7P3)Chl><(FvLX0o{p)(FBJk;t7iB=lYpcLDfcx~MU~e?@odA-dOi`oybKk5M z2D92nkkT7BC*TN~h zIN@C%!NTnZf0>Y|73Ow$bKf5ZE5Y>VQJJMjl`>ME#fqV;pg}7fAl5g-C*V;^_^h_X zcjAfCeFJ`rA>$!Qk3nwJu0YN{e71BA8(u5{rT@voWh+rl4a{!8#<{vc>izhTH@O$| zrmLvqpZn4bq`|cFN&$7tk-;R;U=&jXmL7kRr85GY>&f_B(lb!gq#sBD+zE>7);m^k35gXgB4HUetFOlXh<>q_BWX)nqAK65iIM5akJOUz`bcEIb@uw%3*`_k}0793KzXxP*I!jQ2d=)Hf z0cH1hY|VdTy<}ORxUUdl@HF-mvVdi!fN)O-LIB>d%%3q)q1=c>eKqiOTOy}u!2%y% zKjf|03FM;(>jF|B%+XSe?i}!$O2$7Xz5)78YC`LPc=cUbRvq`{IXLj>DYYf& z`exFgd4b|3pshG_^anI^S!zm9qgCVGnuA$_1Vw| z-ky`eKPsBtttb`7r5?dz=RBO<$z6=@8o511y+Kv&$!qUl5kr@zJLa}ugdO*28euPj7c1l zE7HsZ;saDNz-xEN>dyZPN4-}q=s~HO7mx;F{?0JJt>ApxAkj7>pGcr!}CX9ZPp@hFDRA7Png6VXL2f`S)yd{pH@(K z$_vu0(1?^!5hSDTeXbagN6HE>Y2e!}EyuTg;KBR)zw{D0jZ?&5E3HBQj%1F}VL4=f zZ}F!d`zlfD9r$^rN%#b7T93(LV1_od7o}d^Ip28b2)xs0u+DgnYpH-YGf+<;%CCXi zrh)wA5I+RX5p1tD!Ek{bo&?+F{%tdh}P(cjPkm&bA zF6CMu+;`gwWOuVschj-=&wUG*BXmAf6e+kY2_n0!bVKd^4ZTRL&FxIiJcZ#)c*E{n z>&rhjkLWPqVh3MYfu^x1=ty+2AgSBiGI{7_4E&~Wf{gc-tYeQ*7@ly6szH?6IJ1Rs z4WCXU=Jk%)oFf6hN&IWA#4T7Q6i|5Yv0<(Jiz+1y^Y{C(5FNJnZ879+T|$%M#0>q+ zs=Sw?tiOU)_JM6i?BZwj(!E`;QTKgg0$BO}<6;`NNMg(vlqZLk8-?UkjY728M&@H# z{X2iFk2(?JW&xX=1y?4QfgvR`uVaM0`M9yus|!HezAKfZ8prn_#3Edg>@QTJYwwsl z5mfY0Hed~S)g_3PuV+J&?s{=>OrL;F$j3VDM~yptpP7q*fzO{78u;;OF@+IwTAH<8 zKb~Vr1pUl5X>8{!|8nP2r7##6S_ON<-uTxP3;yIw>G_$9*aXTrdc>D{EGFy7OQS?i wB^nxkN^gEXZEEBuvE#V4(*LKM%6h>MJ=E&6Kla(B-xi>lvBmEEo%G-T3*}IO^Z)<= literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/edit_icon.png b/app/src/main/res/drawable/edit_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..bb9a087c6138c574d0cd3feb05cc580f321f6788 GIT binary patch literal 6206 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 + + + + + + + + +