Skip to content

Commit

Permalink
Minor UI tweaks, lib updates, and fetch fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
premnirmal committed Jan 26, 2022
1 parent 40c363c commit c596499
Show file tree
Hide file tree
Showing 9 changed files with 147 additions and 126 deletions.
22 changes: 11 additions & 11 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ android {
debuggable true
versionNameSuffix "-DEBUG"
ext.enableCrashlytics = false
minifyEnabled true
minifyEnabled false
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
}
}
Expand Down Expand Up @@ -159,14 +159,14 @@ android {

ext {
LIFECYCLE_VERSION = "2.4.0"
DAGGER_VERSION = "2.37"
DAGGER_VERSION = "2.40.5"
MOCKITO_VERSION = "3.4.6"
JUNIT_VERSION = "4.13.1"
RETROFIT_VERSION = "2.9.0"
OKHTTP_VERSION = "4.9.0"
ROBOLECTRIC_VERSION = "4.3.1"
COROUTINES_VERSION = "1.5.2"
ROOM_VERSION = "2.4.0"
COROUTINES_VERSION = "1.6.0"
ROOM_VERSION = "2.4.1"
WORK_VERSION = "2.7.1"
}

Expand All @@ -176,14 +176,14 @@ dependencies {
implementation "androidx.core:core-ktx:1.7.0"
implementation "androidx.multidex:multidex:2.0.1"

implementation "androidx.appcompat:appcompat:1.3.1"
implementation "androidx.appcompat:appcompat:1.4.1"
implementation "androidx.legacy:legacy-support-v4:1.0.0"
implementation "com.google.android.material:material:1.4.0"
implementation "com.google.android.material:material:1.5.0"
implementation "androidx.preference:preference-ktx:1.1.1"
implementation "androidx.browser:browser:1.3.0"
implementation "androidx.constraintlayout:constraintlayout:2.1.1"
implementation "androidx.browser:browser:1.4.0"
implementation "androidx.constraintlayout:constraintlayout:2.1.3"
implementation "androidx.viewpager2:viewpager2:1.0.0"
implementation 'androidx.core:core-splashscreen:1.0.0-alpha02'
implementation 'androidx.core:core-splashscreen:1.0.0-beta01'

implementation "javax.inject:javax.inject:1"
implementation "javax.annotation:javax.annotation-api:1.3.2"
Expand Down Expand Up @@ -216,8 +216,8 @@ dependencies {
kapt "androidx.room:room-compiler:$ROOM_VERSION"
implementation "androidx.room:room-ktx:$ROOM_VERSION"

prodImplementation "com.google.firebase:firebase-crashlytics:18.2.3"
prodImplementation "com.google.firebase:firebase-analytics:19.0.2"
prodImplementation "com.google.firebase:firebase-crashlytics:18.2.7"
prodImplementation "com.google.firebase:firebase-analytics:20.0.2"

// debugImplementation "com.squareup.leakcanary:leakcanary-android:2.4"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import com.github.premnirmal.ticker.isNetworkOnline
import com.github.premnirmal.ticker.portfolio.PortfolioFragment
import com.github.premnirmal.ticker.widget.WidgetDataProvider
import com.github.premnirmal.tickerwidget.R
import com.google.android.material.appbar.AppBarLayout
import com.google.android.material.tabs.TabLayoutMediator
import kotlinx.android.synthetic.main.fragment_home.app_bar_layout
import kotlinx.android.synthetic.main.fragment_home.subtitle
Expand Down Expand Up @@ -75,12 +76,18 @@ class HomeFragment : BaseFragment(), ChildFragment, PortfolioFragment.Parent {
TabLayoutMediator(tabs, view_pager) { tab, position ->
tab.text = widgetDataProvider.widgetDataList()[position].widgetName()
}.attach()
app_bar_layout.addOnOffsetChangedListener(offsetChangedListener)
subtitle.text = subtitleText
viewModel.fetchState.observe(viewLifecycleOwner) {
updateHeader()
}
}

override fun onDestroyView() {
app_bar_layout.removeOnOffsetChangedListener(offsetChangedListener)
super.onDestroyView()
}

override fun onHiddenChanged(hidden: Boolean) {
super.onHiddenChanged(hidden)
if (!hidden) updateHeader()
Expand All @@ -99,13 +106,13 @@ class HomeFragment : BaseFragment(), ChildFragment, PortfolioFragment.Parent {
// Don't attempt to make many requests in a row if the stocks don't fetch.
if (fetchCount <= MAX_FETCH_COUNT) {
attemptingFetch = true
viewModel.fetch().observe(viewLifecycleOwner, { success ->
viewModel.fetch().observe(viewLifecycleOwner) { success ->
attemptingFetch = false
swipe_container?.isRefreshing = false
if (success) {
update()
}
})
}
} else {
attemptingFetch = false
InAppMessage.showMessage(requireActivity(), R.string.refresh_failed, error = true)
Expand Down Expand Up @@ -135,6 +142,23 @@ class HomeFragment : BaseFragment(), ChildFragment, PortfolioFragment.Parent {
swipe_container.isEnabled = true
}

private val offsetChangedListener = object : AppBarLayout.OnOffsetChangedListener {
private var isTitleShowing = true

override fun onOffsetChanged(appBarLayout: AppBarLayout?, verticalOffset: Int) {
val show = verticalOffset > -20
if (show && !isTitleShowing) {
subtitle.animate().alpha(1f).start()
tabs.animate().alpha(1f).start()
isTitleShowing = true
} else if (!show && isTitleShowing) {
subtitle.animate().alpha(0f).start()
tabs.animate().alpha(0f).start()
isTitleShowing = false
}
}
}

// ChildFragment

override fun scrollToTop() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,16 +71,16 @@ class StocksProvider : IStocksProvider, CoroutineScope {
this.tickerSet.addAll(DEFAULT_STOCKS)
}
val lastFetched = preferences.getLong(LAST_FETCHED, 0L)
_lastFetched.value = lastFetched
_lastFetched.tryEmit(lastFetched)
val nextFetch = preferences.getLong(NEXT_FETCH, 0L)
_nextFetch.value = nextFetch
_nextFetch.tryEmit(nextFetch)
alarmScheduler.enqueuePeriodicRefresh(context)
if (lastFetched == 0L) {
launch {
fetch()
fetch().collect()
}
} else {
_fetchState.value = FetchState.Success(lastFetched)
_fetchState.tryEmit(FetchState.Success(lastFetched))
runBlocking { fetchLocal() }
}
}
Expand Down Expand Up @@ -114,7 +114,7 @@ class StocksProvider : IStocksProvider, CoroutineScope {
msToNextAlarm: Long
) {
val updateTime = alarmScheduler.scheduleUpdate(msToNextAlarm, context)
_nextFetch.value = updateTime.toInstant().toEpochMilli()
_nextFetch.tryEmit(updateTime.toInstant().toEpochMilli())
preferences.edit()
.putLong(NEXT_FETCH, _nextFetch.value)
.apply()
Expand All @@ -125,7 +125,7 @@ class StocksProvider : IStocksProvider, CoroutineScope {
private fun fetchStockInternal(ticker: String, allowCache: Boolean): Flow<FetchResult<Quote>> =
flow {
val quote = if (allowCache) quoteMap[ticker] else null
quote?.let { FetchResult.success(quote) } ?: run {
quote?.let { emit(FetchResult.success(quote)) } ?: run {
try {
emit(api.getStock(ticker))
} catch (ex: Exception) {
Expand Down Expand Up @@ -198,14 +198,15 @@ class StocksProvider : IStocksProvider, CoroutineScope {
quote.symbol = ticker
quoteMap[ticker] = quote
saveTickers()
_tickers.value = tickerSet.toList()
_portfolio.value = quoteMap.filter { widgetDataProvider.containsTicker(it.key) }.map { it.value }
_tickers.tryEmit(tickerSet.toList())
_portfolio.tryEmit(quoteMap.filter { widgetDataProvider.containsTicker(it.key) }.map { it.value })
launch {
fetchStockInternal(ticker, false).collect { result ->
if (result.wasSuccessful) {
val data = result.data
quoteMap[ticker] = data
storage.saveQuote(result.data)
_portfolio.tryEmit(quoteMap.filter { widgetDataProvider.containsTicker(it.key) }.map { it.value })
}
}
}
Expand Down Expand Up @@ -233,7 +234,7 @@ class StocksProvider : IStocksProvider, CoroutineScope {
}
if (!tickerSet.contains(ticker)) {
tickerSet.add(ticker)
_tickers.value = tickerSet.toList()
_tickers.tryEmit(tickerSet.toList())
saveTickers()
}
val holding = Holding(ticker, shares, price)
Expand All @@ -243,7 +244,7 @@ class StocksProvider : IStocksProvider, CoroutineScope {
val id = storage.addHolding(holding)
holding.id = id
}
_portfolio.value = quoteMap.filter { widgetDataProvider.containsTicker(it.key) }.map { it.value }
_portfolio.tryEmit(quoteMap.filter { widgetDataProvider.containsTicker(it.key) }.map { it.value })
return holding
}
}
Expand All @@ -260,8 +261,8 @@ class StocksProvider : IStocksProvider, CoroutineScope {
launch {
storage.removeHolding(ticker, holding)
}
_tickers.value = tickerSet.toList()
_portfolio.value = quoteMap.filter { widgetDataProvider.containsTicker(it.key) }.map { it.value }
_tickers.tryEmit(tickerSet.toList())
_portfolio.tryEmit(quoteMap.filter { widgetDataProvider.containsTicker(it.key) }.map { it.value })
}
}

Expand All @@ -272,11 +273,11 @@ class StocksProvider : IStocksProvider, CoroutineScope {
saveTickers()
if (filterNot.isNotEmpty()) {
launch {
fetch()
fetch().collect()
}
}
_tickers.value = tickerSet.toList()
_portfolio.value = quoteMap.filter { widgetDataProvider.containsTicker(it.key) }.map { it.value }
_tickers.tryEmit(tickerSet.toList())
_portfolio.tryEmit(quoteMap.filter { widgetDataProvider.containsTicker(it.key) }.map { it.value })
}
return this.tickerSet
}
Expand All @@ -286,8 +287,8 @@ class StocksProvider : IStocksProvider, CoroutineScope {
tickerSet.remove(ticker)
saveTickers()
quoteMap.remove(ticker)
_tickers.value = tickerSet.toList()
_portfolio.value = quoteMap.filter { widgetDataProvider.containsTicker(it.key) }.map { it.value }
_tickers.tryEmit(tickerSet.toList())
_portfolio.tryEmit(quoteMap.filter { widgetDataProvider.containsTicker(it.key) }.map { it.value })
}
launch {
storage.removeQuoteBySymbol(ticker)
Expand All @@ -301,8 +302,8 @@ class StocksProvider : IStocksProvider, CoroutineScope {
tickerSet.remove(it)
quoteMap.remove(it)
}
_tickers.value = tickerSet.toList()
_portfolio.value = quoteMap.filter { widgetDataProvider.containsTicker(it.key) }.map { it.value }
_tickers.tryEmit(tickerSet.toList())
_portfolio.tryEmit(quoteMap.filter { widgetDataProvider.containsTicker(it.key) }.map { it.value })
}
saveTickers()
launch {
Expand Down Expand Up @@ -335,7 +336,7 @@ class StocksProvider : IStocksProvider, CoroutineScope {
launch {
storage.saveQuotes(portfolio)
fetchLocal()
fetch()
fetch().collect()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AlertDialog
import androidx.core.content.ContextCompat
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import com.github.mikephil.charting.charts.LineChart
Expand All @@ -32,7 +31,7 @@ import com.github.premnirmal.ticker.widget.WidgetDataProvider
import com.github.premnirmal.tickerwidget.R
import com.github.premnirmal.tickerwidget.R.color
import com.github.premnirmal.tickerwidget.R.dimen
import kotlinx.android.synthetic.main.activity_graph.*
import kotlinx.android.synthetic.main.activity_graph.one_day
import kotlinx.android.synthetic.main.activity_quote_detail.alert_above
import kotlinx.android.synthetic.main.activity_quote_detail.alert_below
import kotlinx.android.synthetic.main.activity_quote_detail.alert_header
Expand Down Expand Up @@ -108,7 +107,7 @@ class QuoteDetailActivity : BaseGraphActivity(), NewsFeedAdapter.NewsClickListen
ticker = checkNotNull(intent.getStringExtra(TICKER))

viewModel = ViewModelProvider(this).get(QuoteDetailViewModel::class.java)
viewModel.quote.observe(this, Observer { result ->
viewModel.quote.observe(this) { result ->
if (result.wasSuccessful) {
quote = result.data
fetch()
Expand All @@ -121,40 +120,40 @@ class QuoteDetailActivity : BaseGraphActivity(), NewsFeedAdapter.NewsClickListen
graphView.setNoDataText(getString(R.string.error_fetching_stock))
news_container.displayedChild = INDEX_ERROR
}
})
viewModel.data.observe(this, Observer { data ->
}
viewModel.data.observe(this) { data ->
dataPoints = data
loadGraph(ticker)
})
viewModel.dataFetchError.observe(this, Observer {
}
viewModel.dataFetchError.observe(this) {
progress.visibility = View.GONE
graphView.setNoDataText(getString(R.string.graph_fetch_failed))
InAppMessage.showMessage(this@QuoteDetailActivity, R.string.graph_fetch_failed, error = true)
})
viewModel.newsData.observe(this, Observer { data ->
}
viewModel.newsData.observe(this) { data ->
analytics.trackGeneralEvent(
GeneralEvent("FetchNews")
.addProperty("Success", "True")
)
setUpArticles(data)
})
viewModel.newsError.observe(this, Observer {
}
viewModel.newsError.observe(this) {
news_container.displayedChild = INDEX_ERROR
InAppMessage.showMessage(this@QuoteDetailActivity, R.string.news_fetch_failed, error = true)
analytics.trackGeneralEvent(
GeneralEvent("FetchNews")
.addProperty("Success", "False")
)
})
}
viewModel.fetchQuote(ticker)
var view: View? = null
when (range) {
Range.ONE_DAY -> view = one_day
Range.TWO_WEEKS -> view = two_weeks
Range.ONE_MONTH -> view = one_month
Range.THREE_MONTH -> view = three_month
Range.ONE_YEAR -> view = one_year
Range.MAX -> view = max
val view = when (range) {
Range.ONE_DAY -> one_day
Range.TWO_WEEKS -> two_weeks
Range.ONE_MONTH -> one_month
Range.THREE_MONTH -> three_month
Range.ONE_YEAR -> one_year
Range.MAX -> max
else -> null
}
view?.isEnabled = false
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ import android.view.View
import android.view.ViewGroup
import android.widget.PopupMenu
import androidx.appcompat.app.AlertDialog
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.ItemTouchHelper
import com.github.premnirmal.ticker.analytics.ClickEvent
import com.github.premnirmal.ticker.base.BaseFragment
import com.github.premnirmal.ticker.components.InAppMessage
import com.github.premnirmal.ticker.components.Injector
import com.github.premnirmal.ticker.home.ChildFragment
import com.github.premnirmal.ticker.model.IStocksProvider
import com.github.premnirmal.ticker.network.data.Quote
import com.github.premnirmal.ticker.news.QuoteDetailActivity
import com.github.premnirmal.ticker.portfolio.StocksAdapter.QuoteClickListener
Expand All @@ -25,6 +27,7 @@ import com.github.premnirmal.ticker.widget.WidgetDataProvider
import com.github.premnirmal.tickerwidget.R
import kotlinx.android.synthetic.main.fragment_portfolio.stockList
import kotlinx.android.synthetic.main.fragment_portfolio.view_flipper
import kotlinx.coroutines.launch
import javax.inject.Inject

/**
Expand Down Expand Up @@ -65,6 +68,7 @@ class PortfolioFragment : BaseFragment(), ChildFragment, QuoteClickListener, OnS
class InjectionHolder {

@Inject internal lateinit var widgetDataProvider: WidgetDataProvider
@Inject internal lateinit var stocksProvider: IStocksProvider

init {
Injector.appComponent.inject(this)
Expand Down Expand Up @@ -117,11 +121,6 @@ class PortfolioFragment : BaseFragment(), ChildFragment, QuoteClickListener, OnS
widgetId = requireArguments().getInt(KEY_WIDGET_ID)
}

override fun onResume() {
super.onResume()
update()
}

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
Expand Down Expand Up @@ -155,6 +154,11 @@ class PortfolioFragment : BaseFragment(), ChildFragment, QuoteClickListener, OnS
} else {
view_flipper.displayedChild = 1
}
lifecycleScope.launch {
holder.stocksProvider.portfolio.collect {
update()
}
}
}

private fun update() {
Expand Down
Loading

0 comments on commit c596499

Please sign in to comment.