Commit 61f93aaf by Paktalin

Saves changes only to the local Vocabulary

parent 080d3fb8
package com.paktalin.vocabularynotebook
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.rule.ActivityTestRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest
import com.paktalin.vocabularynotebook.ui.activities.MainActivity
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class HelloWorldEspressoTest {
@get:Rule
val activityRule = ActivityTestRule(MainActivity::class.java)
@Test
fun listGoesOverTheFold() {
onView(withId(R.id.container_main)).perform(click())
}
}
\ No newline at end of file
package com.paktalin.vocabularynotebook.ui.activities
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.action.ViewActions.typeText
import androidx.test.espresso.intent.rule.IntentsTestRule
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.rule.ActivityTestRule
import com.paktalin.vocabularynotebook.R
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class LogInActivityTest {
@get:Rule
val activityRule = ActivityTestRule(LogInActivity::class.java)
@get:Rule
var mLoginActivityActivityTestRule: IntentsTestRule<LogInActivity> = IntentsTestRule(LogInActivity::class.java)
@Test
fun user_can_enter_username() {
onView(withId(R.id.etUsername)).perform(typeText("likorn"))
}
@Test
fun user_can_enter_password() {
onView(withId(R.id.etPassword)).perform(typeText("123456"))
}
@Test
fun user_can_login() {
onView(withId(R.id.btnLogIn)).perform(click())
}
@Test
fun user_can_sign_up() {
onView(withId(R.id.btnSignUp)).perform(click())
}
}
\ No newline at end of file
...@@ -4,25 +4,38 @@ import com.google.firebase.Timestamp ...@@ -4,25 +4,38 @@ import com.google.firebase.Timestamp
import com.google.firebase.firestore.DocumentSnapshot import com.google.firebase.firestore.DocumentSnapshot
import com.paktalin.vocabularynotebook.firestoreitems.WordItem import com.paktalin.vocabularynotebook.firestoreitems.WordItem
import com.paktalin.vocabularynotebook.utils.FirestoreManager.Companion.vocabularyId import com.paktalin.vocabularynotebook.utils.FirestoreManager.Companion.vocabularyId
import com.paktalin.vocabularynotebook.utils.Log
class Vocabulary() { class Vocabulary() {
private var words: MutableList<WordItem> = mutableListOf() private var allWords: MutableList<WordItem> = mutableListOf()
private var displayed: MutableList<WordItem> = mutableListOf() private var displayed: MutableList<WordItem> = mutableListOf()
constructor(vocabulary: Vocabulary) : this() { companion object {
copyWordsFrom(vocabulary) private val TAG = "VN/" + Vocabulary::class.java.simpleName
}
const val SORT_BY_TIME = 0
const val SORT_BY_WORD = 1
const val SORT_BY_TRANSLATION = 2
constructor(documents: MutableList<DocumentSnapshot>) : this() { fun createFromDocs(documents: MutableList<DocumentSnapshot>): Vocabulary {
documents.forEach { ref -> val wordsFromDocs = mutableListOf<WordItem>()
words.add(WordItem( documents.forEach { ref ->
ref["word"].toString(), wordsFromDocs.add(WordItem(
ref["translation"].toString(), ref["word"].toString(),
(ref["time"] as Timestamp).toDate(), ref["translation"].toString(),
ref.id, vocabularyId!!)) (ref["time"] as Timestamp).toDate(),
ref.id, vocabularyId!!))
}
return Vocabulary(wordsFromDocs)
} }
} }
// TODO make private
constructor(words: MutableList<WordItem>): this() {
this.allWords.addAll(words)
this.displayed.addAll(words)
}
fun sort(sortOrder:Int) { fun sort(sortOrder:Int) {
when(sortOrder) { when(sortOrder) {
SORT_BY_TIME -> sortByTime() SORT_BY_TIME -> sortByTime()
...@@ -31,56 +44,50 @@ class Vocabulary() { ...@@ -31,56 +44,50 @@ class Vocabulary() {
} }
} }
fun deleteWord(position:Int) { fun deleteWord(wordItem: WordItem) {
words[position].delete() // delete word from the database allWords.remove(wordItem)
words.removeAt(position) // delete word from the list displayed.remove(wordItem)
} }
fun addWord(newWord: WordItem) { fun addWord(newWord: WordItem) {
words.add(0, newWord) Log.d(TAG, "vocabulary addWord")
allWords.add(0, newWord)
displayed.add(0, newWord)
displayed.forEach { w -> Log.d(TAG, w.toString()) }
} }
fun copyWordsFrom(vocabulary: Vocabulary) { fun displayAll() {
words.addAll(vocabulary.get()) displayed.addAll(allWords)
} }
fun addWordsFittingQuery(vocabulary: Vocabulary, query:String) { fun displayByQuery(query: String) {
vocabulary.get().filter { wordItem -> wordItem.contains(query) }.toCollection(words) allWords.filter { wordItem -> wordItem.contains(query) }.toCollection(displayed)
} }
fun updateWord(updatedWord: WordItem) { fun updateWord(updatedWord: WordItem) {
val updatedItemIndex = words.indexOf(updatedWord) allWords[allWords.indexOf(updatedWord)] = updatedWord
words[updatedItemIndex] = updatedWord displayed[displayed.indexOf(updatedWord)] = updatedWord
} }
fun getAt(position: Int): WordItem { fun displayedAt(position: Int): WordItem {
return words[position] return displayed[position]
} }
fun get():MutableList<WordItem> { return words } fun displayedSize():Int { return displayed.size }
fun size():Int { return words.size } fun clearDisplayed() { displayed.clear() }
fun clear() { words.clear() }
private fun sortByTime() { private fun sortByTime() {
words.sortWith(Comparator { item1, item2 -> displayed.sortWith(Comparator { item1, item2 ->
-item1.pojo.time!!.compareTo(item2.pojo.time) }) -item1.pojo.time!!.compareTo(item2.pojo.time) })
} }
private fun sortByWord() { private fun sortByWord() {
words.sortWith(Comparator { item1, item2 -> displayed.sortWith(Comparator { item1, item2 ->
item1.pojo.word.toLowerCase().compareTo(item2.pojo.word.toLowerCase()) }) item1.pojo.word.toLowerCase().compareTo(item2.pojo.word.toLowerCase()) })
} }
private fun sortByTranslation() { private fun sortByTranslation() {
words.sortWith(Comparator { item1, item2 -> displayed.sortWith(Comparator { item1, item2 ->
item1.pojo.translation.toLowerCase().compareTo(item2.pojo.translation.toLowerCase()) }) item1.pojo.translation.toLowerCase().compareTo(item2.pojo.translation.toLowerCase()) })
} }
companion object {
private val TAG = "VN/" + Vocabulary::class.java.simpleName
const val SORT_BY_TIME = 0
const val SORT_BY_WORD = 1
const val SORT_BY_TRANSLATION = 2
}
} }
\ No newline at end of file
...@@ -9,11 +9,11 @@ import android.view.* ...@@ -9,11 +9,11 @@ import android.view.*
import com.paktalin.vocabularynotebook.firestoreitems.WordItem import com.paktalin.vocabularynotebook.firestoreitems.WordItem
import com.paktalin.vocabularynotebook.ui.fragments.EditWordFragment import com.paktalin.vocabularynotebook.ui.fragments.EditWordFragment
import com.paktalin.vocabularynotebook.ui.activities.MainActivity import com.paktalin.vocabularynotebook.ui.activities.MainActivity
import com.paktalin.vocabularynotebook.utils.Log
import com.paktalin.vocabularynotebook.utils.addFragment import com.paktalin.vocabularynotebook.utils.addFragment
class VocabularyAdapter(private val fullVocabulary: Vocabulary, private val mainActivity: MainActivity) : RecyclerView.Adapter<ViewHolder>() { class VocabularyAdapter(private val vocabulary: Vocabulary, private val mainActivity: MainActivity) : RecyclerView.Adapter<ViewHolder>() {
private var displayedVocabulary = Vocabulary(fullVocabulary)
private lateinit var recyclerView: RecyclerView private lateinit var recyclerView: RecyclerView
var sortOrder: Int = 0 var sortOrder: Int = 0
...@@ -33,11 +33,11 @@ class VocabularyAdapter(private val fullVocabulary: Vocabulary, private val main ...@@ -33,11 +33,11 @@ class VocabularyAdapter(private val fullVocabulary: Vocabulary, private val main
} }
override fun getItemCount(): Int { override fun getItemCount(): Int {
return displayedVocabulary.size() return vocabulary.displayedSize()
} }
override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) { override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
val wordItem = displayedVocabulary.getAt(position) val wordItem = vocabulary.displayedAt(position)
viewHolder.init(wordItem, position) { view, p -> showPopupMenu(view, p)} viewHolder.init(wordItem, position) { view, p -> showPopupMenu(view, p)}
//todo set click listener to menu //todo set click listener to menu
} }
...@@ -46,8 +46,8 @@ class VocabularyAdapter(private val fullVocabulary: Vocabulary, private val main ...@@ -46,8 +46,8 @@ class VocabularyAdapter(private val fullVocabulary: Vocabulary, private val main
val popup = PopupMenu(mainActivity, v) val popup = PopupMenu(mainActivity, v)
popup.menuInflater.inflate(R.menu.word_item_menu, popup.menu) popup.menuInflater.inflate(R.menu.word_item_menu, popup.menu)
popup.setOnMenuItemClickListener { popup.setOnMenuItemClickListener {
if (it.itemId == R.id.option_delete) { deleteWord(position) } if (it.itemId == R.id.option_delete) { deleteWord(vocabulary.displayedAt(position), position) }
if (it.itemId == R.id.option_edit) { startEditFragment(v, displayedVocabulary.getAt(position)) } if (it.itemId == R.id.option_edit) { startEditFragment(v, vocabulary.displayedAt(position)) }
true true
} }
// if not edit mode, then start EditFragment // if not edit mode, then start EditFragment
...@@ -63,28 +63,26 @@ class VocabularyAdapter(private val fullVocabulary: Vocabulary, private val main ...@@ -63,28 +63,26 @@ class VocabularyAdapter(private val fullVocabulary: Vocabulary, private val main
}*/ }*/
} }
private fun deleteWord(position: Int) { private fun deleteWord(wordItem: WordItem, position: Int) {
//TODO delete from fullVocabulary vocabulary.deleteWord(wordItem)
displayedVocabulary.deleteWord(position)
recyclerView.removeViewAt(position) recyclerView.removeViewAt(position)
this.notifyItemRemoved(position) this.notifyItemRemoved(position)
this.notifyItemRangeChanged(position, displayedVocabulary.size()) this.notifyItemRangeChanged(position, vocabulary.displayedSize())
} }
fun addWord(newWord: WordItem) { fun addWord(newWord: WordItem) {
displayedVocabulary.addWord(newWord) Log.d(TAG, "vocabularyAdapter addWord")
// TODO add word to fullVocabulary vocabulary.addWord(newWord)
this.sort() this.sort()
} }
fun updateWord(updatedWord: WordItem) { fun updateWord(updatedWord: WordItem) {
displayedVocabulary.updateWord(updatedWord) vocabulary.updateWord(updatedWord)
// TODO update word in fullVocabulary
this.sort() this.sort()
} }
private fun sort() { private fun sort() {
displayedVocabulary.sort(sortOrder) vocabulary.sort(sortOrder)
this.notifyDataSetChanged() this.notifyDataSetChanged()
} }
...@@ -102,11 +100,11 @@ class VocabularyAdapter(private val fullVocabulary: Vocabulary, private val main ...@@ -102,11 +100,11 @@ class VocabularyAdapter(private val fullVocabulary: Vocabulary, private val main
} }
fun filter(query: String) { fun filter(query: String) {
displayedVocabulary.clear() vocabulary.clearDisplayed()
if (query.isEmpty()) if (query.isEmpty())
displayedVocabulary.copyWordsFrom(fullVocabulary) vocabulary.displayAll()
else else
displayedVocabulary.addWordsFittingQuery(fullVocabulary, query.toLowerCase()) vocabulary.displayByQuery(query.toLowerCase())
notifyDataSetChanged() notifyDataSetChanged()
} }
......
package com.paktalin.vocabularynotebook.firestoreitems package com.paktalin.vocabularynotebook.firestoreitems
import com.paktalin.vocabularynotebook.utils.FirestoreManager
import java.io.Serializable import java.io.Serializable
import java.util.Date import java.util.Date
class WordItem(word: String, translation: String, time: Date?, var id: String?, private val vocabularyId: String?) : Serializable { class WordItem(word: String, translation: String, time: Date?, var id: String?, private val vocabularyId: String?) : Serializable {
var pojo: Pojo = Pojo(word, translation, time) var pojo: Pojo = Pojo(word, translation, time)
class Pojo(var word: String, var translation: String, var time:Date?) : Serializable { class Pojo(var word: String, var translation: String, var time:Date? = null) : Serializable {
init { init {
if (time == null) time = Date(System.currentTimeMillis()) if (time == null) time = Date(System.currentTimeMillis())
} }
...@@ -18,10 +17,6 @@ class WordItem(word: String, translation: String, time: Date?, var id: String?, ...@@ -18,10 +17,6 @@ class WordItem(word: String, translation: String, time: Date?, var id: String?,
constructor(pojo: Pojo) : this(pojo, null, null) constructor(pojo: Pojo) : this(pojo, null, null)
fun delete() {
FirestoreManager().deleteWord(id!!)
}
fun contains(string:String):Boolean { fun contains(string:String):Boolean {
return pojo.word.toLowerCase().contains(string) || return pojo.word.toLowerCase().contains(string) ||
pojo.translation.toLowerCase().contains(string) pojo.translation.toLowerCase().contains(string)
......
...@@ -89,7 +89,7 @@ class MainActivity : AppCompatActivity() { ...@@ -89,7 +89,7 @@ class MainActivity : AppCompatActivity() {
FirestoreManager().extractVocabulary { documents -> FirestoreManager().extractVocabulary { documents ->
run { run {
if (documents.isNotEmpty()) { if (documents.isNotEmpty()) {
vocabularyAdapter = VocabularyAdapter(Vocabulary(documents), this@MainActivity) vocabularyAdapter = VocabularyAdapter(Vocabulary.createFromDocs(documents), this@MainActivity)
recyclerView.adapter = vocabularyAdapter recyclerView.adapter = vocabularyAdapter
} }
else showToastNoWords() else showToastNoWords()
......
package com.paktalin.vocabularynotebook
import com.paktalin.vocabularynotebook.firestoreitems.WordItem
import org.junit.Assert.*
import org.junit.Test
class VocabularyTest {
@Test
fun constructorTest() {
val wordList = mutableListOf(
WordItem(WordItem.Pojo("ciao", "hi")),
WordItem(WordItem.Pojo("grazie", "thanks")),
WordItem(WordItem.Pojo("prego", "you're welcome")),
WordItem(WordItem.Pojo("per favore", "please")),
WordItem(WordItem.Pojo("bene", "good")))
val vocabulary = Vocabulary(wordList)
assertEquals(wordList[0], vocabulary.displayedAt(0))
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment