Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/cache #20

Open
wants to merge 52 commits into
base: main
Choose a base branch
from
Open
Changes from 1 commit
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
8d43411
base navigation
LucasPrioste92 Apr 5, 2024
673aeb2
Merge branch 'feature/splash-screen' into feature/navigation
LucasPrioste92 Apr 5, 2024
907f2ce
update colors background and add scaffold to support bottom bar
LucasPrioste92 Apr 8, 2024
14c67a3
bottom bar
LucasPrioste92 Apr 8, 2024
388f4f2
route with arg symbolId on Detail screen
LucasPrioste92 Apr 8, 2024
398453d
initial setup alpaca API
LucasPrioste92 Apr 8, 2024
3f5ed1f
update dimensions
LucasPrioste92 Apr 8, 2024
51bce36
Merge branch 'feature/navigation' into feature/alpaca-api
LucasPrioste92 Apr 8, 2024
31d797e
update alpaca news service
LucasPrioste92 Apr 10, 2024
739ee01
- refactor alpaca news ws service
LucasPrioste92 Apr 11, 2024
201b4b2
- alpaca news API
LucasPrioste92 Apr 11, 2024
b539b0c
- alpaca news API
LucasPrioste92 Apr 11, 2024
2798774
- setup Unit Test libs
LucasPrioste92 Apr 11, 2024
d26ca4f
- faker dependency
LucasPrioste92 Apr 12, 2024
2b44d41
- unit test (NewsRepository)
LucasPrioste92 Apr 12, 2024
734e555
- unit test (ChangeFilterNews UseCase)
LucasPrioste92 Apr 12, 2024
e487af3
- main carousel news
LucasPrioste92 Apr 17, 2024
84360dd
- main carousel news add anim
LucasPrioste92 Apr 18, 2024
aac9174
- show all news
LucasPrioste92 Apr 19, 2024
0b8c085
- real time news
LucasPrioste92 Apr 22, 2024
80c43b2
- pagination news
LucasPrioste92 Apr 22, 2024
dd409ca
- date picker ui
LucasPrioste92 Apr 24, 2024
3f639fa
- logic to apply filters on VM
LucasPrioste92 Apr 26, 2024
9a765df
- unit test
LucasPrioste92 Apr 29, 2024
fa5c993
- update libs
LucasPrioste92 Apr 29, 2024
232d958
- update symbol crypto
LucasPrioste92 Apr 29, 2024
660586c
- assets API
LucasPrioste92 May 2, 2024
9d0225c
- refactor alpaca data API
LucasPrioste92 May 2, 2024
92f6b79
- trades, quotes, bars info
LucasPrioste92 May 2, 2024
faaf727
- use case to get realtime tardes, quotes and bar
LucasPrioste92 May 6, 2024
0616d85
- unit test MarketRemoteDataSource and AssetRemoteDataSource
LucasPrioste92 May 6, 2024
b6235b6
- unit test AssetsRepository
LucasPrioste92 May 6, 2024
107ed0d
- search input assets
LucasPrioste92 May 8, 2024
5f26ec9
- handle error assets list
LucasPrioste92 May 13, 2024
cda4490
- ui test HomeViewModel
LucasPrioste92 May 13, 2024
378bf20
- header detail screen
LucasPrioste92 May 13, 2024
972655e
- base chart
LucasPrioste92 May 15, 2024
c12e93a
- new version chart
LucasPrioste92 May 20, 2024
40285a7
- update chart
LucasPrioste92 May 21, 2024
9c475d8
- update chart
LucasPrioste92 May 23, 2024
14785b8
- get real time quotes
LucasPrioste92 May 24, 2024
2b2ab02
- get trades
LucasPrioste92 May 28, 2024
2312385
- enabled pull to refresh
LucasPrioste92 May 28, 2024
68d5979
- chart just consume horizontal dragging
LucasPrioste92 May 28, 2024
5253271
- unit test DetailViewModel
LucasPrioste92 May 29, 2024
a85b968
setup room db
LucasPrioste92 May 31, 2024
978cf5c
cache all assets
LucasPrioste92 Jun 4, 2024
90efc9b
cache news and logic to clean cache and retrieve news when the app is…
LucasPrioste92 Jun 12, 2024
cb01fec
update popBackStack to navigateUp
LucasPrioste92 Jun 12, 2024
d2e4719
fix bug when user is offline and data is not being loaded from cache
LucasPrioste92 Jun 12, 2024
c593db9
unit test Assets Cached
LucasPrioste92 Jun 12, 2024
88df26d
unit test News Cached
LucasPrioste92 Jun 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
- refactor alpaca news ws service
- use case to get News
LucasPrioste92 committed Apr 11, 2024
commit 739ee0136f4c3bded2b78c7b260fcaf6c6ddd78d
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ package dev.pinkroom.marketsight.common
import dev.pinkroom.marketsight.domain.model.ErrorMessage

