diff --git a/app/build.gradle b/app/build.gradle index 1aeab34..5555a36 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -38,12 +38,6 @@ android { println(e.message) } } - release { - storeFile file('debug.keystore') - keyAlias 'androiddebugkey' - keyPassword 'android' - storePassword 'android' - } } buildTypes { debug { diff --git a/app/src/main/kotlin/com/ediposouza/teslesgendstracker/data/Deck.kt b/app/src/main/kotlin/com/ediposouza/teslesgendstracker/data/Deck.kt index 6d0011e..ae37a47 100644 --- a/app/src/main/kotlin/com/ediposouza/teslesgendstracker/data/Deck.kt +++ b/app/src/main/kotlin/com/ediposouza/teslesgendstracker/data/Deck.kt @@ -28,6 +28,10 @@ enum class DeckClass(val attr1: CardAttribute, val attr2: CardAttribute = CardAt companion object { + fun getClass(attr1: CardAttribute, attr2: CardAttribute): DeckClass { + return getClasses(listOf(attr1, attr2)).first() + } + fun getClasses(attr: List): List { return values().filter { attr.contains(it.attr1) && attr.contains(it.attr2) } } @@ -43,8 +47,16 @@ enum class DeckType { COMBO, CONTROL, MIDRANGE, - OTHER + OTHER; + + companion object { + fun of(value: String): DeckType { + val name = value.toUpperCase() + return OTHER.takeUnless { values().map { it.name }.contains(name) } ?: valueOf(name) + } + + } } data class DeckUpdate( diff --git a/app/src/main/kotlin/com/ediposouza/teslesgendstracker/data/Patch.kt b/app/src/main/kotlin/com/ediposouza/teslesgendstracker/data/Patch.kt index 7b5056c..2ce93a5 100644 --- a/app/src/main/kotlin/com/ediposouza/teslesgendstracker/data/Patch.kt +++ b/app/src/main/kotlin/com/ediposouza/teslesgendstracker/data/Patch.kt @@ -73,6 +73,7 @@ data class Patch( val uuidDate: String, val date: LocalDate, val desc: String, + val legendsDeck: String, val type: PatchType, val changes: List @@ -86,13 +87,14 @@ data class Patch( } constructor(source: Parcel) : this(source.readString(), LocalDate.ofEpochDay(source.readLong()), - source.readString(), PatchType.values()[source.readInt()], + source.readString(), source.readString(), PatchType.values()[source.readInt()], mutableListOf().apply { source.readList(this, PatchChange::class.java.classLoader) }) override fun writeToParcel(dest: Parcel?, flags: Int) { dest?.writeString(uuidDate) dest?.writeLong(date.toEpochDay()) dest?.writeString(desc) + dest?.writeString(legendsDeck) dest?.writeInt(type.ordinal) dest?.writeList(changes) } diff --git a/app/src/main/kotlin/com/ediposouza/teslesgendstracker/interactor/FirebaseParsers.kt b/app/src/main/kotlin/com/ediposouza/teslesgendstracker/interactor/FirebaseParsers.kt index 5989624..3313699 100644 --- a/app/src/main/kotlin/com/ediposouza/teslesgendstracker/interactor/FirebaseParsers.kt +++ b/app/src/main/kotlin/com/ediposouza/teslesgendstracker/interactor/FirebaseParsers.kt @@ -163,6 +163,7 @@ abstract class FirebaseParsers { val changes: Map> = mapOf() val desc: String = "" + val legendsDeck: String = "" val type: String = "" @Suppress("UNCHECKED_CAST") @@ -174,7 +175,7 @@ abstract class FirebaseParsers { val change = it.value[KEY_PATCH_CHANGE].toString() PatchChange(attr, set, it.key, change) } - return Patch(uuidDate, date, desc, PatchType.of(type), patchCardChanges) + return Patch(uuidDate, date, desc, legendsDeck, PatchType.of(type), patchCardChanges) } } diff --git a/app/src/main/kotlin/com/ediposouza/teslesgendstracker/ui/base/Commands.kt b/app/src/main/kotlin/com/ediposouza/teslesgendstracker/ui/base/Commands.kt index 313ea14..afd8399 100644 --- a/app/src/main/kotlin/com/ediposouza/teslesgendstracker/ui/base/Commands.kt +++ b/app/src/main/kotlin/com/ediposouza/teslesgendstracker/ui/base/Commands.kt @@ -22,7 +22,7 @@ data class CmdUpdateTitle(@IntegerRes val title: Int) data class CmdShowCardsByAttr(val attr: CardAttribute) -data class CmdShowDecksByClasses(val classes: List) +data class CmdShowDecksByClasses(val classes: List?) data class CmdUpdateRarityMagikaFiltersPosition(val high: Boolean) diff --git a/app/src/main/kotlin/com/ediposouza/teslesgendstracker/ui/cards/CardActivity.kt b/app/src/main/kotlin/com/ediposouza/teslesgendstracker/ui/cards/CardActivity.kt index e939f2f..4d2cd8d 100644 --- a/app/src/main/kotlin/com/ediposouza/teslesgendstracker/ui/cards/CardActivity.kt +++ b/app/src/main/kotlin/com/ediposouza/teslesgendstracker/ui/cards/CardActivity.kt @@ -3,6 +3,7 @@ package com.ediposouza.teslesgendstracker.ui.cards import android.app.Activity import android.content.Context import android.content.Intent +import android.os.Build import android.os.Bundle import android.support.design.widget.BottomSheetBehavior import android.support.v4.app.ActivityCompat @@ -12,6 +13,7 @@ import android.support.v7.widget.LinearLayoutManager import android.support.v7.widget.LinearSnapHelper import android.support.v7.widget.RecyclerView import android.text.format.DateUtils +import android.transition.Transition import android.view.View import android.view.ViewGroup import android.view.ViewTreeObserver @@ -82,9 +84,38 @@ class CardActivity : BaseActivity() { override fun onPostCreate(savedInstanceState: Bundle?) { super.onPostCreate(savedInstanceState) + card_ads_view.load() + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + window.sharedElementEnterTransition?.apply { + addListener(object : Transition.TransitionListener { + override fun onTransitionEnd(transition: Transition?) { + removeListener(this) + configQtdAndFavoriteInfo() + } + + override fun onTransitionResume(transition: Transition?) { + } + + override fun onTransitionPause(transition: Transition?) { + } + + override fun onTransitionCancel(transition: Transition?) { + removeListener(this) + } + + override fun onTransitionStart(transition: Transition?) { + } + + }) + } + } else { + configQtdAndFavoriteInfo() + } MetricsManager.trackScreen(MetricScreen.SCREEN_CARD_DETAILS()) MetricsManager.trackCardView(card) - card_ads_view.load() + } + + private fun configQtdAndFavoriteInfo() { if (App.hasUserLogged()) { showUserCardQtd() } diff --git a/app/src/main/kotlin/com/ediposouza/teslesgendstracker/ui/cards/tabs/CardsCollectionFragment.kt b/app/src/main/kotlin/com/ediposouza/teslesgendstracker/ui/cards/tabs/CardsCollectionFragment.kt index 1224160..3b986a8 100644 --- a/app/src/main/kotlin/com/ediposouza/teslesgendstracker/ui/cards/tabs/CardsCollectionFragment.kt +++ b/app/src/main/kotlin/com/ediposouza/teslesgendstracker/ui/cards/tabs/CardsCollectionFragment.kt @@ -40,8 +40,8 @@ import kotlinx.android.synthetic.main.itemlist_card_collection.view.* import kotlinx.android.synthetic.main.itemlist_card_imported.view.* import org.jetbrains.anko.doAsync import org.jetbrains.anko.find -import org.jetbrains.anko.runOnUiThread import org.jetbrains.anko.toast +import org.jetbrains.anko.uiThread import org.jsoup.Jsoup import timber.log.Timber import java.util.* @@ -172,7 +172,7 @@ class CardsCollectionFragment : CardsAllFragment() { loadUrl("javascript:HtmlViewer.showHTML" + "(''+document.getElementsByTagName('html')[0].innerHTML+'');") } - if (url == getString(R.string.dialog_import_legends_deck_login_done_link)) { + if (url == getString(R.string.dialog_import_legends_deck_main_link)) { loadUrl(getString(R.string.dialog_import_legends_deck_link)) } } @@ -239,7 +239,7 @@ class CardsCollectionFragment : CardsAllFragment() { val cardName = it.select(".td_title_card_collection").text() val cardQtd = it.select(".td_total_card_collection").text().toInt() val cardShortName = cardName.replace(" ", "").replace("-", "") - .replace("'", "").replace(",", "").toLowerCase().toLowerCase() + .replace("'", "").replace(",", "").toLowerCase() cardShortName to cardQtd }?.filter { it.second > 0 }?.toMap() ?: mapOf() if (legendsSlots.isNotEmpty()) { @@ -249,38 +249,40 @@ class CardsCollectionFragment : CardsAllFragment() { } private fun importLegendDecksCards(legendsSlots: Map) { - PublicInteractor.getCards(null) { allCards -> - val legendsDecksCards = allCards.filter { legendsSlots.keys.contains(it.shortName) }.toMutableList() - PrivateInteractor.getUserCollection(null) { userSlots -> - val userCards = allCards.filter { userSlots.keys.contains(it.shortName) }.toMutableList() - val onlyInLegendsDecks = legendsDecksCards.filter { !userSlots.keys.contains(it.shortName) } - val onlyInUserCollection = userCards.filter { !legendsSlots.keys.contains(it.shortName) } - val cardsInCommon = userCards.filter { legendsSlots.keys.contains(it.shortName) } - val userQtdGreater = cardsInCommon.filter { - userSlots[it.shortName] ?: 0 > legendsSlots[it.shortName] ?: 0 - } - val legendsQtdGreater = cardsInCommon.filter { - legendsSlots[it.shortName] ?: 0 > userSlots[it.shortName] ?: 0 - } - onlyInLegendsDecks.forEach { - val qtd = legendsSlots[it.shortName] ?: 0 - PrivateInteractor.setUserCardQtd(it, qtd) { - Timber.d("$qtd ${it.name} card added") + doAsync { + PublicInteractor.getCards(null) { allCards -> + val legendsDecksCards = allCards.filter { legendsSlots.keys.contains(it.shortName) }.toMutableList() + PrivateInteractor.getUserCollection(null) { userSlots -> + val userCards = allCards.filter { userSlots.keys.contains(it.shortName) }.toMutableList() + val onlyInLegendsDecks = legendsDecksCards.filter { !userSlots.keys.contains(it.shortName) } + val onlyInUserCollection = userCards.filter { !legendsSlots.keys.contains(it.shortName) } + val cardsInCommon = userCards.filter { legendsSlots.keys.contains(it.shortName) } + val userQtdGreater = cardsInCommon.filter { + userSlots[it.shortName] ?: 0 > legendsSlots[it.shortName] ?: 0 } - } - legendsQtdGreater.forEach { - val qtd = legendsSlots[it.shortName] ?: 0 - PrivateInteractor.setUserCardQtd(it, qtd) { - Timber.d("${it.name} qtd updated to $qtd") + val legendsQtdGreater = cardsInCommon.filter { + legendsSlots[it.shortName] ?: 0 > userSlots[it.shortName] ?: 0 + } + onlyInLegendsDecks.forEach { + val qtd = legendsSlots[it.shortName] ?: 0 + PrivateInteractor.setUserCardQtd(it, qtd) { + Timber.d("$qtd ${it.name} card added") + } + } + legendsQtdGreater.forEach { + val qtd = legendsSlots[it.shortName] ?: 0 + PrivateInteractor.setUserCardQtd(it, qtd) { + Timber.d("${it.name} qtd updated to $qtd") + } } + showImportSummary(onlyInLegendsDecks, onlyInUserCollection, legendsQtdGreater, + userQtdGreater, legendsSlots, userSlots) } - showImportSummary(onlyInLegendsDecks, onlyInUserCollection, legendsQtdGreater, - userQtdGreater, legendsSlots, userSlots) } - } - context.runOnUiThread { - context.toast("Collection imported!") - importDialog?.dismiss() + uiThread { + context.toast("Collection imported!") + importDialog?.dismiss() + } } } diff --git a/app/src/main/kotlin/com/ediposouza/teslesgendstracker/ui/decks/DeckActivity.kt b/app/src/main/kotlin/com/ediposouza/teslesgendstracker/ui/decks/DeckActivity.kt index b198e1e..fa85514 100644 --- a/app/src/main/kotlin/com/ediposouza/teslesgendstracker/ui/decks/DeckActivity.kt +++ b/app/src/main/kotlin/com/ediposouza/teslesgendstracker/ui/decks/DeckActivity.kt @@ -375,8 +375,10 @@ class DeckActivity : BaseActivity() { fun calculateMissingSoul(deck: Deck) { with(deck_details_soul_missing) { - visibility = View.INVISIBLE - deck_details_soul_missing_loading.visibility = View.VISIBLE + runOnUiThread { + visibility = View.INVISIBLE + deck_details_soul_missing_loading.visibility = View.VISIBLE + } PrivateInteractor.getDeckMissingCards(deck, { deck_details_soul_missing_loading.visibility = View.VISIBLE }) { deck_details_soul_missing_loading.visibility = View.GONE val missingSoul = it.map { it.qtd * it.rarity.soulCost }.sum() diff --git a/app/src/main/kotlin/com/ediposouza/teslesgendstracker/ui/decks/DecksFragment.kt b/app/src/main/kotlin/com/ediposouza/teslesgendstracker/ui/decks/DecksFragment.kt index 38a4489..02cbe94 100644 --- a/app/src/main/kotlin/com/ediposouza/teslesgendstracker/ui/decks/DecksFragment.kt +++ b/app/src/main/kotlin/com/ediposouza/teslesgendstracker/ui/decks/DecksFragment.kt @@ -3,6 +3,7 @@ package com.ediposouza.teslesgendstracker.ui.decks import android.app.Activity import android.content.Context import android.content.Intent +import android.graphics.Bitmap import android.os.Bundle import android.os.Handler import android.support.v4.app.ActivityOptionsCompat @@ -10,24 +11,38 @@ import android.support.v4.app.FragmentManager import android.support.v4.app.FragmentStatePagerAdapter import android.support.v4.view.MenuItemCompat import android.support.v4.view.ViewPager +import android.support.v7.app.AlertDialog import android.support.v7.widget.SearchView import android.text.format.DateUtils import android.view.* import android.view.inputmethod.InputMethodManager +import android.webkit.JavascriptInterface +import android.webkit.WebView +import android.webkit.WebViewClient +import com.ediposouza.teslesgendstracker.App import com.ediposouza.teslesgendstracker.R +import com.ediposouza.teslesgendstracker.data.CardAttribute +import com.ediposouza.teslesgendstracker.data.Deck import com.ediposouza.teslesgendstracker.data.DeckClass +import com.ediposouza.teslesgendstracker.data.DeckType +import com.ediposouza.teslesgendstracker.interactor.PrivateInteractor +import com.ediposouza.teslesgendstracker.interactor.PublicInteractor import com.ediposouza.teslesgendstracker.ui.base.* import com.ediposouza.teslesgendstracker.ui.cards.CmdFilterSearch import com.ediposouza.teslesgendstracker.ui.decks.tabs.DecksFavoritedFragment import com.ediposouza.teslesgendstracker.ui.decks.tabs.DecksOwnerFragment import com.ediposouza.teslesgendstracker.ui.decks.tabs.DecksPublicFragment +import com.ediposouza.teslesgendstracker.util.MetricAction import com.ediposouza.teslesgendstracker.util.MetricScreen import com.ediposouza.teslesgendstracker.util.MetricsManager import com.ediposouza.teslesgendstracker.util.inflate import kotlinx.android.synthetic.main.activity_dash.* +import kotlinx.android.synthetic.main.dialog_import.view.* import kotlinx.android.synthetic.main.fragment_decks.* import org.greenrobot.eventbus.Subscribe -import org.jetbrains.anko.intentFor +import org.jetbrains.anko.* +import org.jsoup.Jsoup +import timber.log.Timber /** * Created by EdipoSouza on 11/12/16. @@ -53,6 +68,11 @@ class DecksFragment : BaseFragment(), SearchView.OnQueryTextListener { } + private var importDialog: AlertDialog? = null + private var importDialogWebView: WebView? = null + private var userDecks: List = listOf() + private var userDecksImported = 0 + private fun updateActivityTitle(position: Int) { val title = CmdUpdateTitle(when (position) { 1 -> R.string.title_tab_decks_owned @@ -115,6 +135,7 @@ class DecksFragment : BaseFragment(), SearchView.OnQueryTextListener { override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) { menu?.clear() + inflater?.inflate(R.menu.menu_import, menu) inflater?.inflate(R.menu.menu_search, menu) val actionView = MenuItemCompat.getActionView(menu?.findItem(R.id.menu_search)) if (actionView is SearchView) { @@ -126,6 +147,22 @@ class DecksFragment : BaseFragment(), SearchView.OnQueryTextListener { super.onCreateOptionsMenu(menu, inflater) } + override fun onOptionsItemSelected(item: MenuItem?): Boolean { + if (item?.itemId == R.id.menu_import) { + if (App.hasUserLogged()) { + PrivateInteractor.getUserDecks(null) { + userDecks = it + userDecksImported = 0 + showImportDialog() + } + }else{ + eventBus.post(CmdShowSnackbarMsg(CmdShowSnackbarMsg.TYPE_ERROR, R.string.error_auth)) + } + return true + } + return super.onOptionsItemSelected(item) + } + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (requestCode == RC_NEW_DECK && resultCode == Activity.RESULT_OK) { @@ -157,29 +194,207 @@ class DecksFragment : BaseFragment(), SearchView.OnQueryTextListener { } } - class DecksPageAdapter(ctx: Context, fm: FragmentManager) : FragmentStatePagerAdapter(fm) { + private fun showImportDialog() { + val dialogView = View.inflate(context, R.layout.dialog_import, null) + dialogView.import_dialog_text.text = getString(R.string.dialog_import_deck_text) + importDialog = AlertDialog.Builder(context, R.style.AppDialog) + .setView(dialogView) + .setNegativeButton(android.R.string.cancel, { _, _ -> + dialogView.import_dialog_webview.stopLoading() + MetricsManager.trackAction(MetricAction.ACTION_IMPORT_DECKS_CANCELLED()) + }) + .create() + importDialog?.setOnShowListener { + dialogView.import_dialog_webview?.apply { + importDialogWebView = this + settings.javaScriptEnabled = true + addJavascriptInterface(HTMLViewerInterface(), "HtmlViewer") + loadUrl(getString(R.string.dialog_import_legends_deck_main_link)) + setWebViewClient(object : WebViewClient() { + override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) { + Timber.d("onPageStarted: $url") + val isMyDecksPage = url?.endsWith("/decks") ?: false + settings.loadsImagesAutomatically = !isMyDecksPage + dialogView.import_dialog_loading.visibility = View.VISIBLE.takeIf { isMyDecksPage } ?: View.GONE + with(dialogView.import_dialog_webview) { + layoutParams = layoutParams.apply { + height = 1.takeIf { isMyDecksPage } ?: ViewGroup.LayoutParams.WRAP_CONTENT + } + } + } - var titles: Array = ctx.resources.getStringArray(R.array.decks_tabs) - val decksPublicFragment by lazy { DecksPublicFragment() } - val decksMyFragment by lazy { DecksOwnerFragment() } - val decksSavedFragment by lazy { DecksFavoritedFragment() } + override fun onPageFinished(view: WebView?, url: String?) { + Timber.d("onPageFinished: $url") + if (url?.endsWith("/decks") ?: false) { + loadUrl("javascript:HtmlViewer.showHTML" + + "(''+document.getElementsByTagName('html')[0].innerHTML+'');") + } + if (url == getString(R.string.dialog_import_legends_deck_main_link)) { + loadUrl("javascript:HtmlViewer.showHTMLandCheckLogged" + + "(''+document.getElementsByTagName('html')[0].innerHTML+'');") + } + } + }) + } + } + importDialog?.show() + importDialog?.window?.clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) + importDialog?.window?.clearFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM) + importDialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE) + MetricsManager.trackScreen(MetricScreen.SCREEN_IMPORT_DECKS()) + } - override fun getItem(position: Int): BaseFragment { - return when (position) { - 1 -> decksMyFragment - 2 -> decksSavedFragment - else -> decksPublicFragment + inner class HTMLViewerInterface { + + var decksLinkRemains = listOf() + + @Suppress("unused") + @JavascriptInterface + fun showHTML(html: String) { + doAsync { + try { + val decksLink = Jsoup.parse(html).select(".table_large tr .td_name_deck_full")?.map { + it.child(0).attr("href") + } ?: listOf() + if (decksLink.isNotEmpty()) { + Timber.d("MyDecksLinks: $decksLink") + uiThread { + importLegendDecks(decksLink) + } + } + } catch (e: Exception) { + Timber.e(e) + } } } - override fun getCount(): Int { - return titles.size + @Suppress("unused") + @JavascriptInterface + fun showHTMLandCheckLogged(html: String) { + doAsync { + val baseProfileLink = getString(R.string.dialog_import_legends_deck_profile_base_link) + val profileLink = Jsoup.parse(html).select(".dropdown-menu li a")?.get(1)?.attr("href") + if (profileLink?.contains(baseProfileLink) ?: false) { + val userID = profileLink?.replace(baseProfileLink, "") ?: "" + Timber.d("UserID: $userID") + if (userID.isNotEmpty()) { + uiThread { + importDialogWebView?.loadUrl("$baseProfileLink$userID/decks") + } + } + } + } + } + + @Suppress("unused") + @JavascriptInterface + fun showDeckHTML(html: String) { + doAsync { + PublicInteractor.getPatches { patches -> + Jsoup.parse(html).select(".wrapper .container")?.map { + val deckName = it.select(".col-lg-8 h1").first().text() + val deckCls = it.select(".deck_head_image_attributes").map { + val cardCls1 = it.child(0).attr("alt").toUpperCase() + val cardCls2 = it.child(1).attr("alt").toUpperCase() + DeckClass.getClass(CardAttribute.valueOf(cardCls1), CardAttribute.valueOf(cardCls2)) + }.first() + val deckType = DeckType.of(with(it.select(".panel-body .center").first().text()) { + substring(indexOfLast { it == ' ' } + 1).replace("-", "") + }) + var deckCost = 0 + var deckPatchName = "" + with(it.select(".inner_deck_head b").map { it.text() }) { + val craftingCostIndexOf = indexOf("Crafting Cost:") + deckCost = get(craftingCostIndexOf + 1).toInt() + deckPatchName = with(get(craftingCostIndexOf - 1)) { + substring(indexOfFirst { it == '(' } + 1, indexOfFirst { it == ')' }) + } + } + val deckPatch = patches.find { it.legendsDeck == deckPatchName } ?: patches.last() + val deckCards = it.select("#deck .card_deck")?.map { + val text = it.text().substring(it.text().indexOfFirst { it == ' ' } + 1) + .replace("-1", "").replace("-2", "").replace("-3", "").trim() + val cardName = text.substring(0, text.indexOfLast { it == ' ' }) + cardName.replace(" ", "").replace("-", "").replace("'", "").replace(",", "").toLowerCase() to + text.substring(text.indexOfLast { it == ' ' } + 1).toInt() + }?.toMap() ?: mapOf() + + Timber.d("Saving Deck: $deckName $deckCls $deckType $deckCost $deckPatch $deckCards") + if(userDecks.find { it.name == deckName } == null){ + PrivateInteractor.saveDeck(deckName, deckCls, deckType, deckCost, deckPatch.uuidDate, + deckCards, false) { + userDecksImported += 1 + Timber.d("$deckName Saved") + uiThread { + loadNextDeckPage(decksLinkRemains) + } + } + }else{ + Timber.d("$deckName is already saved") + uiThread { + loadNextDeckPage(decksLinkRemains) + } + } + } + } + } } - override fun getPageTitle(position: Int): CharSequence { - return titles[position] + private fun importLegendDecks(decksLink: List) { + importDialogWebView?.apply { + settings.loadsImagesAutomatically = false + settings.blockNetworkImage = true + setWebViewClient(object : WebViewClient() { + override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) { + } + + override fun onPageFinished(view: WebView?, url: String?) { + Timber.d("onPageFinished: $url") + loadUrl("javascript:HtmlViewer.showDeckHTML" + + "(''+document.getElementsByTagName('html')[0].innerHTML+'');") + } + }) + } + loadNextDeckPage(decksLink) } + private fun loadNextDeckPage(decksLink: List) { + if (decksLink.isNotEmpty()) { + decksLinkRemains = decksLink.minus(decksLink.first()) + importDialogWebView?.loadUrl(decksLink.first()) + } else { + context.runOnUiThread { + context.toast("$userDecksImported Decks imported!") + importDialog?.dismiss() + } + MetricsManager.trackAction(MetricAction.ACTION_IMPORT_DECKS_FINISH(userDecksImported)) + } + } } } + +class DecksPageAdapter(ctx: Context, fm: FragmentManager) : FragmentStatePagerAdapter(fm) { + + var titles: Array = ctx.resources.getStringArray(R.array.decks_tabs) + val decksPublicFragment by lazy { DecksPublicFragment() } + val decksMyFragment by lazy { DecksOwnerFragment() } + val decksSavedFragment by lazy { DecksFavoritedFragment() } + + override fun getItem(position: Int): BaseFragment { + return when (position) { + 1 -> decksMyFragment + 2 -> decksSavedFragment + else -> decksPublicFragment + } + } + + override fun getCount(): Int { + return titles.size + } + + override fun getPageTitle(position: Int): CharSequence { + return titles[position] + } + +} \ No newline at end of file diff --git a/app/src/main/kotlin/com/ediposouza/teslesgendstracker/ui/decks/tabs/DecksPublicFragment.kt b/app/src/main/kotlin/com/ediposouza/teslesgendstracker/ui/decks/tabs/DecksPublicFragment.kt index cb56ed9..9f04ce3 100644 --- a/app/src/main/kotlin/com/ediposouza/teslesgendstracker/ui/decks/tabs/DecksPublicFragment.kt +++ b/app/src/main/kotlin/com/ediposouza/teslesgendstracker/ui/decks/tabs/DecksPublicFragment.kt @@ -148,7 +148,7 @@ open class DecksPublicFragment : BaseFragment() { @Subscribe @Suppress("unused") fun onCmdShowDecksByClasses(cmdShowDecksByClasses: CmdShowDecksByClasses) { - currentClasses = cmdShowDecksByClasses.classes.toTypedArray() + currentClasses = cmdShowDecksByClasses.classes?.toTypedArray() ?: DeckClass.values() showDecks() if (currentClasses.isEmpty()) { decksAdapter.notifyDataSetChanged() diff --git a/app/src/main/kotlin/com/ediposouza/teslesgendstracker/util/MetricsConstants.kt b/app/src/main/kotlin/com/ediposouza/teslesgendstracker/util/MetricsConstants.kt index 41be1db..28620ba 100644 --- a/app/src/main/kotlin/com/ediposouza/teslesgendstracker/util/MetricsConstants.kt +++ b/app/src/main/kotlin/com/ediposouza/teslesgendstracker/util/MetricsConstants.kt @@ -181,6 +181,10 @@ sealed class MetricAction(val name: String) { val PARAM_CARD = "Card" } + class ACTION_IMPORT_DECKS_CANCELLED : MetricAction("ImportDecksCancelled") + class ACTION_IMPORT_DECKS_FINISH(val decksImported: Int) : MetricAction("ImportDecksFinish") { + val PARAM_DECKS_IMPORTED = "DecksImported" + } } sealed class MetricScreen(val name: String) { @@ -216,5 +220,6 @@ sealed class MetricScreen(val name: String) { class SCREEN_DONATE : MetricScreen("Donate") class SCREEN_ABOUT : MetricScreen("About") class SCREEN_IMPORT_COLLECTION : MetricScreen("ImportCollection") + class SCREEN_IMPORT_DECKS : MetricScreen("ImportDecks") } \ No newline at end of file diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 1b3082e..c7cf2bc 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -59,6 +59,7 @@ Importación desde Legends-Decks Inicie sesión y abra su página de edición de la colección + Inicie sesión y abra su página de mis decks Importación de la colección Tarjetas importadas: Diferencias de colección de Legends-Decks: diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 45c6238..a228255 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -60,6 +60,7 @@ Importar de Legends-Decks Por favor faça login e abra a página de editar coleção + Por favor faça login e abra a página meus decks Importar Coleção Cartas importadas: Diferenças da coleção de Legends-Decks: diff --git a/app/src/main/res/values-v21/dimens.xml b/app/src/main/res/values-v21/dimens.xml new file mode 100644 index 0000000..45a016e --- /dev/null +++ b/app/src/main/res/values-v21/dimens.xml @@ -0,0 +1,19 @@ + + + 25dp + 48dp + + + + 56dp + + + + 36dp + + + + 115dp + + 38dp + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4157aba..fa3b5ca 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -89,6 +89,7 @@ Import from Legends-Decks Please do login and open your collection edit page + Please do login and open my decks page Collection Import Cards imported: Collection differences of Legends-Decks: @@ -97,7 +98,8 @@ YOU HAVE HAS MORE https://www.legends-decks.com/collection-manager - https://www.legends-decks.com/# + https://www.legends-decks.com/# + https://www.legends-decks.com/profile/ Cards Collection diff --git a/app/src/release/java/com/ediposouza/teslesgendstracker/util/MetricsManager.kt b/app/src/release/java/com/ediposouza/teslesgendstracker/util/MetricsManager.kt index 3a3be17..ea677de 100644 --- a/app/src/release/java/com/ediposouza/teslesgendstracker/util/MetricsManager.kt +++ b/app/src/release/java/com/ediposouza/teslesgendstracker/util/MetricsManager.kt @@ -112,6 +112,8 @@ object MetricsManager : MetricsConstants() { } is MetricAction.ACTION_IMPORT_COLLECTION_FINISH -> putInt(action.PARAM_CARDS_IMPORTED, action.cardsImported) + is MetricAction.ACTION_IMPORT_DECKS_FINISH -> + putInt(action.PARAM_DECKS_IMPORTED, action.decksImported) is MetricAction.ACTION_ARTICLES_VIEW_NEWS -> putString(action.PARAM_ARTICLE, action.article.uuidDate) is MetricAction.ACTION_ARTICLES_VIEW_WORLD -> diff --git a/database/dbPatches.json b/database/dbPatches.json index 7f69320..911d3c8 100644 --- a/database/dbPatches.json +++ b/database/dbPatches.json @@ -99,11 +99,13 @@ } }, "desc": "Mantikora Nerf", - "type": "balance" + "type": "balance", + "legendsDeck": "Beta" }, "2016_10_01": { "desc": "Hist Grove", - "type": "reward" + "type": "reward", + "legendsDeck": "HistGrove" }, "2016_11_01": { "desc": "Mechanical Ally", @@ -188,7 +190,8 @@ } }, "desc": "Nahkriin Nerf", - "type": "balance" + "type": "balance", + "legendsDeck": "NahkriinNerf" }, "2016_12_01": { "desc": "Battlereeve Of Dusk", @@ -203,7 +206,8 @@ } }, "desc": "Madhouse Collection", - "type": "set" + "type": "set", + "legendsDeck": "Madhouse" }, "2017_01_01": { "desc": "Elsweyr Lookout", @@ -258,7 +262,8 @@ } }, "desc": "Hist Grove Nerf", - "type": "balance" + "type": "balance", + "legendsDeck": "JanuaryNerf" }, "2017_01_25": { "changes": { @@ -303,6 +308,7 @@ }, "2017_02_01": { "desc": "Stampede Sentinel", - "type": "reward" + "type": "reward", + "legendsDeck": "Patch-1-61" } }