Just take the 0

main
Alexis Drai 3 years ago
parent b4f6e61b77
commit b59fbc1a8b

@ -4,6 +4,7 @@ import android.app.Application
import androidx.room.Database import androidx.room.Database
import androidx.room.Room import androidx.room.Room
import androidx.room.RoomDatabase import androidx.room.RoomDatabase
import fr.uca.iut.urbandictionarylight.data.definition.DefinitionDao
import fr.uca.iut.urbandictionarylight.data.entry.EntryDao import fr.uca.iut.urbandictionarylight.data.entry.EntryDao
import fr.uca.iut.urbandictionarylight.model.Definition import fr.uca.iut.urbandictionarylight.model.Definition
import fr.uca.iut.urbandictionarylight.model.Entry import fr.uca.iut.urbandictionarylight.model.Entry
@ -14,7 +15,7 @@ private const val DB_FILE = "u_d_light.db"
abstract class UrbanDictionaryDatabase : RoomDatabase() { abstract class UrbanDictionaryDatabase : RoomDatabase() {
abstract fun entryDao(): EntryDao abstract fun entryDao(): EntryDao
abstract fun definitionDao(): fr.uca.iut.urbandictionarylight.data.definition.DefinitionDao abstract fun definitionDao(): DefinitionDao
companion object { companion object {
private lateinit var application: Application private lateinit var application: Application

@ -9,7 +9,7 @@ interface DefinitionDao {
@Query("SELECT * FROM definitions") @Query("SELECT * FROM definitions")
fun queryAll(): LiveData<List<Definition>> fun queryAll(): LiveData<List<Definition>>
@Query("SELECT * FROM entries WHERE id = :id") @Query("SELECT * FROM entries WHERE definitionId = :id")
fun query(id: Long): LiveData<Definition> fun query(id: Long): LiveData<Definition>
@Insert(onConflict = OnConflictStrategy.REPLACE) @Insert(onConflict = OnConflictStrategy.REPLACE)

@ -2,19 +2,35 @@ package fr.uca.iut.urbandictionarylight.data.entry
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.room.* import androidx.room.*
import fr.uca.iut.urbandictionarylight.model.Definition
import fr.uca.iut.urbandictionarylight.model.Entry
import fr.uca.iut.urbandictionarylight.model.EntryWithDefinitions import fr.uca.iut.urbandictionarylight.model.EntryWithDefinitions
@Dao @Dao
interface EntryDao { interface EntryDao {
@Transaction
@Query("SELECT * FROM entries") @Query("SELECT * FROM entries")
fun queryAll(): LiveData<List<EntryWithDefinitions>> fun queryAll(): LiveData<List<EntryWithDefinitions>>
@Query("SELECT * FROM entries WHERE id = :id") @Transaction
@Query("SELECT * FROM entries WHERE entryId = :id")
fun query(id: Long): LiveData<EntryWithDefinitions> fun query(id: Long): LiveData<EntryWithDefinitions>
@Insert(onConflict = OnConflictStrategy.REPLACE) @Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(entry: EntryWithDefinitions) suspend fun insert(entry: EntryWithDefinitions) {
val entryId: Long = insert(entry.entry)
for (def in entry.definitions) {
def.correspondingEntryId = entryId
insert(def)
}
}
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(entry: Entry): Long
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(entry: Definition)
@Update @Update
suspend fun update(entry: EntryWithDefinitions) suspend fun update(entry: EntryWithDefinitions)

@ -10,5 +10,6 @@ data class Definition(
val content: String, val content: String,
val example: String, val example: String,
var upvotes: Int = 0, var upvotes: Int = 0,
@PrimaryKey(autoGenerate = true) val id: Long = NEW_DEFINITION_ID var correspondingEntryId: Long,
@PrimaryKey(autoGenerate = true) val definitionId: Long = NEW_DEFINITION_ID
) )

@ -8,5 +8,5 @@ const val NEW_ENTRY_ID = 0L
@Entity(tableName = "entries") @Entity(tableName = "entries")
data class Entry( data class Entry(
val phrase: String = "", val phrase: String = "",
@PrimaryKey(autoGenerate = true) val id: Long = NEW_ENTRY_ID @PrimaryKey(autoGenerate = true) val entryId: Long = NEW_ENTRY_ID
) )

@ -1,12 +1,14 @@
package fr.uca.iut.urbandictionarylight.model package fr.uca.iut.urbandictionarylight.model
import androidx.room.Embedded import androidx.room.Embedded
import androidx.room.Entity
import androidx.room.Relation import androidx.room.Relation
data class EntryWithDefinitions( data class EntryWithDefinitions(
@Embedded val entry: Entry = Entry(), @Embedded val entry: Entry = Entry(),
@Relation( @Relation(
parentColumn = "id", parentColumn = "entryId",
entityColumn = "entryId" entityColumn = "correspondingEntryId"
) val definitions: List<Definition> = listOf() )
val definitions: List<Definition> = mutableListOf()
) )

@ -28,7 +28,7 @@ class EntryListFragment : Fragment(), EntryRecyclerViewAdapter.Callbacks {
val binding = FragmentListEntryBinding.inflate(inflater) val binding = FragmentListEntryBinding.inflate(inflater)
binding.entryListVM = entryListVM binding.entryListVM = entryListVM
binding.lifecycleOwner = viewLifecycleOwner binding.lifecycleOwner = viewLifecycleOwner
with(binding.recyclerView) { with(binding.entriesRecyclerView) {
adapter = entryListAdapter adapter = entryListAdapter
ItemTouchHelper(EntryListItemTouchHelper()).attachToRecyclerView(this) ItemTouchHelper(EntryListItemTouchHelper()).attachToRecyclerView(this)
} }

@ -13,12 +13,12 @@ class EntryPagerAdapter(fragmentActivity: FragmentActivity) :
override fun getItemCount() = entryList.size override fun getItemCount() = entryList.size
override fun createFragment(position: Int) = override fun createFragment(position: Int) =
EntryFragment.newInstance(entryList[position].entry.id) EntryFragment.newInstance(entryList[position].entry.entryId)
fun positionFromId(entryId: Long) = entryList.indexOfFirst { it.entry.id == entryId } fun positionFromId(entryId: Long) = entryList.indexOfFirst { it.entry.entryId == entryId }
fun entryIdAt(position: Int) = fun entryIdAt(position: Int) =
if (entryList.isEmpty()) NEW_ENTRY_ID else entryList[position].entry.id if (entryList.isEmpty()) NEW_ENTRY_ID else entryList[position].entry.entryId
fun submitList(entryList: List<EntryWithDefinitions>) { fun submitList(entryList: List<EntryWithDefinitions>) {
this.entryList = entryList this.entryList = entryList

@ -15,7 +15,7 @@ class EntryRecyclerViewAdapter(private val listener: Callbacks) :
private object DiffUtilEntryCallback : DiffUtil.ItemCallback<EntryWithDefinitions>() { private object DiffUtilEntryCallback : DiffUtil.ItemCallback<EntryWithDefinitions>() {
override fun areItemsTheSame(oldItem: EntryWithDefinitions, newItem: EntryWithDefinitions) = override fun areItemsTheSame(oldItem: EntryWithDefinitions, newItem: EntryWithDefinitions) =
oldItem.entry.id == newItem.entry.id oldItem.entry.entryId == newItem.entry.entryId
override fun areContentsTheSame( override fun areContentsTheSame(
oldItem: EntryWithDefinitions, oldItem: EntryWithDefinitions,
@ -40,7 +40,7 @@ class EntryRecyclerViewAdapter(private val listener: Callbacks) :
val entry: EntryWithDefinitions? get() = binding.entryWithDefinitions val entry: EntryWithDefinitions? get() = binding.entryWithDefinitions
init { init {
itemView.setOnClickListener { entry?.let { listener.onEntrySelected(it.entry.id) } } itemView.setOnClickListener { entry?.let { listener.onEntrySelected(it.entry.entryId) } }
} }
fun bind(entryWithDefinitions: EntryWithDefinitions) { fun bind(entryWithDefinitions: EntryWithDefinitions) {

@ -23,13 +23,13 @@ class EntryViewModel(entryId: Long) : ViewModel() {
false false
else { else {
viewModelScope.launch { viewModelScope.launch {
if (it.entry.id == NEW_ENTRY_ID) entryRepo.insert(it) else entryRepo.update(it) if (it.entry.entryId == NEW_ENTRY_ID) entryRepo.insert(it) else entryRepo.update(it)
} }
true true
} }
} }
fun deleteEntry() = viewModelScope.launch { fun deleteEntry() = viewModelScope.launch {
entry.value?.let { if (it.entry.id != NEW_ENTRY_ID) entryRepo.delete(it) } entry.value?.let { if (it.entry.entryId != NEW_ENTRY_ID) entryRepo.delete(it) }
} }
} }

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#000000"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M1,21h4L5,9L1,9v12zM23,10c0,-1.1 -0.9,-2 -2,-2h-6.31l0.95,-4.57 0.03,-0.32c0,-0.41 -0.17,-0.79 -0.44,-1.06L14.17,1 7.59,7.59C7.22,7.95 7,8.45 7,9v10c0,1.1 0.9,2 2,2h9c0.83,0 1.54,-0.5 1.84,-1.22l3.02,-7.05c0.09,-0.23 0.14,-0.47 0.14,-0.73v-2z"/>
</vector>

@ -22,119 +22,28 @@
android:padding="@dimen/activity_margin" android:padding="@dimen/activity_margin"
tools:context=".ui.activity.EntryActivity"> tools:context=".ui.activity.EntryActivity">
<androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="right"
app:constraint_referenced_ids="text_overview,text_gender,text_measurement,text_aggressiveness,text_misc" />
<TextView <TextView
android:id="@+id/text_overview" android:id="@+id/entry_text_view"
style="@style/CategoryStyle" android:layout_width="match_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/category_overview" android:textAppearance="?attr/textAppearanceHeadline3"
app:layout_constraintStart_toStartOf="parent" android:hint="@string/hint_entry_phrase"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/edit_dog_name"
style="@style/EditorFieldStyle"
android:layout_width="0dp"
android:hint="@string/hint_dog_name"
android:importantForAutofill="no" android:importantForAutofill="no"
android:inputType="textCapWords" android:text="@{entryVM.entry.entry.phrase}"
android:text="@={entryVM.dog.name}"
app:layout_constraintBaseline_toBaselineOf="@+id/text_overview"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/barrier" />
<EditText
android:id="@+id/edit_dog_breed"
style="@style/EditorFieldStyle"
android:layout_width="0dp"
android:hint="@string/hint_dog_breed"
android:importantForAutofill="no"
android:inputType="textCapWords"
android:text="@={entryVM.dog.breed}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/barrier"
app:layout_constraintTop_toBottomOf="@+id/edit_dog_name" />
<TextView
android:id="@+id/text_gender"
style="@style/CategoryStyle"
android:layout_width="wrap_content"
android:text="@string/category_gender"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/edit_dog_breed" />
<Spinner
android:id="@+id/spinner_gender"
android:layout_width="wrap_content"
android:layout_height="@dimen/large_space"
android:entries="@array/array_gender_options"
android:selectedItemPosition="@={Converters.genderToInt(dogVM.dog.gender)}"
android:spinnerMode="dropdown"
app:layout_constraintStart_toEndOf="@id/barrier"
app:layout_constraintTop_toTopOf="@+id/text_gender" />
<TextView
android:id="@+id/text_measurement"
style="@style/CategoryStyle"
android:layout_width="wrap_content"
android:text="@string/category_measurement"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/spinner_gender" /> app:layout_constraintTop_toTopOf="parent"
tools:text="Phrase goes here" />
<EditText
android:id="@+id/edit_dog_weight"
style="@style/EditorFieldStyle"
android:layout_width="0dp"
android:hint="@string/hint_dog_weight"
android:importantForAutofill="no"
android:inputType="numberDecimal"
android:text="@={Converters.floatToString(dogVM.dog.weight)}"
app:layout_constraintBaseline_toBaselineOf="@+id/text_measurement"
app:layout_constraintEnd_toStartOf="@id/label_weight_unit"
app:layout_constraintStart_toEndOf="@id/barrier" />
<TextView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/label_weight_unit" android:id="@+id/definitions_recycler_view"
style="@style/EditorUnitsStyle" android:layout_width="match_parent"
android:layout_width="wrap_content" android:layout_height="match_parent"
android:text="@string/unit_dog_weight" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBaseline_toBaselineOf="@+id/text_measurement" app:layout_constraintTop_toBottomOf="@id/entry_text_view"
app:layout_constraintEnd_toEndOf="parent" tools:listitem="@layout/item_list_definition" />
app:layout_constraintStart_toEndOf="@id/edit_dog_weight" />
<TextView
android:id="@+id/text_aggressiveness"
style="@style/CategoryStyle"
android:layout_width="wrap_content"
android:text="@string/category_aggressiveness"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/edit_dog_weight" />
<RatingBar
android:id="@+id/ratingbar_aggressiveness"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:numStars="3"
android:rating="@={(float) dogVM.dog.aggressiveness}"
android:stepSize="1"
app:layout_constraintStart_toEndOf="@id/barrier"
app:layout_constraintTop_toTopOf="@+id/text_aggressiveness" />
<TextView
android:id="@+id/text_misc"
style="@style/CategoryStyle"
android:layout_width="wrap_content"
android:layout_marginTop="@dimen/large_space"
android:text="@string/category_misc"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/ratingbar_aggressiveness" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView> </ScrollView>

@ -30,7 +30,7 @@
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view" android:id="@+id/entries_recycler_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager" app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"

@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="definition"
type="fr.uca.iut.urbandictionarylight.model.Definition" />
</data>
<androidx.cardview.widget.CardView
android:id="@+id/cardview_definition"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="2dp"
card_view:cardUseCompatPadding="true">
<LinearLayout
android:id="@+id/layout_cardview_definition"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="@dimen/activity_margin">
<TextView
android:id="@+id/view_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-medium"
android:text="@{definition.content}"
android:textAppearance="?android:textAppearanceMedium"
android:textColor="@color/black"
tools:text="Definition content" />
<TextView
android:id="@+id/view_example"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-medium"
android:text="@{definition.example}"
android:textAppearance="?android:textAppearanceMedium"
android:textColor="@color/black"
tools:text="Definition example" />
<TextView
android:id="@+id/view_upvotes"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-medium"
android:text="@{ + definition.upvotes}"
android:textAppearance="?android:textAppearanceSmall"
android:textColor="@color/black"
card_view:drawableLeftCompat="@drawable/ic_thumb_up"
tools:text=" + Definition upvotes" />
</LinearLayout>
</androidx.cardview.widget.CardView>
</layout>

@ -24,7 +24,7 @@
android:padding="@dimen/activity_margin"> android:padding="@dimen/activity_margin">
<TextView <TextView
android:id="@+id/view_name" android:id="@+id/view_phrase"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:fontFamily="sans-serif-medium" android:fontFamily="sans-serif-medium"

@ -11,4 +11,5 @@
<dimen name="medium_space">16dp</dimen> <dimen name="medium_space">16dp</dimen>
<dimen name="small_space">8dp</dimen> <dimen name="small_space">8dp</dimen>
<dimen name="icon_title_space">24dp</dimen> <dimen name="icon_title_space">24dp</dimen>
<dimen name="small_icon">24dp</dimen>
</resources> </resources>

@ -9,4 +9,5 @@
<string name="delete_lbl">Delete</string> <string name="delete_lbl">Delete</string>
<string name="create_entry_error_dialog_title" translatable="false">That\'s a woopsie</string> <string name="create_entry_error_dialog_title" translatable="false">That\'s a woopsie</string>
<string name="create_entry_error_message" translatable="false">sorry bud, no can do</string> <string name="create_entry_error_message" translatable="false">sorry bud, no can do</string>
<string name="hint_entry_phrase">Phrase, term or entry</string>
</resources> </resources>
Loading…
Cancel
Save