sealed class Resource<T>{
data class Success<T>(val data: T?): Resource<T>()
data class Success<T>(val data: T): Resource<T>()
data class Error<T>(
val message: String? = null,
val errorInfo: ErrorMessage? = null,
Original file line number Diff line number Diff line change
@@ -16,9 +16,7 @@ import dev.pinkroom.marketsight.data.mapper.toSubscriptionMessage
import dev.pinkroom.marketsight.data.remote.AlpacaService
import dev.pinkroom.marketsight.data.remote.model.dto.NewsMessageDto
import dev.pinkroom.marketsight.data.remote.model.request.MessageAlpacaService
import dev.pinkroom.marketsight.domain.model.NewsInfo
import dev.pinkroom.marketsight.domain.model.SubscriptionMessage
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.take
@@ -29,11 +27,11 @@ class AlpacaRemoteDataSource @Inject constructor(
private val alpacaService: AlpacaService,
private val dispatchers: DispatcherProvider,
) {
fun subscribeNews(symbols: List<String> = listOf("*")): Flow<Resource<WebSocket.Event>> = flow<Resource<WebSocket.Event>> {
fun subscribeNews(symbols: List<String> = listOf("*")) = flow<Resource<WebSocket.Event>> {
alpacaService.observeOnConnectionEvent().collect{
when(it){
is WebSocket.Event.OnConnectionOpened<*> -> {
alpacaService.sendSubscribe(message = MessageAlpacaService(action = ActionAlpaca.Subscribe.action, news = symbols))
alpacaService.sendMessage(message = MessageAlpacaService(action = ActionAlpaca.Subscribe.action, news = symbols))
}
is WebSocket.Event.OnMessageReceived -> {
Log.d(TAG,"Received: ${it.message}")
@@ -53,21 +51,20 @@ class AlpacaRemoteDataSource @Inject constructor(
}
}.flowOn(dispatchers.IO)

fun getRealTimeNews(): Flow<Resource<List<NewsInfo>>> = flow {
fun getRealTimeNews() = flow {
alpacaService.observeResponse().collect{ data ->
Log.d("TESTE","AQUI SEMPRE")
val listNews = mutableListOf<NewsMessageDto>()
data.forEach {
gson.toObject(value = it, helperIdentifier = HelperIdentifierMessagesAlpacaService.News)?.let { news ->
listNews.add(news)
}
}
emit(Resource.Success(listNews.map { it.toNewsInfo() }))
if (listNews.isNotEmpty()) emit(listNews.map { it.toNewsInfo() })
}
}.flowOn(dispatchers.IO)

fun sendMessageToAlpacaService(message: MessageAlpacaService): Flow<Resource<SubscriptionMessage>> = flow<Resource<SubscriptionMessage>> {
alpacaService.sendSubscribe(message = message)
fun sendMessageToAlpacaService(message: MessageAlpacaService) = flow<Resource<SubscriptionMessage>> {
alpacaService.sendMessage(message = message)
alpacaService.observeResponse().collect { data ->
data.forEach {
gson.toObject(value = it, helperIdentifier = HelperIdentifierMessagesAlpacaService.Subscription)?.let { sub ->
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@ interface AlpacaService {
fun observeOnConnectionEvent(): Flow<WebSocket.Event>

@Send
fun sendSubscribe(message: MessageAlpacaService)
fun sendMessage(message: MessageAlpacaService)

@Receive
fun observeResponse(): Flow<List<Any>>
Original file line number Diff line number Diff line change
@@ -1,44 +1,43 @@
package dev.pinkroom.marketsight.data.repository

import android.util.Log
import com.tinder.scarlet.WebSocket
import dev.pinkroom.marketsight.common.ActionAlpaca
import dev.pinkroom.marketsight.common.DispatcherProvider
import dev.pinkroom.marketsight.common.Resource
import dev.pinkroom.marketsight.data.data_source.AlpacaRemoteDataSource
import dev.pinkroom.marketsight.data.remote.model.request.MessageAlpacaService
import dev.pinkroom.marketsight.domain.model.NewsInfo
import dev.pinkroom.marketsight.domain.model.SubscriptionMessage
import dev.pinkroom.marketsight.domain.repository.NewsRepository
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.single
import javax.inject.Inject

class NewsRepositoryImp @Inject constructor(
private val remoteDataSource: AlpacaRemoteDataSource,
private val dispatchers: DispatcherProvider,
): NewsRepository {
override fun subscribeNews(
symbols: List<String>,
): Flow<Resource<WebSocket.Event>> = flow {
override fun subscribeNews(symbols: List<String>) = flow {
remoteDataSource.subscribeNews(symbols = symbols).collect{
emit(it)
}
}.flowOn(dispatchers.IO)

override fun getRealTimeNews(): Flow<Resource<List<NewsInfo>>> = flow {
override fun getRealTimeNews() = flow {
remoteDataSource.getRealTimeNews().collect{
emit(it)
}
}.flowOn(dispatchers.IO)

override fun changeFilterNews(
symbolsToSubscribe: List<String>?,
symbolsToUnsubscribe: List<String>?
): Flow<Resource<SubscriptionMessage>> = flow<Resource<SubscriptionMessage>> {
remoteDataSource.sendMessageToAlpacaService(message = MessageAlpacaService(action = ActionAlpaca.Subscribe.action, news = listOf("*"))).collect{

override suspend fun changeFilterNews(
symbols: List<String>,
actionAlpaca: ActionAlpaca,
): Resource<List<String>> = flow {
val message = MessageAlpacaService(action = actionAlpaca.action, news = symbols)
remoteDataSource.sendMessageToAlpacaService(message = message).collect{ response ->
when(response){
is Resource.Error -> emit(Resource.Error(data = symbols))
is Resource.Success -> emit(Resource.Success(data = response.data.news ?: symbols))
else -> Unit
}
}
}.flowOn(dispatchers.IO)
}.flowOn(dispatchers.IO).single()
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
package dev.pinkroom.marketsight.domain.repository

import com.tinder.scarlet.WebSocket
import dev.pinkroom.marketsight.common.ActionAlpaca
import dev.pinkroom.marketsight.common.Resource
import dev.pinkroom.marketsight.domain.model.NewsInfo
import dev.pinkroom.marketsight.domain.model.SubscriptionMessage
import kotlinx.coroutines.flow.Flow

interface NewsRepository {
fun subscribeNews(
symbols: List<String> = listOf("*"),
): Flow<Resource<WebSocket.Event>>
fun getRealTimeNews(): Flow<Resource<List<NewsInfo>>>
fun changeFilterNews(
symbolsToSubscribe: List<String>? = null,
symbolsToUnsubscribe: List<String>? = null,
): Flow<Resource<SubscriptionMessage>>
fun getRealTimeNews(): Flow<List<NewsInfo>>
suspend fun changeFilterNews(
symbols: List<String>,
actionAlpaca: ActionAlpaca,
): Resource<List<String>>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package dev.pinkroom.marketsight.domain.use_case.news

import dev.pinkroom.marketsight.common.ActionAlpaca
import dev.pinkroom.marketsight.common.DispatcherProvider
import dev.pinkroom.marketsight.common.Resource
import dev.pinkroom.marketsight.domain.repository.NewsRepository
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import javax.inject.Inject

class ChangeFilterNews @Inject constructor(
private val newsRepository: NewsRepository,
private val dispatchers: DispatcherProvider,
){
operator fun invoke(
subscribeSymbols: List<String>? = null,
unsubscribeSymbols: List<String>? = null,
) = flow<Resource<List<String>>> {
val symbolsToRevert = mutableListOf<String>()
unsubscribeSymbols?.let { symbols ->
val response = newsRepository.changeFilterNews(symbols = symbols, actionAlpaca = ActionAlpaca.Unsubscribe)
when(response){
is Resource.Error -> {
symbolsToRevert.addAll(unsubscribeSymbols)
}
else -> Unit
}
}

subscribeSymbols?.let { symbols ->
val response = newsRepository.changeFilterNews(symbols = symbols, actionAlpaca = ActionAlpaca.Subscribe)
when(response){
is Resource.Success -> emit(Resource.Success(data = response.data))
is Resource.Error -> {
symbolsToRevert.addAll(subscribeSymbols)
}
else -> Unit
}
}

if (symbolsToRevert.isNotEmpty()) emit(Resource.Error(data = symbolsToRevert))
}.flowOn(dispatchers.IO)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package dev.pinkroom.marketsight.domain.use_case.news

import dev.pinkroom.marketsight.common.DispatcherProvider
import dev.pinkroom.marketsight.domain.repository.NewsRepository
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import javax.inject.Inject

class GetRealTimeNews @Inject constructor(
private val newsRepository: NewsRepository,
private val dispatchers: DispatcherProvider,
){
operator fun invoke() = flow {
emit(newsRepository.getRealTimeNews())
}.flowOn(dispatchers.IO)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package dev.pinkroom.marketsight.domain.use_case.news

import dev.pinkroom.marketsight.common.DispatcherProvider
import dev.pinkroom.marketsight.domain.repository.NewsRepository
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import javax.inject.Inject

class SubscribeNews @Inject constructor(
private val newsRepository: NewsRepository,
private val dispatchers: DispatcherProvider,
){
operator fun invoke() = flow {
emit(newsRepository.subscribeNews())
}.flowOn(dispatchers.IO)
}
Original file line number Diff line number Diff line change
@@ -1,33 +1,11 @@
package dev.pinkroom.marketsight.ui.home_screen

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import dev.pinkroom.marketsight.domain.repository.NewsRepository
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import javax.inject.Inject

@HiltViewModel
class HomeViewModel @Inject constructor(
newsRepository: NewsRepository
): ViewModel(){
init {
viewModelScope.launch {
newsRepository.subscribeNews().collect{

}
}
viewModelScope.launch {
newsRepository.getRealTimeNews().collect{

}
}
viewModelScope.launch {
delay(10000)
newsRepository.changeFilterNews().collect{

}
}
}
}