feat(android): introduce a separate SearchActivity

This commit is contained in:
Harsh Shandilya 2023-11-04 02:42:21 +05:30
parent ed81ceaa94
commit f636b56ee3
No known key found for this signature in database
5 changed files with 110 additions and 117 deletions

View file

@ -132,6 +132,17 @@
<data android:scheme="https" />
</intent-filter>
</activity>
<activity
android:name=".SearchActivity"
android:configChanges="colorMode|density|fontScale|keyboard|keyboardHidden|layoutDirection|locale|mcc|mnc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|touchscreen|uiMode"
android:exported="true"
android:label="Claw Search"
android:theme="@style/Theme.Claw">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity>
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"

View file

@ -0,0 +1,77 @@
/*
* Copyright © 2021-2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.android
import android.app.assist.AssistContent
import android.graphics.Color
import android.net.Uri
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.SystemBarStyle
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.padding
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.unit.dp
import androidx.navigation.compose.rememberNavController
import com.deliveryhero.whetstone.Whetstone
import com.deliveryhero.whetstone.activity.ContributesActivityInjector
import dev.msfjarvis.claw.android.ui.lists.SearchList
import dev.msfjarvis.claw.android.ui.rememberPostActions
import dev.msfjarvis.claw.android.viewmodel.ClawViewModel
import dev.msfjarvis.claw.common.theme.LobstersTheme
import dev.msfjarvis.claw.common.urllauncher.UrlLauncher
import javax.inject.Inject
@ContributesActivityInjector
class SearchActivity : ComponentActivity() {
@Inject lateinit var urlLauncher: UrlLauncher
@Inject lateinit var viewModel: ClawViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Whetstone.inject(this)
enableEdgeToEdge(
statusBarStyle =
SystemBarStyle.light(
Color.TRANSPARENT,
Color.TRANSPARENT,
),
navigationBarStyle =
SystemBarStyle.light(
Color.TRANSPARENT,
Color.TRANSPARENT,
),
)
setContent {
LobstersTheme(
dynamicColor = true,
providedValues = arrayOf(LocalUriHandler provides urlLauncher),
) {
val navController = rememberNavController()
val postActions = rememberPostActions(urlLauncher, navController, viewModel)
SearchList(
items = viewModel.searchResults,
isPostSaved = viewModel::isPostSaved,
postActions = postActions,
searchQuery = viewModel.searchQuery,
setSearchQuery = { query -> viewModel.searchQuery = query },
modifier = Modifier.padding(top = 56.dp),
)
}
}
}
override fun onProvideAssistContent(outContent: AssistContent?) {
super.onProvideAssistContent(outContent)
if (outContent != null) {
outContent.webUri = Uri.parse("https://lobste.rs/search")
}
}
}

View file

@ -246,7 +246,6 @@ fun LobstersApp(
setWebUri("https://lobste.rs/search")
SearchList(
items = viewModel.searchResults,
listState = searchListState,
isPostSaved = viewModel::isPostSaved,
postActions = postActions,
searchQuery = viewModel.searchQuery,

View file

@ -6,25 +6,18 @@
*/
package dev.msfjarvis.claw.android.ui.lists
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.SearchOff
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.SearchBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.semantics.isTraversalGroup
@ -34,15 +27,15 @@ import androidx.compose.ui.zIndex
import androidx.paging.PagingData
import androidx.paging.compose.collectAsLazyPagingItems
import dev.msfjarvis.claw.common.posts.PostActions
import dev.msfjarvis.claw.common.ui.SearchBar
import dev.msfjarvis.claw.database.local.SavedPost
import dev.msfjarvis.claw.model.LobstersPost
import dev.msfjarvis.claw.model.toSavedPost
import kotlinx.coroutines.flow.Flow
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SearchList(
items: Flow<PagingData<LobstersPost>>,
listState: LazyListState,
isPostSaved: (SavedPost) -> Boolean,
postActions: PostActions,
searchQuery: String,
@ -58,37 +51,30 @@ fun SearchList(
// Clear search field when navigating away
onDispose { setSearchQuery("") }
}
var searchActive by remember { mutableStateOf(false) }
Column(modifier = Modifier.semantics { isTraversalGroup = true }.zIndex(1f).fillMaxWidth()) {
Column(
modifier = modifier.semantics { isTraversalGroup = true }.zIndex(1f).fillMaxWidth(),
) {
SearchBar(
value = searchQuery,
onValueChange = setSearchQuery,
query = searchQuery,
onQueryChange = setSearchQuery,
onSearch = {
triggerSearch(it)
searchActive = true
},
active = searchActive,
onActiveChange = { searchActive = it },
modifier = Modifier.fillMaxWidth().padding(horizontal = 8.dp).testTag("search_bar"),
)
if (searchActive) {
NetworkPosts(
lazyPagingItems = lazyPagingItems,
listState = listState,
isPostSaved = isPostSaved,
isPostRead = { false },
) {
lazyPagingItems.itemSnapshotList.items.forEach { item ->
val dbModel = item.toSavedPost()
ListItem(
item = dbModel,
isSaved = isPostSaved,
isRead = { false },
postActions = postActions,
modifier = modifier,
)
} else {
Box(modifier = Modifier.fillMaxSize()) {
Column(modifier = Modifier.align(Alignment.Center)) {
Icon(
imageVector = Icons.Filled.SearchOff,
contentDescription = "No search results",
modifier = Modifier.align(Alignment.CenterHorizontally).size(36.dp),
)
Text(text = "Nothing to see here", style = MaterialTheme.typography.headlineSmall)
}
HorizontalDivider()
}
}
}

View file

@ -1,80 +0,0 @@
/*
* Copyright © 2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.common.ui
import androidx.compose.foundation.background
import androidx.compose.foundation.focusable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Search
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import dev.msfjarvis.claw.common.theme.LobstersTheme
@Composable
fun SearchBar(
value: String,
onValueChange: (String) -> Unit,
onSearch: (String) -> Unit,
modifier: Modifier = Modifier,
) {
TextField(
value = value,
onValueChange = onValueChange,
shape = RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp),
textStyle = MaterialTheme.typography.bodyLarge,
placeholder = { Text(text = "Search") },
trailingIcon = {
IconButton(onClick = { onSearch(value) }) {
Icon(imageVector = Icons.Outlined.Search, contentDescription = "Search")
}
},
keyboardActions = KeyboardActions(onSearch = { onSearch(value) }),
keyboardOptions =
KeyboardOptions(
keyboardType = KeyboardType.Text,
imeAction = ImeAction.Search,
),
singleLine = true,
modifier = modifier.focusable(),
)
}
@Preview
@Composable
fun SearchBarPreview() {
LobstersTheme {
Box(Modifier.fillMaxWidth().background(MaterialTheme.colorScheme.background).padding(8.dp)) {
var value by remember { mutableStateOf("") }
SearchBar(
value = value,
onValueChange = { value = it },
onSearch = {},
modifier = Modifier.align(Alignment.TopCenter)
)
}
}
}