Refactor button bar component
|
@ -75,14 +75,13 @@ dependencies {
|
||||||
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
|
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
|
||||||
implementation 'com.squareup.okhttp3:okhttp:5.0.0-alpha.4'
|
implementation 'com.squareup.okhttp3:okhttp:5.0.0-alpha.4'
|
||||||
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
|
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
|
||||||
implementation "me.onebone:toolbar-compose:2.3.1"
|
|
||||||
implementation "com.google.accompanist:accompanist-insets:0.24.1-alpha"
|
implementation "com.google.accompanist:accompanist-insets:0.24.1-alpha"
|
||||||
implementation "com.google.accompanist:accompanist-systemuicontroller:0.24.1-alpha"
|
implementation "com.google.accompanist:accompanist-systemuicontroller:0.24.1-alpha"
|
||||||
implementation 'com.google.accompanist:accompanist-pager:0.24.1-alpha'
|
implementation 'com.google.accompanist:accompanist-pager:0.24.1-alpha'
|
||||||
implementation 'androidx.core:core-ktx:1.7.0'
|
implementation 'androidx.core:core-ktx:1.7.0'
|
||||||
implementation "androidx.compose.ui:ui:$compose_version"
|
implementation "androidx.compose.ui:ui:$compose_version"
|
||||||
implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.5.0-alpha01"
|
implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.5.0-alpha01"
|
||||||
implementation "androidx.compose.material:material:1.2.0-alpha03"
|
implementation "androidx.compose.material:material:1.2.0-alpha04"
|
||||||
implementation "androidx.compose.material3:material3:1.0.0-alpha06"
|
implementation "androidx.compose.material3:material3:1.0.0-alpha06"
|
||||||
implementation "androidx.compose.material:material-icons-extended:$compose_version"
|
implementation "androidx.compose.material:material-icons-extended:$compose_version"
|
||||||
implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
|
implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:networkSecurityConfig="@xml/network_security_config"
|
android:networkSecurityConfig="@xml/network_security_config"
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/Theme.Reader">
|
android:theme="@style/Theme.Reader">
|
||||||
<activity
|
<activity
|
||||||
|
|
231
app/src/main/java/me/ash/reader/ui/page/home/feed/ButtonBar.kt
Normal file
|
@ -0,0 +1,231 @@
|
||||||
|
package me.ash.reader.ui.page.home.feed
|
||||||
|
|
||||||
|
import android.view.HapticFeedbackConstants
|
||||||
|
import androidx.compose.foundation.Image
|
||||||
|
import androidx.compose.foundation.LocalIndication
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.gestures.detectTapGestures
|
||||||
|
import androidx.compose.foundation.indication
|
||||||
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
|
import androidx.compose.foundation.interaction.PressInteraction
|
||||||
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Surface
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.*
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.graphics.painter.Painter
|
||||||
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
|
import androidx.compose.ui.input.pointer.pointerInput
|
||||||
|
import androidx.compose.ui.platform.LocalView
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
|
import androidx.compose.ui.unit.DpOffset
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import me.ash.reader.R
|
||||||
|
import me.ash.reader.ui.widget.AnimatedText
|
||||||
|
import me.ash.reader.ui.widget.Menu
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ButtonBar(
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
onClick: () -> Unit = {},
|
||||||
|
buttonBarType: ButtonBarType,
|
||||||
|
) {
|
||||||
|
var expanded by remember { mutableStateOf(false) }
|
||||||
|
var offset by remember { mutableStateOf(DpOffset.Zero) }
|
||||||
|
val interactionSource = remember { MutableInteractionSource() }
|
||||||
|
val view = LocalView.current
|
||||||
|
|
||||||
|
Row(
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
modifier = modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(50.dp)
|
||||||
|
.indication(interactionSource, LocalIndication.current)
|
||||||
|
.padding(horizontal = 20.dp)
|
||||||
|
.clip(RoundedCornerShape(8.dp))
|
||||||
|
.pointerInput(Unit) {
|
||||||
|
detectTapGestures(
|
||||||
|
onPress = { offset ->
|
||||||
|
val press = PressInteraction.Press(offset)
|
||||||
|
interactionSource.emit(press)
|
||||||
|
tryAwaitRelease()
|
||||||
|
interactionSource.emit(PressInteraction.Release(press))
|
||||||
|
},
|
||||||
|
onTap = {
|
||||||
|
onClick()
|
||||||
|
},
|
||||||
|
onLongPress = {
|
||||||
|
view.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP)
|
||||||
|
offset = DpOffset(it.x.toDp(), it.y.toDp())
|
||||||
|
expanded = true
|
||||||
|
},
|
||||||
|
)
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
when (buttonBarType) {
|
||||||
|
is ButtonBarType.FilterBar -> FilterBar(buttonBarType)
|
||||||
|
is ButtonBarType.AllBar -> AllBar(buttonBarType)
|
||||||
|
is ButtonBarType.GroupBar -> GroupBar(buttonBarType)
|
||||||
|
is ButtonBarType.FeedBar -> FeedBar(buttonBarType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Menu(
|
||||||
|
offset = offset,
|
||||||
|
expanded = expanded,
|
||||||
|
dismissFunction = { expanded = false },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun FilterBar(
|
||||||
|
buttonBarType: ButtonBarType.FilterBar,
|
||||||
|
) {
|
||||||
|
AnimatedText(
|
||||||
|
text = buttonBarType.title,
|
||||||
|
fontSize = 22.sp,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
color = MaterialTheme.colorScheme.primary,
|
||||||
|
)
|
||||||
|
AnimatedText(
|
||||||
|
text = buttonBarType.important.toString(),
|
||||||
|
fontSize = 18.sp,
|
||||||
|
color = MaterialTheme.colorScheme.outline,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun AllBar(
|
||||||
|
buttonBarType: ButtonBarType.AllBar,
|
||||||
|
) {
|
||||||
|
AnimatedText(
|
||||||
|
text = buttonBarType.title,
|
||||||
|
fontSize = 22.sp,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
color = MaterialTheme.colorScheme.primary,
|
||||||
|
)
|
||||||
|
Icon(
|
||||||
|
imageVector = buttonBarType.icon,
|
||||||
|
contentDescription = "Expand More",
|
||||||
|
tint = MaterialTheme.colorScheme.outline,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun GroupBar(
|
||||||
|
buttonBarType: ButtonBarType.GroupBar,
|
||||||
|
) {
|
||||||
|
Row {
|
||||||
|
Icon(
|
||||||
|
imageVector = buttonBarType.icon,
|
||||||
|
contentDescription = "icon",
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(end = 4.dp)
|
||||||
|
.clip(CircleShape)
|
||||||
|
.clickable(onClick = buttonBarType.iconOnClick),
|
||||||
|
tint = MaterialTheme.colorScheme.onPrimaryContainer,
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.padding(end = 20.dp),
|
||||||
|
maxLines = 1,
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
text = buttonBarType.title,
|
||||||
|
fontSize = 18.sp,
|
||||||
|
fontWeight = FontWeight.SemiBold,
|
||||||
|
color = MaterialTheme.colorScheme.onPrimaryContainer,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
AnimatedText(
|
||||||
|
text = buttonBarType.important.toString(),
|
||||||
|
fontSize = 18.sp,
|
||||||
|
color = MaterialTheme.colorScheme.outline,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun FeedBar(
|
||||||
|
buttonBarType: ButtonBarType.FeedBar,
|
||||||
|
) {
|
||||||
|
Row {
|
||||||
|
Surface(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(start = 28.dp, end = 4.dp)
|
||||||
|
.size(24.dp),
|
||||||
|
//.background(MaterialTheme.colorScheme.inversePrimary),
|
||||||
|
color = if (buttonBarType.icon == null) {
|
||||||
|
MaterialTheme.colorScheme.inversePrimary
|
||||||
|
} else {
|
||||||
|
Color.Unspecified
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
if (buttonBarType.icon == null) {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(id = R.drawable.default_folder),
|
||||||
|
contentDescription = "icon",
|
||||||
|
modifier = Modifier.fillMaxSize(),
|
||||||
|
tint = MaterialTheme.colorScheme.onPrimaryContainer,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Image(
|
||||||
|
painter = buttonBarType.icon,
|
||||||
|
contentDescription = "icon",
|
||||||
|
modifier = Modifier.fillMaxSize(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Text(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(end = 20.dp),
|
||||||
|
maxLines = 1,
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
text = buttonBarType.title,
|
||||||
|
fontSize = 18.sp,
|
||||||
|
fontWeight = FontWeight.SemiBold,
|
||||||
|
color = MaterialTheme.colorScheme.onPrimaryContainer,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
AnimatedText(
|
||||||
|
text = buttonBarType.important.toString(),
|
||||||
|
fontSize = 18.sp,
|
||||||
|
color = MaterialTheme.colorScheme.outline,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class ButtonBarType {
|
||||||
|
data class FilterBar(
|
||||||
|
val modifier: Modifier = Modifier,
|
||||||
|
val title: String = "",
|
||||||
|
val important: Int = 0,
|
||||||
|
) : ButtonBarType()
|
||||||
|
|
||||||
|
data class AllBar(
|
||||||
|
val title: String = "",
|
||||||
|
val icon: ImageVector,
|
||||||
|
) : ButtonBarType()
|
||||||
|
|
||||||
|
data class GroupBar(
|
||||||
|
val title: String = "",
|
||||||
|
val important: Int = 0,
|
||||||
|
val icon: ImageVector,
|
||||||
|
val iconOnClick: () -> Unit = {},
|
||||||
|
) : ButtonBarType()
|
||||||
|
|
||||||
|
data class FeedBar(
|
||||||
|
val title: String = "",
|
||||||
|
val important: Int = 0,
|
||||||
|
val icon: Painter? = null,
|
||||||
|
) : ButtonBarType()
|
||||||
|
}
|
|
@ -1,199 +0,0 @@
|
||||||
package me.ash.reader.ui.page.home.feed
|
|
||||||
|
|
||||||
import android.graphics.BitmapFactory
|
|
||||||
import androidx.compose.foundation.Image
|
|
||||||
import androidx.compose.foundation.background
|
|
||||||
import androidx.compose.foundation.clickable
|
|
||||||
import androidx.compose.foundation.layout.*
|
|
||||||
import androidx.compose.foundation.shape.CircleShape
|
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.draw.clip
|
|
||||||
import androidx.compose.ui.graphics.Color
|
|
||||||
import androidx.compose.ui.graphics.asImageBitmap
|
|
||||||
import androidx.compose.ui.graphics.painter.BitmapPainter
|
|
||||||
import androidx.compose.ui.graphics.painter.Painter
|
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
|
||||||
import androidx.compose.ui.res.painterResource
|
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import androidx.compose.ui.unit.sp
|
|
||||||
import me.ash.reader.R
|
|
||||||
import me.ash.reader.ui.extension.paddingFixedHorizontal
|
|
||||||
import me.ash.reader.ui.extension.roundClick
|
|
||||||
import me.ash.reader.ui.widget.AnimatedText
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun FeedBar(
|
|
||||||
barButtonType: BarButtonType,
|
|
||||||
iconOnClickListener: () -> Unit = {},
|
|
||||||
onClickListener: () -> Unit = {},
|
|
||||||
) {
|
|
||||||
Box(
|
|
||||||
modifier = Modifier
|
|
||||||
.paddingFixedHorizontal()
|
|
||||||
.roundClick(onClick = onClickListener),
|
|
||||||
) {
|
|
||||||
Row(
|
|
||||||
horizontalArrangement = Arrangement.SpaceBetween,
|
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.height(50.dp)
|
|
||||||
.padding(
|
|
||||||
start = 10.dp,
|
|
||||||
end = if (barButtonType is FirstExpandType) 2.dp else 10.dp
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
when (barButtonType) {
|
|
||||||
is SecondExpandType -> {
|
|
||||||
Icon(
|
|
||||||
imageVector = barButtonType.img,
|
|
||||||
contentDescription = "icon",
|
|
||||||
modifier = Modifier
|
|
||||||
.padding(end = 4.dp)
|
|
||||||
.clip(CircleShape)
|
|
||||||
.clickable(onClick = iconOnClickListener),
|
|
||||||
tint = MaterialTheme.colorScheme.onPrimaryContainer,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
is ItemType -> {
|
|
||||||
val modifier = Modifier
|
|
||||||
Row(
|
|
||||||
modifier = modifier
|
|
||||||
.padding(start = 28.dp, end = 4.dp)
|
|
||||||
.size(24.dp)
|
|
||||||
.background(
|
|
||||||
if (barButtonType.icon != null) Color.Unspecified
|
|
||||||
else MaterialTheme.colorScheme.inversePrimary
|
|
||||||
),
|
|
||||||
// .background(MaterialTheme.colorScheme.inversePrimary),
|
|
||||||
horizontalArrangement = Arrangement.Center,
|
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
|
||||||
) {
|
|
||||||
if (barButtonType.icon == null) {
|
|
||||||
Icon(
|
|
||||||
painter = painterResource(id = R.drawable.default_folder),
|
|
||||||
contentDescription = "icon",
|
|
||||||
modifier = modifier.fillMaxSize(),
|
|
||||||
tint = MaterialTheme.colorScheme.onPrimaryContainer,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
Image(
|
|
||||||
painter = barButtonType.icon,
|
|
||||||
contentDescription = "icon",
|
|
||||||
modifier = modifier.fillMaxSize(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
when (barButtonType) {
|
|
||||||
is ButtonType -> {
|
|
||||||
AnimatedText(
|
|
||||||
modifier = Modifier.weight(1f),
|
|
||||||
text = barButtonType.text,
|
|
||||||
fontSize = 22.sp,
|
|
||||||
fontWeight = FontWeight.Bold,
|
|
||||||
color = MaterialTheme.colorScheme.primary,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
Text(
|
|
||||||
modifier = Modifier
|
|
||||||
.weight(1f)
|
|
||||||
.padding(end = 20.dp),
|
|
||||||
maxLines = 1,
|
|
||||||
overflow = TextOverflow.Ellipsis,
|
|
||||||
text = barButtonType.text,
|
|
||||||
fontSize = if (barButtonType is FirstExpandType) 22.sp else 18.sp,
|
|
||||||
fontWeight = if (barButtonType is FirstExpandType) FontWeight.Bold else FontWeight.SemiBold,
|
|
||||||
color = if (barButtonType is FirstExpandType)
|
|
||||||
MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onPrimaryContainer,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
when (barButtonType) {
|
|
||||||
is ButtonType, is ItemType, is SecondExpandType -> {
|
|
||||||
AnimatedText(
|
|
||||||
text = barButtonType.additional.toString(),
|
|
||||||
fontSize = 18.sp,
|
|
||||||
color = MaterialTheme.colorScheme.outline,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
is FirstExpandType -> {
|
|
||||||
Icon(
|
|
||||||
imageVector = barButtonType.additional as ImageVector,
|
|
||||||
contentDescription = "Expand More",
|
|
||||||
tint = MaterialTheme.colorScheme.outline,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
interface BarButtonType {
|
|
||||||
val img: Any?
|
|
||||||
val text: String
|
|
||||||
val additional: Any?
|
|
||||||
}
|
|
||||||
|
|
||||||
class ButtonType(
|
|
||||||
private val content: String,
|
|
||||||
private val important: Int,
|
|
||||||
) : BarButtonType {
|
|
||||||
override val img: ImageVector?
|
|
||||||
get() = null
|
|
||||||
override val text: String
|
|
||||||
get() = content
|
|
||||||
override val additional: Any
|
|
||||||
get() = important
|
|
||||||
}
|
|
||||||
|
|
||||||
class FirstExpandType(
|
|
||||||
private val content: String,
|
|
||||||
private val icon: ImageVector,
|
|
||||||
) : BarButtonType {
|
|
||||||
override val img: ImageVector?
|
|
||||||
get() = null
|
|
||||||
override val text: String
|
|
||||||
get() = content
|
|
||||||
override val additional: Any
|
|
||||||
get() = icon
|
|
||||||
}
|
|
||||||
|
|
||||||
class SecondExpandType(
|
|
||||||
private val icon: ImageVector,
|
|
||||||
private val content: String,
|
|
||||||
private val important: Int,
|
|
||||||
) : BarButtonType {
|
|
||||||
override val img: ImageVector
|
|
||||||
get() = icon
|
|
||||||
override val text: String
|
|
||||||
get() = content
|
|
||||||
override val additional: Any
|
|
||||||
get() = important
|
|
||||||
}
|
|
||||||
|
|
||||||
class ItemType(
|
|
||||||
// private val icon: String,
|
|
||||||
val icon: BitmapPainter?,
|
|
||||||
private val content: String,
|
|
||||||
private val important: Int,
|
|
||||||
) : BarButtonType {
|
|
||||||
// override val img: String
|
|
||||||
override val img: Painter
|
|
||||||
get() = icon ?: BitmapPainter(
|
|
||||||
BitmapFactory.decodeByteArray(byteArrayOf(), 0, 0).asImageBitmap()
|
|
||||||
)
|
|
||||||
override val text: String
|
|
||||||
get() = content
|
|
||||||
override val additional: Any
|
|
||||||
get() = important
|
|
||||||
}
|
|
|
@ -23,9 +23,10 @@ fun ColumnScope.FeedList(
|
||||||
) {
|
) {
|
||||||
Column(modifier = Modifier.animateContentSize()) {
|
Column(modifier = Modifier.animateContentSize()) {
|
||||||
feeds.forEach { feed ->
|
feeds.forEach { feed ->
|
||||||
FeedBar(
|
ButtonBar(
|
||||||
barButtonType = ItemType(
|
buttonBarType = ButtonBarType.FeedBar(
|
||||||
// icon = feed.icon ?: "",
|
title = feed.name,
|
||||||
|
important = feed.important ?: 0,
|
||||||
icon = if (feed.icon == null) {
|
icon = if (feed.icon == null) {
|
||||||
null
|
null
|
||||||
} else {
|
} else {
|
||||||
|
@ -37,12 +38,11 @@ fun ColumnScope.FeedList(
|
||||||
).asImageBitmap()
|
).asImageBitmap()
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
content = feed.name,
|
),
|
||||||
important = feed.important ?: 0
|
onClick = {
|
||||||
)
|
onClick(feed)
|
||||||
) {
|
},
|
||||||
onClick(feed)
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,25 +99,27 @@ fun FeedPage(
|
||||||
) {
|
) {
|
||||||
item {
|
item {
|
||||||
Spacer(modifier = Modifier.height(114.dp))
|
Spacer(modifier = Modifier.height(114.dp))
|
||||||
FeedBar(
|
ButtonBar(
|
||||||
barButtonType = ButtonType(
|
buttonBarType = ButtonBarType.FilterBar(
|
||||||
content = filter.title,
|
title = filter.title,
|
||||||
important = viewState.filterImportant
|
important = viewState.filterImportant,
|
||||||
)
|
),
|
||||||
) {
|
onClick = {
|
||||||
groupAndFeedOnClick(null, null)
|
groupAndFeedOnClick(null, null)
|
||||||
}
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
item {
|
item {
|
||||||
Spacer(modifier = Modifier.height(10.dp))
|
Spacer(modifier = Modifier.height(10.dp))
|
||||||
FeedBar(
|
ButtonBar(
|
||||||
barButtonType = FirstExpandType(
|
buttonBarType = ButtonBarType.AllBar(
|
||||||
content = "Feeds",
|
title = "Feeds",
|
||||||
icon = Icons.Rounded.ExpandMore
|
icon = Icons.Rounded.ExpandMore
|
||||||
)
|
),
|
||||||
) {
|
onClick = {
|
||||||
viewModel.dispatch(FeedViewAction.ChangeGroupVisible(!viewState.groupsVisible))
|
viewModel.dispatch(FeedViewAction.ChangeGroupVisible)
|
||||||
}
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
itemsIndexed(viewState.groupWithFeedList) { index, groupWithFeed ->
|
itemsIndexed(viewState.groupWithFeedList) { index, groupWithFeed ->
|
||||||
GroupList(
|
GroupList(
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package me.ash.reader.ui.page.home.feed
|
package me.ash.reader.ui.page.home.feed
|
||||||
|
|
||||||
import android.view.HapticFeedbackConstants
|
import android.view.HapticFeedbackConstants
|
||||||
import androidx.compose.foundation.layout.size
|
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.outlined.Settings
|
import androidx.compose.material.icons.outlined.Settings
|
||||||
import androidx.compose.material.icons.rounded.Add
|
import androidx.compose.material.icons.rounded.Add
|
||||||
|
@ -11,9 +10,7 @@ import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.SmallTopAppBar
|
import androidx.compose.material3.SmallTopAppBar
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.platform.LocalView
|
import androidx.compose.ui.platform.LocalView
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import androidx.navigation.NavHostController
|
import androidx.navigation.NavHostController
|
||||||
import me.ash.reader.ui.page.common.RouteName
|
import me.ash.reader.ui.page.common.RouteName
|
||||||
|
|
||||||
|
@ -33,7 +30,7 @@ fun FeedPageTopBar(
|
||||||
navController.navigate(route = RouteName.SETTINGS)
|
navController.navigate(route = RouteName.SETTINGS)
|
||||||
}) {
|
}) {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.size(22.dp),
|
// modifier = Modifier.size(22.dp),
|
||||||
imageVector = Icons.Outlined.Settings,
|
imageVector = Icons.Outlined.Settings,
|
||||||
contentDescription = "Back",
|
contentDescription = "Back",
|
||||||
tint = MaterialTheme.colorScheme.primary
|
tint = MaterialTheme.colorScheme.primary
|
||||||
|
@ -47,7 +44,7 @@ fun FeedPageTopBar(
|
||||||
syncOnClick()
|
syncOnClick()
|
||||||
}) {
|
}) {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.size(26.dp),
|
// modifier = Modifier.size(26.dp),
|
||||||
imageVector = Icons.Rounded.Refresh,
|
imageVector = Icons.Rounded.Refresh,
|
||||||
contentDescription = "Sync",
|
contentDescription = "Sync",
|
||||||
tint = MaterialTheme.colorScheme.primary,
|
tint = MaterialTheme.colorScheme.primary,
|
||||||
|
@ -58,7 +55,7 @@ fun FeedPageTopBar(
|
||||||
subscribeOnClick()
|
subscribeOnClick()
|
||||||
}) {
|
}) {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.size(26.dp),
|
// modifier = Modifier.size(26.dp),
|
||||||
imageVector = Icons.Rounded.Add,
|
imageVector = Icons.Rounded.Add,
|
||||||
contentDescription = "Subscribe",
|
contentDescription = "Subscribe",
|
||||||
tint = MaterialTheme.colorScheme.primary,
|
tint = MaterialTheme.colorScheme.primary,
|
||||||
|
|
|
@ -31,7 +31,7 @@ class FeedViewModel @Inject constructor(
|
||||||
is FeedViewAction.FetchData -> fetchData(action.isStarred, action.isUnread)
|
is FeedViewAction.FetchData -> fetchData(action.isStarred, action.isUnread)
|
||||||
is FeedViewAction.AddFromFile -> addFromFile(action.inputStream)
|
is FeedViewAction.AddFromFile -> addFromFile(action.inputStream)
|
||||||
is FeedViewAction.ChangeFeedVisible -> changeFeedVisible(action.index)
|
is FeedViewAction.ChangeFeedVisible -> changeFeedVisible(action.index)
|
||||||
is FeedViewAction.ChangeGroupVisible -> changeGroupVisible(action.visible)
|
is FeedViewAction.ChangeGroupVisible -> changeGroupVisible()
|
||||||
is FeedViewAction.ScrollToItem -> scrollToItem(action.index)
|
is FeedViewAction.ScrollToItem -> scrollToItem(action.index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -121,10 +121,10 @@ class FeedViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun changeGroupVisible(visible: Boolean) {
|
private fun changeGroupVisible() {
|
||||||
_viewState.update {
|
_viewState.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
groupsVisible = visible
|
groupsVisible = !_viewState.value.groupsVisible
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -163,9 +163,7 @@ sealed class FeedViewAction {
|
||||||
val index: Int
|
val index: Int
|
||||||
) : FeedViewAction()
|
) : FeedViewAction()
|
||||||
|
|
||||||
data class ChangeGroupVisible(
|
object ChangeGroupVisible : FeedViewAction()
|
||||||
val visible: Boolean
|
|
||||||
) : FeedViewAction()
|
|
||||||
|
|
||||||
data class ScrollToItem(
|
data class ScrollToItem(
|
||||||
val index: Int
|
val index: Int
|
||||||
|
|
|
@ -18,7 +18,7 @@ fun ColumnScope.GroupList(
|
||||||
feedVisible: Boolean,
|
feedVisible: Boolean,
|
||||||
groupWithFeed: GroupWithFeed,
|
groupWithFeed: GroupWithFeed,
|
||||||
groupAndFeedOnClick: (currentGroup: Group?, currentFeed: Feed?) -> Unit = { _, _ -> },
|
groupAndFeedOnClick: (currentGroup: Group?, currentFeed: Feed?) -> Unit = { _, _ -> },
|
||||||
expandOnClick: () -> Unit
|
expandOnClick: () -> Unit,
|
||||||
) {
|
) {
|
||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
visible = groupVisible,
|
visible = groupVisible,
|
||||||
|
@ -26,16 +26,17 @@ fun ColumnScope.GroupList(
|
||||||
exit = fadeOut() + shrinkVertically(),
|
exit = fadeOut() + shrinkVertically(),
|
||||||
) {
|
) {
|
||||||
Column(modifier = modifier) {
|
Column(modifier = modifier) {
|
||||||
FeedBar(
|
ButtonBar(
|
||||||
barButtonType = SecondExpandType(
|
buttonBarType = ButtonBarType.GroupBar(
|
||||||
content = groupWithFeed.group.name,
|
title = groupWithFeed.group.name,
|
||||||
icon = Icons.Rounded.ExpandMore,
|
icon = Icons.Rounded.ExpandMore,
|
||||||
important = groupWithFeed.group.important ?: 0,
|
important = groupWithFeed.group.important ?: 0,
|
||||||
|
iconOnClick = expandOnClick,
|
||||||
),
|
),
|
||||||
iconOnClickListener = expandOnClick
|
onClick = {
|
||||||
) {
|
groupAndFeedOnClick(groupWithFeed.group, null)
|
||||||
groupAndFeedOnClick(groupWithFeed.group, null)
|
}
|
||||||
}
|
)
|
||||||
FeedList(
|
FeedList(
|
||||||
visible = feedVisible,
|
visible = feedVisible,
|
||||||
feeds = groupWithFeed.feeds,
|
feeds = groupWithFeed.feeds,
|
||||||
|
|
|
@ -40,7 +40,7 @@ fun ReadPageTopBar(
|
||||||
view.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP)
|
view.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP)
|
||||||
}) {
|
}) {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.size(20.dp),
|
// modifier = Modifier.size(20.dp),
|
||||||
imageVector = Icons.Rounded.Share,
|
imageVector = Icons.Rounded.Share,
|
||||||
contentDescription = "Share",
|
contentDescription = "Share",
|
||||||
tint = MaterialTheme.colorScheme.primary,
|
tint = MaterialTheme.colorScheme.primary,
|
||||||
|
@ -50,7 +50,7 @@ fun ReadPageTopBar(
|
||||||
view.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP)
|
view.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP)
|
||||||
}) {
|
}) {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.size(28.dp),
|
// modifier = Modifier.size(28.dp),
|
||||||
imageVector = Icons.Rounded.MoreHoriz,
|
imageVector = Icons.Rounded.MoreHoriz,
|
||||||
contentDescription = "More",
|
contentDescription = "More",
|
||||||
tint = MaterialTheme.colorScheme.primary,
|
tint = MaterialTheme.colorScheme.primary,
|
||||||
|
|
53
app/src/main/java/me/ash/reader/ui/widget/Menu.kt
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
package me.ash.reader.ui.widget
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.material3.DropdownMenu
|
||||||
|
import androidx.compose.material3.DropdownMenuItem
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.unit.DpOffset
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun Menu(
|
||||||
|
offset: DpOffset,
|
||||||
|
expanded: Boolean,
|
||||||
|
dismissFunction: () -> Unit = {},
|
||||||
|
) {
|
||||||
|
Box {
|
||||||
|
DropdownMenu(
|
||||||
|
// modifier = Modifier.offset(offset.x.dp, offset.y.dp),
|
||||||
|
offset = offset,
|
||||||
|
expanded = expanded,
|
||||||
|
onDismissRequest = dismissFunction,
|
||||||
|
) {
|
||||||
|
DropdownMenuItem(
|
||||||
|
text = {
|
||||||
|
Text(text = "打开")
|
||||||
|
},
|
||||||
|
onClick = {
|
||||||
|
}
|
||||||
|
)
|
||||||
|
DropdownMenuItem(
|
||||||
|
text = {
|
||||||
|
Text(text = "取消订阅")
|
||||||
|
},
|
||||||
|
onClick = {
|
||||||
|
}
|
||||||
|
)
|
||||||
|
DropdownMenuItem(
|
||||||
|
text = {
|
||||||
|
Text(text = "编辑")
|
||||||
|
},
|
||||||
|
onClick = {
|
||||||
|
}
|
||||||
|
)
|
||||||
|
DropdownMenuItem(
|
||||||
|
text = {
|
||||||
|
Text(text = "默认全文解析")
|
||||||
|
},
|
||||||
|
onClick = {
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<background android:drawable="@drawable/ic_launcher_background" />
|
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
|
||||||
</adaptive-icon>
|
|
|
@ -1,5 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<background android:drawable="@drawable/ic_launcher_background" />
|
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
|
||||||
</adaptive-icon>
|
|
BIN
app/src/main/res/mipmap-hdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 2.8 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 982 B |
Before Width: | Height: | Size: 1.7 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 3.8 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 7.8 KiB |
Before Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 5.8 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 7.6 KiB |