Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions app/src/main/java/one/mixin/android/db/MarketCategoryDao.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package one.mixin.android.db

import androidx.room3.Dao
import androidx.room3.Query
import androidx.room3.RewriteQueriesToDropUnusedColumns
import androidx.room3.Transaction
import kotlinx.coroutines.flow.Flow
import one.mixin.android.vo.market.MarketCategoryRelation
Expand Down Expand Up @@ -36,6 +37,7 @@ interface MarketCategoryDao : BaseDao<MarketCategoryRelation> {
}
}

@RewriteQueriesToDropUnusedColumns
@Query(
"""
SELECT m.*, mf.is_favored
Expand All @@ -48,6 +50,7 @@ interface MarketCategoryDao : BaseDao<MarketCategoryRelation> {
)
fun observeMarketsByCategory(category: Int): Flow<List<MarketItem>>

@RewriteQueriesToDropUnusedColumns
@Query(
"""
SELECT m.*, mf.is_favored
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/java/one/mixin/android/db/SafeSnapshotDao.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ interface SafeSnapshotDao : BaseDao<SafeSnapshot> {
SELECT s.snapshot_id, s.type, s.asset_id, s.amount, s.created_at, s.opponent_id, s.trace_id, s.memo,
s.confirmations, s.transaction_hash, s.opening_balance, s.closing_balance, s.deposit AS deposit, s.withdrawal AS withdrawal,
u.avatar_url, u.full_name AS opponent_ful_name, t.symbol AS asset_symbol, t.confirmations AS asset_confirmations,
i.inscription_hash, i.collection_hash, i.inscription_hash, ic.name, i.sequence, i.content_type, i.content_url, ic.icon_url
i.inscription_hash, i.collection_hash, ic.name, i.sequence, i.content_type, i.content_url, ic.icon_url
FROM safe_snapshots s
LEFT JOIN users u ON u.user_id = s.opponent_id
LEFT JOIN tokens t ON t.asset_id = s.asset_id
Expand Down
6 changes: 3 additions & 3 deletions app/src/main/java/one/mixin/android/db/TokenDao.kt
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ interface TokenDao : BaseDao<Token> {
@Query("$PREFIX_ASSET_ITEM")
fun assetFlow(): Flow<List<TokenItem>>

@Query("SELECT * FROM tokens a1 LEFT JOIN tokens_extra ae ON ae.asset_id = a1.asset_id $POSTFIX")
@Query("SELECT a1.* FROM tokens a1 LEFT JOIN tokens_extra ae ON ae.asset_id = a1.asset_id $POSTFIX")
fun assets(): LiveData<List<Token>>

@Query("SELECT a1.* FROM tokens a1 LEFT JOIN tokens_extra ae ON ae.asset_id = a1.asset_id WHERE balance > 0 $POSTFIX")
Expand All @@ -54,10 +54,10 @@ interface TokenDao : BaseDao<Token> {
@Query("SELECT a1.* FROM tokens a1 LEFT JOIN tokens_extra ae ON ae.asset_id = a1.asset_id WHERE balance > 0 $POSTFIX")
suspend fun simpleAssetsWithBalance(): List<Token>

@Query("SELECT a1.asset_id, a1.chain_id, ae.balance, a1.symbol, a1.name, a1.icon_url, ae.balance FROM tokens a1 LEFT JOIN tokens_extra ae ON ae.asset_id = a1.asset_id WHERE balance > 0 $POSTFIX")
@Query("SELECT a1.asset_id, a1.chain_id, ae.balance, a1.symbol, a1.name, a1.icon_url FROM tokens a1 LEFT JOIN tokens_extra ae ON ae.asset_id = a1.asset_id WHERE balance > 0 $POSTFIX")
suspend fun tokenEntry(): List<TokenEntry>

@Query("SELECT a1.asset_id, a1.chain_id, ae.balance, a1.symbol, a1.name, a1.icon_url, ae.balance FROM tokens a1 LEFT JOIN tokens_extra ae ON ae.asset_id = a1.asset_id WHERE a1.asset_id IN (:ids)")
@Query("SELECT a1.asset_id, a1.chain_id, ae.balance, a1.symbol, a1.name, a1.icon_url FROM tokens a1 LEFT JOIN tokens_extra ae ON ae.asset_id = a1.asset_id WHERE a1.asset_id IN (:ids)")
suspend fun tokenEntry(ids: Array<String>): List<TokenEntry>

@Query("SELECT asset_id FROM tokens WHERE kernel_asset_id = :asset")
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/java/one/mixin/android/db/UserDao.kt
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ interface UserDao : BaseDao<User> {

@SuppressWarnings(RoomWarnings.QUERY_MISMATCH)
@Query(
"""SELECT * FROM users u INNER JOIN participants p ON p.user_id = u.user_id
"""SELECT u.*, p.role FROM users u INNER JOIN participants p ON p.user_id = u.user_id
WHERE p.conversation_id = :conversationId AND u.user_id IN (:userIds)
""",
)
Expand All @@ -234,7 +234,7 @@ interface UserDao : BaseDao<User> {

@SuppressWarnings(RoomWarnings.QUERY_MISMATCH)
@Query(
"""SELECT * FROM users u INNER JOIN participants p ON p.user_id = u.user_id
"""SELECT u.*, p.role FROM users u INNER JOIN participants p ON p.user_id = u.user_id
WHERE p.conversation_id = :conversationId AND u.user_id = :userId
""",
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ interface Web3TransactionDao : BaseDao<Web3Transaction> {
@RawQuery(observedEntities = [Web3Transaction::class])
fun allTransactions(query: RoomRawQuery): PagingSource<Int, Web3TransactionItem>

@Query("SELECT DISTINCT transaction_hash, * FROM transactions WHERE transaction_hash = :hash AND chain_id = :chainId LIMIT 1")
@Query("SELECT DISTINCT * FROM transactions WHERE transaction_hash = :hash AND chain_id = :chainId LIMIT 1")
suspend fun getLatestTransaction(hash: String, chainId: String): Web3Transaction?

@Query("DELETE FROM transactions WHERE status = 'pending' AND transaction_hash = :hash AND chain_id = :chainId")
Expand All @@ -73,7 +73,7 @@ interface Web3TransactionDao : BaseDao<Web3Transaction> {
@Query("SELECT COUNT(*) FROM transactions WHERE status = 'pending' AND address in (SELECT destination FROM addresses WHERE wallet_id = :walletId)")
fun getPendingTransactionCount(walletId: String): LiveData<Int>

@Query("SELECT DISTINCT transaction_hash, * FROM transactions WHERE status = 'pending' AND address in (SELECT destination FROM addresses WHERE wallet_id = :walletId)")
@Query("SELECT DISTINCT * FROM transactions WHERE status = 'pending' AND address in (SELECT destination FROM addresses WHERE wallet_id = :walletId)")
suspend fun getPendingTransactions(walletId: String): List<Web3Transaction>

@Query(""" SELECT DISTINCT w.transaction_hash, w.transaction_type, w.status, w.block_number, w.chain_id, w.address, w.fee, w.sponsor_fee_asset_id, w.sponsor_fee_amount, w.senders, w.receivers, w.approvals, w.send_asset_id, w.receive_asset_id, w.transaction_at, w.updated_at, w.level,
Expand Down
23 changes: 23 additions & 0 deletions app/src/main/java/one/mixin/android/extension/IterableExtension.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,26 @@ suspend fun <A, B> Iterable<A>.pmap(f: suspend (A) -> B): List<B> =
coroutineScope {
map { async { f(it) } }.awaitAll()
}

fun <T, K> mergeLocalAndRefreshed(
localMatches: List<T>,
refreshedMatches: List<T>,
keySelector: (T) -> K,
): List<T> {
val refreshedByKey = refreshedMatches.associateBy(keySelector)
val localKeys = LinkedHashSet<K>()
val merged = ArrayList<T>(localMatches.size + refreshedMatches.size)

localMatches.forEach { local ->
val key = keySelector(local)
localKeys += key
merged += refreshedByKey[key] ?: local
}
refreshedMatches.forEach { refreshed ->
if (keySelector(refreshed) !in localKeys) {
merged += refreshed
}
}

return merged
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package one.mixin.android.repository

import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.flow.Flow
import one.mixin.android.Constants
import one.mixin.android.api.response.perps.PerpsFavorite
Expand All @@ -12,6 +13,7 @@ import one.mixin.android.db.withRoomTransaction
import one.mixin.android.db.perps.PerpsFavoriteDao
import one.mixin.android.db.perps.PerpsMarketCategoryDao
import one.mixin.android.db.perps.PerpsMarketDao
import one.mixin.android.extension.mergeLocalAndRefreshed
import one.mixin.android.extension.nowInUtc
import one.mixin.android.ui.wallet.fiatmoney.requestRouteAPI
import one.mixin.android.vo.market.MarketCategory
Expand Down Expand Up @@ -40,6 +42,13 @@ class PerpsMarketRepository

suspend fun searchMarkets(query: String): List<PerpsMarket> = marketDao.searchMarkets(query.trim())

suspend fun searchMarketsOnlineFirst(query: String): List<PerpsMarket> =
searchPerpsMarketsOnlineFirst(
query = query,
searchLocalMarkets = marketDao::searchMarkets,
syncOnlineMarkets = { syncAllMarkets() },
)

suspend fun getMarket(marketId: String): PerpsMarket? = marketDao.getMarket(marketId)

suspend fun syncAllMarkets(): List<PerpsMarket>? {
Expand Down Expand Up @@ -167,7 +176,10 @@ class PerpsMarketRepository
response.data.orEmpty().map(PerpsMarket::withDefaults)
},
failureBlock = { true },
exceptionBlock = { true },
exceptionBlock = { throwable ->
if (throwable is CancellationException) throw throwable
true
},
defaultErrorHandle = {},
defaultExceptionHandle = {},
requestSession = {
Expand All @@ -179,3 +191,24 @@ class PerpsMarketRepository
const val CATEGORY_FAVORITE = "favorite"
}
}

internal suspend fun searchPerpsMarketsOnlineFirst(
query: String,
searchLocalMarkets: suspend (query: String) -> List<PerpsMarket>,
syncOnlineMarkets: suspend () -> Unit,
): List<PerpsMarket> {
val normalizedQuery = query.trim()
if (normalizedQuery.isBlank()) return emptyList()

val localMatches = searchLocalMarkets(normalizedQuery)

return try {
syncOnlineMarkets()
val refreshedMatches = searchLocalMarkets(normalizedQuery)
mergeLocalAndRefreshed(localMatches, refreshedMatches, PerpsMarket::marketId)
} catch (e: CancellationException) {
throw e
} catch (_: Exception) {
localMatches
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,8 @@ class MarketSearchFragment : BaseFragment() {
}
}

override fun onViewCreated(
view: View,
savedInstanceState: Bundle?,
) {
super.onViewCreated(view, savedInstanceState)
override fun onStart() {
super.onStart()
marketSearchViewModel.loadRecentSearches(requireContext().defaultSharedPreferences)
}

Expand Down Expand Up @@ -113,7 +110,7 @@ class MarketSearchFragment : BaseFragment() {
RecentSearch(
type = RecentSearchType.PERPETUAL,
iconUrl = market.iconUrl,
title = market.displaySymbol.ifBlank { market.tokenSymbol },
title = market.tokenSymbol,
subTitle = market.tokenSymbol,
primaryKey = market.marketId,
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,18 @@ internal fun List<PerpsMarket>.sortedForTrendingSearch(): List<PerpsMarket> =
.thenBy { it.marketId },
)

internal fun <T> List<T>.sortedForMarketSearch(
symbol: (T) -> String,
name: (T) -> String,
volume: (T) -> String,
): List<T> {
return sortedWith(
compareByDescending<T> { volume(it).toBigDecimalOrNull() ?: BigDecimal.ZERO }
.thenBy { symbol(it).lowercase(Locale.ROOT) }
.thenBy { name(it).lowercase(Locale.ROOT) },
)
}

internal data class MarketSearchUiState(
val query: String = "",
val selectedTab: MarketSearchTab = MarketSearchTab.CRYPTO,
Expand Down
Loading