Skip to content

Commit

Permalink
Update
Browse files Browse the repository at this point in the history
  • Loading branch information
Recognized committed Dec 7, 2018
1 parent 5d47132 commit 623348a
Show file tree
Hide file tree
Showing 50 changed files with 145 additions and 53 deletions.
Binary file modified .idea/caches/build_file_checksums.ser
Binary file not shown.
2 changes: 1 addition & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ android {
compileSdkVersion 26
defaultConfig {
applicationId "vladsaif.gitcards"
minSdkVersion 26
minSdkVersion 17
targetSdkVersion 26
versionCode 1
versionName "1.0"
Expand Down
83 changes: 71 additions & 12 deletions app/src/main/kotlin/vladsaif/gitcards/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package vladsaif.gitcards

import android.annotation.SuppressLint
import android.content.Context
import android.content.SharedPreferences
import android.graphics.Color
import android.os.Bundle
import android.support.v7.app.AlertDialog
Expand All @@ -16,6 +15,7 @@ import android.widget.*
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.lb.auto_fit_textview.AutoResizeTextView
import io.ktor.http.Url
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.actor
import java.util.concurrent.TimeUnit.*
Expand All @@ -30,14 +30,23 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
@ObsoleteCoroutinesApi
private val syncActor = actor<Unit>(Dispatchers.IO) {
for (x in channel) {
val cards = fetchCards()
val hasCardsBefore = CardsHolder.hasCards
CardsHolder.loadCards(cards)
withContext(Dispatchers.Main) {
Toast.makeText(applicationContext, "Loaded cards: ${cards.size}", Toast.LENGTH_LONG).show()
if (!hasCardsBefore && CardsHolder.hasCards) {
buttonsFrame.visibility = View.VISIBLE
cardsCarousel.next()
try {
val url = withContext(Dispatchers.Main) {
getPreferences(Context.MODE_PRIVATE).getString(
"url", "https://raw.githubusercontent.com/Recognized/GitCards/master/cards.json"
)
}
val cards = fetchCards(url)
CardsHolder.loadCards(cards)
withContext(Dispatchers.Main) {
Toast.makeText(applicationContext, "Loaded cards: ${cards.size}", Toast.LENGTH_LONG).show()
if (CardsHolder.hasCards && currentCard == null) {
startShowing()
}
}
} catch (ex: Throwable) {
withContext(Dispatchers.Main) {
Toast.makeText(applicationContext, "Try sync again", Toast.LENGTH_LONG).show()
}
}
}
Expand Down Expand Up @@ -135,9 +144,14 @@ class MainActivity : AppCompatActivity(), CoroutineScope {

private fun startShowing() {
if (CardsHolder.hasCards) {
frontFrame.removeAllViews()
backFrame.removeAllViews()
buttonsFrame.visibility = View.VISIBLE
val old = currentCard
cardsCarousel.next()
if (old == currentCard) {
cardsCarousel.next()
}
} else {
setNoCardsAvailableState()
}
Expand Down Expand Up @@ -186,6 +200,41 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
syncActor.offer(Unit)
}

private fun setUrl() {
val builder = AlertDialog.Builder(this)
builder.setTitle("Set data url")
val view = LayoutInflater.from(this).inflate(R.layout.set_url, null)
builder.setView(view)
val input by lazy { view.findViewById<AppCompatEditText>(R.id.urlInput) }

fun CharSequence.validate(): Boolean {
return try {
Url(this.toString())
true
} catch (ex: Throwable) {
false
}
}
input.setText(getPreferences(Context.MODE_PRIVATE).getString(
"url", "https://raw.githubusercontent.com/Recognized/GitCards/master/cards.json"
))
builder.setPositiveButton("Add") { dialog, _ ->
if (input.text.validate()) {
dialog.dismiss()
with(getPreferences(Context.MODE_PRIVATE).edit()) {
putString("url", input.text.toString())
apply()
}
} else {
Toast.makeText(this, "Input must be valid url", Toast.LENGTH_LONG).show()
}
}
builder.setNegativeButton("Cancel") { dialog, _ ->
dialog.cancel()
}
builder.show()
}

private fun onBadClick() {
onMemoryButtonClick(MemoryStrength.BAD)
}
Expand Down Expand Up @@ -233,18 +282,27 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
val inputBack by lazy { view.findViewById<AppCompatEditText>(R.id.inputBack) }

fun CharSequence.validate(): Boolean {
return this.isNotBlank() && this.isNotEmpty()
return this@validate.isNotBlank() && this@validate.isNotEmpty()
}
builder.setPositiveButton("Add") { dialog, _ ->
if (inputFront.text.validate() && inputBack.text.validate()) {
dialog.dismiss()
with(getPreferences(Context.MODE_PRIVATE)) {
var id = getInt("id", -1)
CardsHolder.loadCards(listOf(TextCard(--id, inputFront.text.trim().toString(), inputBack.text.trim().toString())))
CardsHolder.loadCards(
listOf(
TextCard(
--id,
inputFront.text.trim().toString(),
inputBack.text.trim().toString()
)
)
)
with(edit()) {
putInt("id", id)
apply()
}
startShowing()
}

} else {
Expand All @@ -258,6 +316,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
}

private fun removeCard() {
if (currentCard == null) return
CardsHolder.removeCard(currentCard!!)
if (!CardsHolder.hasCards) {
currentCard = null
Expand All @@ -275,7 +334,6 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
val inflater = menuInflater
inflater.inflate(R.menu.main_menu, menu)
removeCardItem = menu.findItem(R.id.remove_card)
removeCardItem.isEnabled = currentCard != null
return true
}

Expand All @@ -286,6 +344,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
R.id.sync -> sync()
R.id.add_card -> addCard()
R.id.remove_card -> removeCard()
R.id.url -> setUrl()
else -> return super.onOptionsItemSelected(item)
}
return true
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 0 additions & 10 deletions app/src/main/res/drawable/baseline_add_24.xml

This file was deleted.

10 changes: 0 additions & 10 deletions app/src/main/res/drawable/baseline_delete_24.xml

This file was deleted.

15 changes: 15 additions & 0 deletions app/src/main/res/layout/set_url.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?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="wrap_content"
android:orientation="vertical"
android:padding="5dp"
android:theme="@style/Theme.AppCompat.Light.NoActionBar">

<android.support.v7.widget.AppCompatEditText
android:id="@+id/urlInput"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="text"
android:hint="Data URL"/>
</LinearLayout>
17 changes: 11 additions & 6 deletions app/src/main/res/menu/main_menu.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,20 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="vladsaif.gitcards.MainActivity">
<item android:id="@+id/add_card"
android:icon="@drawable/baseline_add_white_48"
app:showAsAction="ifRoom"
android:title="Add"/>
<item android:id="@+id/remove_card"
android:icon="@drawable/baseline_delete_white_48"
app:showAsAction="ifRoom"
app:showAsAction="always"
android:title="Remove"/>
<item android:id="@+id/url"
android:title="URL"
android:icon="@drawable/baseline_insert_link_white_48"
app:showAsAction="always"/>
<item android:id="@+id/sync"
android:title="Sync"
app:showAsAction="ifRoom|withText"/>
android:icon="@drawable/baseline_sync_white_48"
app:showAsAction="always"/>
<item android:id="@+id/add_card"
android:icon="@drawable/baseline_add_white_48"
app:showAsAction="always"
android:title="Add"/>
</menu>
56 changes: 44 additions & 12 deletions console/src/main/kotlin/vladsaif/gitcards/Card.kt
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ sealed class Card(val id: Int) {

class TextCard(id: Int, val frontText: String, val backText: String) : Card(id)

suspend fun fetchCards(): List<Card> {
suspend fun fetchCards(url: String): List<Card> {
val call = HttpClient(Android).use { client ->
client.call("https://raw.githubusercontent.com/Recognized/GitCards/master/cards.json") {
client.call(url) {
method = HttpMethod.Get
}
}
Expand Down Expand Up @@ -86,32 +86,55 @@ class PrioritizedCard(val card: Card) : Comparable<PrioritizedCard> {

fun toDescriptor() = Descriptor(this)

override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is PrioritizedCard) return false

if (card != other.card) return false

return true
}

override fun hashCode(): Int {
return card.hashCode()
}

companion object {
const val DEFAULT_PRIORITY = 1 shl 16
val COMPARATOR = kotlin.Comparator<PrioritizedCard> { a, b -> a.priority - b.priority }
val COMPARATOR = kotlin.Comparator<PrioritizedCard> { a, b ->
if (a.card.id == b.card.id) return@Comparator 0
val res = b.priority - a.priority
if (res != 0) res else a.card.id - b.card.id
}
}
}

object CardsHolder {
private val cardLock = ReentrantLock()
private val allCards = mutableSetOf<PrioritizedCard>()
private var cardsQueue = PriorityQueue<PrioritizedCard>(PrioritizedCard.COMPARATOR.reversed())
private val removed = mutableSetOf<PrioritizedCard>()
private var cardsQueue = TreeSet<PrioritizedCard>(PrioritizedCard.COMPARATOR)

val cards = sequence {
if (cardLock.withLock { cardsQueue.isEmpty() }) return@sequence
while (true) {
val card = cardLock.withLock {
cardsQueue.poll()
val first = cardsQueue.first()
cardsQueue.remove(first)
first
}
yield(card)
cardLock.withLock {
cardsQueue.add(card)
if (!removed.remove(card)) {
cardsQueue.add(card)
}
}
}
}

fun removeCard(card: PrioritizedCard) {
cardLock.withLock {
removed.add(card)
allCards.remove(card)
cardsQueue.remove(card)
}
Expand All @@ -120,7 +143,13 @@ object CardsHolder {
fun loadCards(newCards: List<Card>) {
val newQueue = newCards.map { PrioritizedCard(it) }.toMutableSet()
cardLock.withLock {
newQueue.removeIf { it in allCards }
val iter = newQueue.iterator()
while (iter.hasNext()) {
val elem = iter.next()
if (elem in allCards) {
iter.remove()
}
}
allCards.addAll(newQueue)
cardsQueue.addAll(newQueue)
}
Expand All @@ -129,12 +158,15 @@ object CardsHolder {
fun loadPrioritizedCards(newCards: List<PrioritizedCard>) {
val set = newCards.toMutableSet()
cardLock.withLock {
for (x in set) {
allCards.removeIf { it in set }
allCards.addAll(set)
cardsQueue.clear()
cardsQueue.addAll(allCards)
val iter = allCards.iterator()
while (iter.hasNext()) {
if (iter.next() in set) {
iter.remove()
}
}
allCards.addAll(set)
cardsQueue.clear()
cardsQueue.addAll(allCards)
}
}

Expand Down
3 changes: 2 additions & 1 deletion words.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ acknowledge=выразить признательность
deceptive=обманчивый
stake=stick used as support
good riddance to them=скатертью дорога
commute=заменить
commute=заменить
coax=persuade

0 comments on commit 623348a

Please sign in to comment.