coming up: adapting the layouts and VM, plugging in the API, maybe set up notificationsmain
parent
e064615a9d
commit
b4f6e61b77
@ -1,17 +0,0 @@
|
|||||||
package fr.uca.iut.urbandictionarylight
|
|
||||||
|
|
||||||
import android.os.Bundle
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
|
||||||
import fr.uca.iut.urbandictionarylight.data.UrbanDictionaryDatabase
|
|
||||||
import fr.uca.iut.urbandictionarylight.databinding.ActivityMainBinding
|
|
||||||
|
|
||||||
class MainActivity : AppCompatActivity() {
|
|
||||||
|
|
||||||
lateinit var binding: ActivityMainBinding
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
binding = ActivityMainBinding.inflate(layoutInflater)
|
|
||||||
setContentView(binding.root)
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,11 @@
|
|||||||
|
package fr.uca.iut.urbandictionarylight
|
||||||
|
|
||||||
|
import android.app.Application
|
||||||
|
import fr.uca.iut.urbandictionarylight.data.UrbanDictionaryDatabase
|
||||||
|
|
||||||
|
class UrbanDictionaryLight : Application() {
|
||||||
|
override fun onCreate() {
|
||||||
|
super.onCreate()
|
||||||
|
UrbanDictionaryDatabase.initialize(this)
|
||||||
|
}
|
||||||
|
}
|
@ -1,22 +0,0 @@
|
|||||||
package fr.uca.iut.urbandictionarylight.data
|
|
||||||
|
|
||||||
import androidx.room.*
|
|
||||||
import fr.uca.iut.urbandictionarylight.model.Definition
|
|
||||||
|
|
||||||
@Dao
|
|
||||||
interface DefinitionDao {
|
|
||||||
@Query("SELECT * FROM definitions")
|
|
||||||
fun queryAll(): Set<Definition>
|
|
||||||
|
|
||||||
@Query("SELECT * FROM entries WHERE id == :id")
|
|
||||||
fun query(id: Int): Definition?
|
|
||||||
|
|
||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
|
||||||
fun insert(entry: Definition)
|
|
||||||
|
|
||||||
@Update
|
|
||||||
fun update(entry: Definition)
|
|
||||||
|
|
||||||
@Delete
|
|
||||||
fun delete(entry: Definition)
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
package fr.uca.iut.urbandictionarylight.data
|
|
||||||
|
|
||||||
import androidx.room.*
|
|
||||||
import fr.uca.iut.urbandictionarylight.model.EntryWithDefinitions
|
|
||||||
|
|
||||||
|
|
||||||
@Dao
|
|
||||||
interface EntryDao {
|
|
||||||
@Query("SELECT * FROM entries")
|
|
||||||
fun queryAll(): List<EntryWithDefinitions>
|
|
||||||
|
|
||||||
@Query("SELECT * FROM entries WHERE id == :id")
|
|
||||||
fun query(id: Int): EntryWithDefinitions?
|
|
||||||
|
|
||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
|
||||||
fun insert(entry: EntryWithDefinitions)
|
|
||||||
|
|
||||||
@Update
|
|
||||||
fun update(entry: EntryWithDefinitions)
|
|
||||||
|
|
||||||
@Delete
|
|
||||||
fun delete(entry: EntryWithDefinitions)
|
|
||||||
}
|
|
@ -0,0 +1,23 @@
|
|||||||
|
package fr.uca.iut.urbandictionarylight.data.definition
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import androidx.room.*
|
||||||
|
import fr.uca.iut.urbandictionarylight.model.Definition
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface DefinitionDao {
|
||||||
|
@Query("SELECT * FROM definitions")
|
||||||
|
fun queryAll(): LiveData<List<Definition>>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM entries WHERE id = :id")
|
||||||
|
fun query(id: Long): LiveData<Definition>
|
||||||
|
|
||||||
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
|
suspend fun insert(entry: Definition)
|
||||||
|
|
||||||
|
@Update(onConflict = OnConflictStrategy.REPLACE)
|
||||||
|
suspend fun update(entry: Definition)
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
suspend fun delete(entry: Definition)
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
package fr.uca.iut.urbandictionarylight.data.definition
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import fr.uca.iut.urbandictionarylight.model.Definition
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
|
private const val TAG = "DefinitionRepository"
|
||||||
|
|
||||||
|
|
||||||
|
class DefinitionRepository(private val definitionDao: DefinitionDao) {
|
||||||
|
|
||||||
|
fun getAll(): LiveData<List<Definition>> {
|
||||||
|
Log.i(TAG, "GET ALL DEFINITIONS")
|
||||||
|
return definitionDao.queryAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun findById(definitionId: Long): LiveData<Definition> {
|
||||||
|
Log.i(TAG, "GET DEFINITION")
|
||||||
|
return definitionDao.query(definitionId)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun insert(definition: Definition) = withContext(Dispatchers.IO) {
|
||||||
|
Log.i(TAG, "POST DEFINITION")
|
||||||
|
definitionDao.insert(definition)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun delete(definition: Definition) = withContext(Dispatchers.IO) {
|
||||||
|
Log.i(TAG, "DELETE DEFINITION")
|
||||||
|
definitionDao.delete(definition)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun update(definition: Definition) = withContext(Dispatchers.IO) {
|
||||||
|
Log.i(TAG, "PUT DEFINITION")
|
||||||
|
definitionDao.update(definition)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
package fr.uca.iut.urbandictionarylight.data.entry
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import androidx.room.*
|
||||||
|
import fr.uca.iut.urbandictionarylight.model.EntryWithDefinitions
|
||||||
|
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface EntryDao {
|
||||||
|
@Query("SELECT * FROM entries")
|
||||||
|
fun queryAll(): LiveData<List<EntryWithDefinitions>>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM entries WHERE id = :id")
|
||||||
|
fun query(id: Long): LiveData<EntryWithDefinitions>
|
||||||
|
|
||||||
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
|
suspend fun insert(entry: EntryWithDefinitions)
|
||||||
|
|
||||||
|
@Update
|
||||||
|
suspend fun update(entry: EntryWithDefinitions)
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
suspend fun delete(entry: EntryWithDefinitions)
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
package fr.uca.iut.urbandictionarylight.data.entry
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import fr.uca.iut.urbandictionarylight.model.EntryWithDefinitions
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
|
private const val TAG = "EntryRepository"
|
||||||
|
|
||||||
|
class EntryRepository(private val entryDao: EntryDao) {
|
||||||
|
|
||||||
|
fun getAll(): LiveData<List<EntryWithDefinitions>> {
|
||||||
|
Log.i(TAG, "GET ALL ENTRIES")
|
||||||
|
return entryDao.queryAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun findById(entryId: Long): LiveData<EntryWithDefinitions> {
|
||||||
|
Log.i(TAG, "GET ENTRY")
|
||||||
|
return entryDao.query(entryId)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun insert(entry: EntryWithDefinitions) = withContext(Dispatchers.IO) {
|
||||||
|
Log.i(TAG, "POST ENTRY")
|
||||||
|
entryDao.insert(entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun delete(entry: EntryWithDefinitions) = withContext(Dispatchers.IO) {
|
||||||
|
Log.i(TAG, "DELETE ENTRY")
|
||||||
|
entryDao.delete(entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun update(entry: EntryWithDefinitions) = withContext(Dispatchers.IO) {
|
||||||
|
Log.i(TAG, "PUT ENTRY")
|
||||||
|
entryDao.update(entry)
|
||||||
|
}
|
||||||
|
}
|
@ -1,45 +0,0 @@
|
|||||||
// UHM THIS WILL PROBABLY BE THE REPOSITORY ITSELF
|
|
||||||
|
|
||||||
/*
|
|
||||||
package fr.uca.iut.urbandictionarylight.model
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
class Dictionary {
|
|
||||||
private val entries: MutableSet<Entry> = mutableSetOf()
|
|
||||||
|
|
||||||
fun createEntry(entry: Entry) {
|
|
||||||
if (entry.phrase.isNotBlank() && entry.readAllDefinitions().isNotEmpty()) {
|
|
||||||
entries.add(entry)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun readEntry(id: Int): Entry {
|
|
||||||
// TODO implement once ORM is in place
|
|
||||||
return Entry(phrase = "womp womp -- WIP").also { e -> e.createDefinition(e.readDefinition(-1)) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun readAllEntries() = entries.toSet()
|
|
||||||
|
|
||||||
fun updateEntry(entry: Entry) {
|
|
||||||
// TODO implement once ORM is in place
|
|
||||||
// removeEntry(entry.id)
|
|
||||||
createEntry(entry)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO throw this away soon
|
|
||||||
fun updateEntry(old: Entry, new: Entry) {
|
|
||||||
deleteEntry(old)
|
|
||||||
createEntry(new)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deleteEntry(entry: Entry) {
|
|
||||||
entries.remove(entry)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deleteEntry(id: Int) {
|
|
||||||
// TODO implement once ORM is in place
|
|
||||||
// entries.removeIf { e -> id == e.id }
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO ? redefine equals and hashset ?
|
|
||||||
}*/
|
|
@ -0,0 +1,35 @@
|
|||||||
|
package fr.uca.iut.urbandictionarylight.ui.activity
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
|
import fr.uca.iut.urbandictionarylight.R
|
||||||
|
import fr.uca.iut.urbandictionarylight.model.NEW_ENTRY_ID
|
||||||
|
import fr.uca.iut.urbandictionarylight.ui.fragment.EntryFragment
|
||||||
|
|
||||||
|
class EntryActivity : SimpleFragmentActivity(), EntryFragment.OnInteractionListener {
|
||||||
|
companion object {
|
||||||
|
private const val EXTRA_ENTRY_ID =
|
||||||
|
"fr.uca.iut.urbandictionarylight.ui.activity.extra_entry_id"
|
||||||
|
|
||||||
|
fun getIntent(context: Context, entryId: Long) =
|
||||||
|
Intent(context, EntryActivity::class.java).apply {
|
||||||
|
putExtra(EXTRA_ENTRY_ID, entryId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var entryId = NEW_ENTRY_ID
|
||||||
|
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
entryId = intent.getLongExtra(EXTRA_ENTRY_ID, NEW_ENTRY_ID)
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun createFragment() = EntryFragment.newInstance(entryId)
|
||||||
|
override fun getLayoutResId() = R.layout.toolbar_activity
|
||||||
|
override fun onEntrySaved() = finish()
|
||||||
|
override fun onEntryDeleted() = finish()
|
||||||
|
}
|
@ -0,0 +1,70 @@
|
|||||||
|
package fr.uca.iut.urbandictionarylight.ui.activity
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.widget.FrameLayout
|
||||||
|
import fr.uca.iut.urbandictionarylight.R
|
||||||
|
import fr.uca.iut.urbandictionarylight.model.NEW_ENTRY_ID
|
||||||
|
import fr.uca.iut.urbandictionarylight.ui.fragment.EntryFragment
|
||||||
|
import fr.uca.iut.urbandictionarylight.ui.fragment.EntryListFragment
|
||||||
|
|
||||||
|
class EntryListActivity : SimpleFragmentActivity(),
|
||||||
|
EntryListFragment.OnInteractionListener, EntryFragment.OnInteractionListener {
|
||||||
|
|
||||||
|
private var isTwoPane: Boolean = false
|
||||||
|
private lateinit var masterFragment: EntryListFragment
|
||||||
|
|
||||||
|
override fun createFragment() = EntryListFragment().also { masterFragment = it }
|
||||||
|
override fun getLayoutResId() = R.layout.toolbar_md_activity
|
||||||
|
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
isTwoPane = findViewById<FrameLayout>(R.id.container_fragment_detail) != null
|
||||||
|
if (savedInstanceState != null)
|
||||||
|
masterFragment = supportFragmentManager.findFragmentById(R.id.container_fragment) as EntryListFragment
|
||||||
|
|
||||||
|
if (!isTwoPane) {
|
||||||
|
removeDisplayedFragment()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun onEntrySelected(entryId: Long) {
|
||||||
|
if (isTwoPane) {
|
||||||
|
supportFragmentManager.beginTransaction()
|
||||||
|
.replace(R.id.container_fragment_detail, EntryFragment.newInstance(entryId))
|
||||||
|
.commit()
|
||||||
|
} else {
|
||||||
|
startActivity(EntryPagerActivity.getIntent(this, entryId))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun onAddNewEntry() = startActivity(EntryActivity.getIntent(this, NEW_ENTRY_ID))
|
||||||
|
|
||||||
|
|
||||||
|
override fun onEntrySaved() { }
|
||||||
|
|
||||||
|
|
||||||
|
private fun removeDisplayedFragment() {
|
||||||
|
supportFragmentManager.findFragmentById(R.id.container_fragment_detail)?.let {
|
||||||
|
supportFragmentManager.beginTransaction().remove(it).commit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun onEntryDeleted() {
|
||||||
|
if (isTwoPane) {
|
||||||
|
removeDisplayedFragment()
|
||||||
|
} else
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun onEntrySwiped() {
|
||||||
|
if (isTwoPane) {
|
||||||
|
removeDisplayedFragment()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
package fr.uca.iut.urbandictionarylight.ui.activity
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import androidx.activity.viewModels
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.viewpager2.widget.ViewPager2
|
||||||
|
import fr.uca.iut.urbandictionarylight.R
|
||||||
|
import fr.uca.iut.urbandictionarylight.model.NEW_ENTRY_ID
|
||||||
|
import fr.uca.iut.urbandictionarylight.ui.fragment.EntryFragment
|
||||||
|
import fr.uca.iut.urbandictionarylight.ui.utils.EntryPagerAdapter
|
||||||
|
import fr.uca.iut.urbandictionarylight.ui.viewmodel.EntryPagerViewModel
|
||||||
|
|
||||||
|
|
||||||
|
class EntryPagerActivity : AppCompatActivity(), EntryFragment.OnInteractionListener {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val EXTRA_ENTRY_ID =
|
||||||
|
"fr.uca.iut.urbandictionarylight.ui.activity.extra_entry_id"
|
||||||
|
|
||||||
|
fun getIntent(context: Context, entryId: Long) =
|
||||||
|
Intent(context, EntryPagerActivity::class.java).apply {
|
||||||
|
putExtra(EXTRA_ENTRY_ID, entryId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val pagerAdapter = EntryPagerAdapter(this)
|
||||||
|
private val entryPagerVM by viewModels<EntryPagerViewModel>()
|
||||||
|
private lateinit var viewPager: ViewPager2
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(R.layout.activity_pager)
|
||||||
|
|
||||||
|
setSupportActionBar(findViewById(R.id.toolbar_activity))
|
||||||
|
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||||
|
|
||||||
|
viewPager = ViewPager2(this)
|
||||||
|
viewPager.id = R.id.view_pager
|
||||||
|
findViewById<LinearLayout>(R.id.pager_layout).addView(viewPager)
|
||||||
|
|
||||||
|
viewPager.adapter = pagerAdapter
|
||||||
|
entryPagerVM.currentEntryId =
|
||||||
|
savedInstanceState?.getLong(EXTRA_ENTRY_ID) ?: intent.getLongExtra(
|
||||||
|
EXTRA_ENTRY_ID,
|
||||||
|
NEW_ENTRY_ID
|
||||||
|
)
|
||||||
|
|
||||||
|
entryPagerVM.entryList.observe(this) {
|
||||||
|
pagerAdapter.submitList(it)
|
||||||
|
var position = pagerAdapter.positionFromId(entryPagerVM.currentEntryId)
|
||||||
|
if (position == -1) position = 0
|
||||||
|
viewPager.currentItem = position
|
||||||
|
}
|
||||||
|
|
||||||
|
viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
|
||||||
|
override fun onPageSelected(position: Int) {
|
||||||
|
entryPagerVM.currentEntryId = pagerAdapter.entryIdAt(position)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSaveInstanceState(outState: Bundle) {
|
||||||
|
super.onSaveInstanceState(outState)
|
||||||
|
outState.putLong(EXTRA_ENTRY_ID, entryPagerVM.currentEntryId)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onEntrySaved() = finish()
|
||||||
|
override fun onEntryDeleted() = finish()
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,29 @@
|
|||||||
|
package fr.uca.iut.urbandictionarylight.ui.activity
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.annotation.LayoutRes
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import fr.uca.iut.urbandictionarylight.R
|
||||||
|
|
||||||
|
abstract class SimpleFragmentActivity : AppCompatActivity() {
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
setContentView(getLayoutResId())
|
||||||
|
|
||||||
|
setSupportActionBar(findViewById(R.id.toolbar_activity))
|
||||||
|
|
||||||
|
if (supportFragmentManager.findFragmentById(R.id.container_fragment) == null) {
|
||||||
|
supportFragmentManager.beginTransaction()
|
||||||
|
.add(R.id.container_fragment, createFragment())
|
||||||
|
.commit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract fun createFragment(): Fragment
|
||||||
|
|
||||||
|
@LayoutRes
|
||||||
|
protected abstract fun getLayoutResId(): Int
|
||||||
|
}
|
@ -0,0 +1,138 @@
|
|||||||
|
package fr.uca.iut.urbandictionarylight.ui.fragment
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.*
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
import androidx.core.os.bundleOf
|
||||||
|
import androidx.core.view.MenuProvider
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.lifecycle.Lifecycle
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.lifecycle.get
|
||||||
|
import androidx.lifecycle.viewmodel.viewModelFactory
|
||||||
|
import fr.uca.iut.urbandictionarylight.R
|
||||||
|
import fr.uca.iut.urbandictionarylight.databinding.FragmentEntryBinding
|
||||||
|
import fr.uca.iut.urbandictionarylight.model.NEW_ENTRY_ID
|
||||||
|
import fr.uca.iut.urbandictionarylight.ui.viewmodel.EntryViewModel
|
||||||
|
|
||||||
|
class EntryFragment : Fragment() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val EXTRA_ENTRY_ID =
|
||||||
|
"fr.uca.iut.urbandictionarylight.ui.activity.extra_entry_id"
|
||||||
|
|
||||||
|
fun newInstance(entryId: Long) = EntryFragment().apply {
|
||||||
|
arguments = bundleOf(EXTRA_ENTRY_ID to entryId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var entryId: Long = NEW_ENTRY_ID
|
||||||
|
private lateinit var entryVM: EntryViewModel
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
entryId = savedInstanceState?.getLong(EXTRA_ENTRY_ID) ?: arguments?.getLong(EXTRA_ENTRY_ID)
|
||||||
|
?: NEW_ENTRY_ID
|
||||||
|
|
||||||
|
|
||||||
|
if (entryId == NEW_ENTRY_ID) {
|
||||||
|
requireActivity().setTitle(R.string.add_entry_lbl)
|
||||||
|
}
|
||||||
|
|
||||||
|
entryVM = ViewModelProvider(this, viewModelFactory { EntryViewModel(entryId) }).get()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSaveInstanceState(outState: Bundle) {
|
||||||
|
super.onSaveInstanceState(outState)
|
||||||
|
outState.putLong(EXTRA_ENTRY_ID, entryId)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater, container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View {
|
||||||
|
val binding = FragmentEntryBinding.inflate(inflater)
|
||||||
|
binding.entryVM = entryVM
|
||||||
|
binding.lifecycleOwner = viewLifecycleOwner
|
||||||
|
|
||||||
|
return binding.root
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
setupMenu()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupMenu() {
|
||||||
|
requireActivity().addMenuProvider(object : MenuProvider {
|
||||||
|
override fun onPrepareMenu(menu: Menu) {
|
||||||
|
super.onPrepareMenu(menu)
|
||||||
|
if (entryId == NEW_ENTRY_ID) {
|
||||||
|
menu.findItem(R.id.action_delete)?.isVisible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
|
||||||
|
menuInflater.inflate(R.menu.fragment_entry, menu)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
|
||||||
|
return when (menuItem.itemId) {
|
||||||
|
R.id.action_save -> {
|
||||||
|
saveEntry()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
R.id.action_delete -> {
|
||||||
|
deleteEntry()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}, viewLifecycleOwner, Lifecycle.State.RESUMED)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun saveEntry() {
|
||||||
|
if (entryVM.saveEntry() == true) {
|
||||||
|
listener?.onEntrySaved()
|
||||||
|
} else {
|
||||||
|
AlertDialog.Builder(requireActivity())
|
||||||
|
.setTitle(R.string.create_entry_error_dialog_title)
|
||||||
|
.setMessage(R.string.create_entry_error_message)
|
||||||
|
.setNeutralButton(android.R.string.ok, null)
|
||||||
|
.show()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deleteEntry() {
|
||||||
|
if (entryId != NEW_ENTRY_ID) {
|
||||||
|
entryVM.deleteEntry()
|
||||||
|
listener?.onEntryDeleted()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface OnInteractionListener {
|
||||||
|
fun onEntrySaved()
|
||||||
|
fun onEntryDeleted()
|
||||||
|
}
|
||||||
|
|
||||||
|
private var listener: OnInteractionListener? = null
|
||||||
|
|
||||||
|
override fun onAttach(context: Context) {
|
||||||
|
super.onAttach(context)
|
||||||
|
if (context is OnInteractionListener) {
|
||||||
|
listener = context
|
||||||
|
} else {
|
||||||
|
throw RuntimeException("$context must implement OnInteractionListener")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDetach() {
|
||||||
|
super.onDetach()
|
||||||
|
listener = null
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,129 @@
|
|||||||
|
package fr.uca.iut.urbandictionarylight.ui.fragment
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.*
|
||||||
|
import androidx.core.view.MenuProvider
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.viewModels
|
||||||
|
import androidx.lifecycle.Lifecycle
|
||||||
|
import androidx.recyclerview.widget.ItemTouchHelper
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import fr.uca.iut.urbandictionarylight.R
|
||||||
|
import fr.uca.iut.urbandictionarylight.databinding.FragmentListEntryBinding
|
||||||
|
import fr.uca.iut.urbandictionarylight.ui.utils.EntryRecyclerViewAdapter
|
||||||
|
import fr.uca.iut.urbandictionarylight.ui.viewmodel.EntryListViewModel
|
||||||
|
|
||||||
|
|
||||||
|
class EntryListFragment : Fragment(), EntryRecyclerViewAdapter.Callbacks {
|
||||||
|
|
||||||
|
private val entryListAdapter = EntryRecyclerViewAdapter(this)
|
||||||
|
private val entryListVM by viewModels<EntryListViewModel>()
|
||||||
|
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater, container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View {
|
||||||
|
val binding = FragmentListEntryBinding.inflate(inflater)
|
||||||
|
binding.entryListVM = entryListVM
|
||||||
|
binding.lifecycleOwner = viewLifecycleOwner
|
||||||
|
with(binding.recyclerView) {
|
||||||
|
adapter = entryListAdapter
|
||||||
|
ItemTouchHelper(EntryListItemTouchHelper()).attachToRecyclerView(this)
|
||||||
|
}
|
||||||
|
binding.addEntryBtn.setOnClickListener { addNewEntry() }
|
||||||
|
return binding.root
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
setupMenu()
|
||||||
|
|
||||||
|
entryListVM.entryList.observe(viewLifecycleOwner) {
|
||||||
|
entryListAdapter.submitList(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun setupMenu() {
|
||||||
|
requireActivity().addMenuProvider(object : MenuProvider {
|
||||||
|
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
|
||||||
|
menuInflater.inflate(R.menu.fragment_list_entry, menu)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
|
||||||
|
return when (menuItem.itemId) {
|
||||||
|
R.id.menu_item_new_entry -> {
|
||||||
|
addNewEntry()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, viewLifecycleOwner, Lifecycle.State.RESUMED)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun addNewEntry() {
|
||||||
|
listener?.onAddNewEntry()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun onEntrySelected(entryId: Long) {
|
||||||
|
listener?.onEntrySelected(entryId)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private inner class EntryListItemTouchHelper : ItemTouchHelper.Callback() {
|
||||||
|
override fun isLongPressDragEnabled() = false
|
||||||
|
|
||||||
|
override fun getMovementFlags(
|
||||||
|
recyclerView: RecyclerView,
|
||||||
|
viewHolder: RecyclerView.ViewHolder
|
||||||
|
) =
|
||||||
|
makeMovementFlags(
|
||||||
|
ItemTouchHelper.UP or ItemTouchHelper.DOWN,
|
||||||
|
ItemTouchHelper.START or ItemTouchHelper.END
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun onMove(
|
||||||
|
recyclerView: RecyclerView,
|
||||||
|
viewHolder: RecyclerView.ViewHolder,
|
||||||
|
target: RecyclerView.ViewHolder
|
||||||
|
) = false
|
||||||
|
|
||||||
|
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
|
||||||
|
(viewHolder as EntryRecyclerViewAdapter.EntryViewHolder).entry?.also {
|
||||||
|
entryListVM.delete(it)
|
||||||
|
listener?.onEntrySwiped()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
interface OnInteractionListener {
|
||||||
|
fun onEntrySelected(entryId: Long)
|
||||||
|
fun onAddNewEntry()
|
||||||
|
fun onEntrySwiped()
|
||||||
|
}
|
||||||
|
|
||||||
|
private var listener: OnInteractionListener? = null
|
||||||
|
|
||||||
|
|
||||||
|
override fun onAttach(context: Context) {
|
||||||
|
super.onAttach(context)
|
||||||
|
if (context is OnInteractionListener) {
|
||||||
|
listener = context
|
||||||
|
} else {
|
||||||
|
throw RuntimeException("$context must implement OnInteractionListener")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun onDetach() {
|
||||||
|
super.onDetach()
|
||||||
|
listener = null
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package fr.uca.iut.urbandictionarylight.ui.utils
|
||||||
|
|
||||||
|
import androidx.fragment.app.FragmentActivity
|
||||||
|
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||||
|
import fr.uca.iut.urbandictionarylight.model.EntryWithDefinitions
|
||||||
|
import fr.uca.iut.urbandictionarylight.model.NEW_ENTRY_ID
|
||||||
|
import fr.uca.iut.urbandictionarylight.ui.fragment.EntryFragment
|
||||||
|
|
||||||
|
class EntryPagerAdapter(fragmentActivity: FragmentActivity) :
|
||||||
|
FragmentStateAdapter(fragmentActivity) {
|
||||||
|
private var entryList = listOf<EntryWithDefinitions>()
|
||||||
|
|
||||||
|
override fun getItemCount() = entryList.size
|
||||||
|
|
||||||
|
override fun createFragment(position: Int) =
|
||||||
|
EntryFragment.newInstance(entryList[position].entry.id)
|
||||||
|
|
||||||
|
fun positionFromId(entryId: Long) = entryList.indexOfFirst { it.entry.id == entryId }
|
||||||
|
|
||||||
|
fun entryIdAt(position: Int) =
|
||||||
|
if (entryList.isEmpty()) NEW_ENTRY_ID else entryList[position].entry.id
|
||||||
|
|
||||||
|
fun submitList(entryList: List<EntryWithDefinitions>) {
|
||||||
|
this.entryList = entryList
|
||||||
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
package fr.uca.iut.urbandictionarylight.ui.utils
|
||||||
|
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import fr.uca.iut.urbandictionarylight.databinding.ItemListEntryBinding
|
||||||
|
import fr.uca.iut.urbandictionarylight.model.EntryWithDefinitions
|
||||||
|
|
||||||
|
class EntryRecyclerViewAdapter(private val listener: Callbacks) :
|
||||||
|
ListAdapter<EntryWithDefinitions, EntryRecyclerViewAdapter.EntryViewHolder>(
|
||||||
|
DiffUtilEntryCallback
|
||||||
|
) {
|
||||||
|
|
||||||
|
private object DiffUtilEntryCallback : DiffUtil.ItemCallback<EntryWithDefinitions>() {
|
||||||
|
override fun areItemsTheSame(oldItem: EntryWithDefinitions, newItem: EntryWithDefinitions) =
|
||||||
|
oldItem.entry.id == newItem.entry.id
|
||||||
|
|
||||||
|
override fun areContentsTheSame(
|
||||||
|
oldItem: EntryWithDefinitions,
|
||||||
|
newItem: EntryWithDefinitions
|
||||||
|
) = oldItem == newItem
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
|
||||||
|
EntryViewHolder(
|
||||||
|
ItemListEntryBinding.inflate(LayoutInflater.from(parent.context)), listener
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: EntryViewHolder, position: Int) =
|
||||||
|
holder.bind(getItem(position))
|
||||||
|
|
||||||
|
|
||||||
|
class EntryViewHolder(private val binding: ItemListEntryBinding, listener: Callbacks) :
|
||||||
|
RecyclerView.ViewHolder(binding.root) {
|
||||||
|
|
||||||
|
val entry: EntryWithDefinitions? get() = binding.entryWithDefinitions
|
||||||
|
|
||||||
|
init {
|
||||||
|
itemView.setOnClickListener { entry?.let { listener.onEntrySelected(it.entry.id) } }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun bind(entryWithDefinitions: EntryWithDefinitions) {
|
||||||
|
binding.entryWithDefinitions = entryWithDefinitions
|
||||||
|
binding.executePendingBindings()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Callbacks {
|
||||||
|
fun onEntrySelected(entryId: Long)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package fr.uca.iut.urbandictionarylight.ui.utils
|
||||||
|
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
inline fun <VM : ViewModel> viewModelFactory(crossinline f: () -> VM) = object : ViewModelProvider.Factory {
|
||||||
|
override fun <T : ViewModel> create(modelClass: Class<T>): T = f() as T
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package fr.uca.iut.urbandictionarylight.ui.viewmodel
|
||||||
|
|
||||||
|
import androidx.lifecycle.Transformations
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import fr.uca.iut.urbandictionarylight.data.UrbanDictionaryDatabase
|
||||||
|
import fr.uca.iut.urbandictionarylight.data.entry.EntryRepository
|
||||||
|
import fr.uca.iut.urbandictionarylight.model.EntryWithDefinitions
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
class EntryListViewModel : ViewModel() {
|
||||||
|
private val entryRepo = EntryRepository(UrbanDictionaryDatabase.getInstance().entryDao())
|
||||||
|
|
||||||
|
val entryList = entryRepo.getAll()
|
||||||
|
|
||||||
|
fun delete(entry: EntryWithDefinitions) = viewModelScope.launch { entryRepo.delete(entry) }
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
package fr.uca.iut.urbandictionarylight.ui.viewmodel
|
||||||
|
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import fr.uca.iut.urbandictionarylight.data.UrbanDictionaryDatabase
|
||||||
|
import fr.uca.iut.urbandictionarylight.data.entry.EntryRepository
|
||||||
|
import fr.uca.iut.urbandictionarylight.model.NEW_ENTRY_ID
|
||||||
|
|
||||||
|
class EntryPagerViewModel : ViewModel() {
|
||||||
|
private val entryRepo = EntryRepository(UrbanDictionaryDatabase.getInstance().entryDao())
|
||||||
|
val entryList = entryRepo.getAll()
|
||||||
|
var currentEntryId = NEW_ENTRY_ID
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package fr.uca.iut.urbandictionarylight.ui.viewmodel
|
||||||
|
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import fr.uca.iut.urbandictionarylight.data.UrbanDictionaryDatabase
|
||||||
|
import fr.uca.iut.urbandictionarylight.data.entry.EntryRepository
|
||||||
|
import fr.uca.iut.urbandictionarylight.model.EntryWithDefinitions
|
||||||
|
import fr.uca.iut.urbandictionarylight.model.NEW_ENTRY_ID
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
|
||||||
|
class EntryViewModel(entryId: Long) : ViewModel() {
|
||||||
|
private val entryRepo = EntryRepository(UrbanDictionaryDatabase.getInstance().entryDao())
|
||||||
|
|
||||||
|
val entry =
|
||||||
|
if (entryId == NEW_ENTRY_ID) MutableLiveData(EntryWithDefinitions()) else entryRepo.findById(
|
||||||
|
entryId
|
||||||
|
)
|
||||||
|
|
||||||
|
fun saveEntry() = entry.value?.let {
|
||||||
|
if (it.entry.phrase.isBlank() || it.definitions.isEmpty())
|
||||||
|
false
|
||||||
|
else {
|
||||||
|
viewModelScope.launch {
|
||||||
|
if (it.entry.id == NEW_ENTRY_ID) entryRepo.insert(it) else entryRepo.update(it)
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deleteEntry() = viewModelScope.launch {
|
||||||
|
entry.value?.let { if (it.entry.id != NEW_ENTRY_ID) entryRepo.delete(it) }
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +0,0 @@
|
|||||||
package fr.uca.iut.urbandictionarylight.utils
|
|
||||||
|
|
||||||
public enum class Sorting {
|
|
||||||
ASC, DESC
|
|
||||||
}
|
|
@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#727272"
|
||||||
|
android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
|
||||||
|
</vector>
|
@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFFFF"
|
||||||
|
android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7H6v12zM19,4h-3.5l-1,-1h-5l-1,1H5v2h14V4z"/>
|
||||||
|
</vector>
|
@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFFFF"
|
||||||
|
android:pathData="M9,16.2L4.8,12l-1.4,1.4L9,19 21,7l-1.4,-1.4L9,16.2z"/>
|
||||||
|
</vector>
|
@ -0,0 +1,22 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:baselineAligned="false"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:showDividers="middle"
|
||||||
|
android:divider="?android:attr/dividerVertical">
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/container_fragment"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="3" />
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/container_fragment_detail"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="7" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
@ -1,82 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
tools:context=".MainActivity">
|
|
||||||
|
|
||||||
<SearchView
|
|
||||||
android:id="@+id/search_view"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:layout_marginTop="32dp"
|
|
||||||
android:layout_marginEnd="16dp"
|
|
||||||
android:background="#EEE"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
|
||||||
android:id="@+id/recycler_view"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:layout_marginEnd="16dp"
|
|
||||||
android:clipToPadding="false"
|
|
||||||
android:padding="16dp"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/search_view" />
|
|
||||||
|
|
||||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
|
||||||
android:id="@+id/add_definition_btn"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:layout_marginEnd="24dp"
|
|
||||||
android:clickable="true"
|
|
||||||
android:contentDescription="@string/add_def_btn"
|
|
||||||
android:focusable="true"
|
|
||||||
app:backgroundTint="#55752F"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/search_view"
|
|
||||||
app:srcCompat="@android:drawable/ic_input_add" />
|
|
||||||
|
|
||||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
|
||||||
android:id="@+id/add_term_btn"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="24dp"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:clickable="true"
|
|
||||||
android:contentDescription="@string/add_term_btn"
|
|
||||||
android:focusable="true"
|
|
||||||
app:backgroundTint="#3E4E83"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/search_view"
|
|
||||||
app:srcCompat="@android:drawable/ic_input_add" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/add_definition_btn_lbl"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:layout_marginEnd="16dp"
|
|
||||||
android:text="@string/add_def_lbl"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/add_definition_btn" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/add_term_btn_lbl"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:text="@string/add_term_lbl"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/add_term_btn" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:id="@+id/pager_layout">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.Toolbar
|
||||||
|
android:id="@+id/toolbar_activity"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="?attr/actionBarSize"
|
||||||
|
android:background="?attr/colorPrimary"
|
||||||
|
app:elevation="@dimen/toolbar_elevation"
|
||||||
|
app:titleMarginStart="@dimen/icon_title_space" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
@ -0,0 +1,141 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
|
<data>
|
||||||
|
|
||||||
|
<variable
|
||||||
|
name="entryVM"
|
||||||
|
type="fr.uca.iut.urbandictionarylight.ui.viewmodel.EntryViewModel" />
|
||||||
|
</data>
|
||||||
|
|
||||||
|
<ScrollView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:fillViewport="true">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="@dimen/activity_margin"
|
||||||
|
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
|
||||||
|
android:id="@+id/text_overview"
|
||||||
|
style="@style/CategoryStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/category_overview"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
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:inputType="textCapWords"
|
||||||
|
android:text="@={entryVM.dog.name}"
|
||||||
|
app:layout_constraintBaseline_toBaselineOf="@+id/text_overview"
|
||||||
|
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_constraintTop_toBottomOf="@+id/spinner_gender" />
|
||||||
|
|
||||||
|
<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
|
||||||
|
android:id="@+id/label_weight_unit"
|
||||||
|
style="@style/EditorUnitsStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:text="@string/unit_dog_weight"
|
||||||
|
app:layout_constraintBaseline_toBaselineOf="@+id/text_measurement"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
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>
|
||||||
|
</ScrollView>
|
||||||
|
</layout>
|
@ -0,0 +1,55 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
|
<data>
|
||||||
|
|
||||||
|
<import type="android.view.View" />
|
||||||
|
|
||||||
|
<variable
|
||||||
|
name="entryListVM"
|
||||||
|
type="fr.uca.iut.urbandictionarylight.ui.viewmodel.EntryListViewModel" />
|
||||||
|
</data>
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context=".ui.activity.EntryListActivity">
|
||||||
|
|
||||||
|
<SearchView
|
||||||
|
android:id="@+id/search_view"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_marginTop="32dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:background="#EEE"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/recycler_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
|
||||||
|
app:spanCount="2"
|
||||||
|
tools:listitem="@layout/item_list_entry" />
|
||||||
|
|
||||||
|
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
|
android:id="@+id/add_entry_btn"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="24dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:clickable="true"
|
||||||
|
android:contentDescription="@string/add_entry_btn"
|
||||||
|
android:focusable="true"
|
||||||
|
app:backgroundTint="#3E4E83"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/search_view"
|
||||||
|
app:srcCompat="@android:drawable/ic_input_add" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
</layout>
|
@ -0,0 +1,37 @@
|
|||||||
|
<?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="entryWithDefinitions"
|
||||||
|
type="fr.uca.iut.urbandictionarylight.model.EntryWithDefinitions" />
|
||||||
|
</data>
|
||||||
|
|
||||||
|
<androidx.cardview.widget.CardView
|
||||||
|
android:id="@+id/cardview_entry"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="2dp"
|
||||||
|
card_view:cardUseCompatPadding="true">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/layout_cardview_entry"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="@dimen/activity_margin">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/view_name"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="sans-serif-medium"
|
||||||
|
android:text="@{entryWithDefinitions.entry.phrase}"
|
||||||
|
android:textAppearance="?android:textAppearanceMedium"
|
||||||
|
android:textColor="@color/black"
|
||||||
|
tools:text="Entry phrase" />
|
||||||
|
</LinearLayout>
|
||||||
|
</androidx.cardview.widget.CardView>
|
||||||
|
</layout>
|
@ -0,0 +1,25 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
tools:context=".ui.activity.EntryActivity">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.Toolbar
|
||||||
|
android:id="@+id/toolbar_activity"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="?attr/actionBarSize"
|
||||||
|
android:background="?attr/colorPrimary"
|
||||||
|
android:theme="@style/Theme.UrbanDictionaryLight.AppBarOverlay"
|
||||||
|
app:elevation="@dimen/toolbar_elevation"
|
||||||
|
app:popupTheme="@style/Theme.UrbanDictionaryLight.PopupOverlay"
|
||||||
|
app:titleMarginStart="@dimen/icon_title_space" />
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/container_fragment"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
@ -0,0 +1,22 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
tools:context=".ui.activity.EntryListActivity">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.Toolbar
|
||||||
|
android:id="@+id/toolbar_activity"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="?attr/actionBarSize"
|
||||||
|
android:background="?attr/colorPrimary"
|
||||||
|
app:elevation="@dimen/toolbar_elevation"
|
||||||
|
android:theme="@style/Theme.UrbanDictionaryLight.AppBarOverlay"
|
||||||
|
app:popupTheme="@style/Theme.UrbanDictionaryLight.PopupOverlay"
|
||||||
|
app:titleMarginStart="@dimen/icon_title_space" />
|
||||||
|
|
||||||
|
<include layout="@layout/toolbar_md_activity_content" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
@ -0,0 +1,4 @@
|
|||||||
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/container_fragment"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_save"
|
||||||
|
android:icon="@drawable/ic_done"
|
||||||
|
android:title="@string/save_lbl"
|
||||||
|
app:showAsAction="always"/>
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_delete"
|
||||||
|
android:icon="@drawable/ic_delete"
|
||||||
|
android:title="@string/delete_lbl"
|
||||||
|
app:showAsAction="ifRoom"/>
|
||||||
|
</menu>
|
@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/menu_item_new_entry"
|
||||||
|
android:icon="@drawable/ic_add"
|
||||||
|
android:title="@string/add_entry_lbl"
|
||||||
|
app:showAsAction="never"/>
|
||||||
|
|
||||||
|
</menu>
|
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="app_name">Urban Dictionary Light</string>
|
||||||
|
<string name="add_def_lbl">Nouvelle définition</string>
|
||||||
|
<string name="add_def_btn">Cliquez pour ajouter une nouvelle définition</string>
|
||||||
|
<string name="add_entry_lbl">Nouveau terme</string>
|
||||||
|
<string name="add_entry_btn">Cliquez pour ajouter un nouveau terme</string>
|
||||||
|
<string name="save_lbl">Enregistrer</string>
|
||||||
|
<string name="delete_lbl">Supprimer</string>
|
||||||
|
</resources>
|
@ -1,10 +1,13 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<color name="purple_200">#FFBB86FC</color>
|
|
||||||
<color name="purple_500">#FF6200EE</color>
|
|
||||||
<color name="purple_700">#FF3700B3</color>
|
|
||||||
<color name="teal_200">#FF03DAC5</color>
|
<color name="teal_200">#FF03DAC5</color>
|
||||||
<color name="teal_700">#FF018786</color>
|
<color name="teal_700">#0097A7</color>
|
||||||
|
<color name="teal_900">#006064</color>
|
||||||
|
|
||||||
|
<color name="blue_200">#62A3FF</color>
|
||||||
|
<color name="blue_700">#1675D1</color>
|
||||||
|
<color name="blue_900">#004A9F</color>
|
||||||
|
|
||||||
<color name="black">#FF000000</color>
|
<color name="black">#FF000000</color>
|
||||||
<color name="white">#FFFFFFFF</color>
|
<color name="white">#FFFFFFFF</color>
|
||||||
</resources>
|
</resources>
|
@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<!-- Common margin value used throughout the app -->
|
||||||
|
<dimen name="activity_margin">16dp</dimen>
|
||||||
|
<dimen name="text_margin">16dp</dimen>
|
||||||
|
|
||||||
|
<dimen name="toolbar_elevation">4dp</dimen>
|
||||||
|
|
||||||
|
<!-- Common spaces used throughout the app -->
|
||||||
|
<dimen name="large_space">32dp</dimen>
|
||||||
|
<dimen name="medium_space">16dp</dimen>
|
||||||
|
<dimen name="small_space">8dp</dimen>
|
||||||
|
<dimen name="icon_title_space">24dp</dimen>
|
||||||
|
</resources>
|
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<item name="view_pager" type="id" />
|
||||||
|
</resources>
|
@ -1,7 +1,12 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">Urban Dictionary Light</string>
|
<string name="app_name">Urban Dictionary Light</string>
|
||||||
|
|
||||||
<string name="add_def_lbl">New definition</string>
|
<string name="add_def_lbl">New definition</string>
|
||||||
<string name="add_term_lbl">New term</string>
|
|
||||||
<string name="add_term_btn">Click to add a new term</string>
|
|
||||||
<string name="add_def_btn">Click to add a new definition</string>
|
<string name="add_def_btn">Click to add a new definition</string>
|
||||||
|
<string name="add_entry_lbl">New term</string>
|
||||||
|
<string name="add_entry_btn">Click to add a new term</string>
|
||||||
|
<string name="save_lbl">Save</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_message" translatable="false">sorry bud, no can do</string>
|
||||||
</resources>
|
</resources>
|
Loading…
Reference in new issue