|
|
|
@ -9,6 +9,8 @@ import androidx.compose.foundation.layout.* |
|
|
|
|
import androidx.compose.foundation.lazy.LazyColumn |
|
|
|
|
import androidx.compose.foundation.lazy.items |
|
|
|
|
import androidx.compose.foundation.shape.CircleShape |
|
|
|
|
import androidx.compose.material.Colors |
|
|
|
|
import androidx.compose.material.MaterialTheme |
|
|
|
|
import androidx.compose.material.Text |
|
|
|
|
import androidx.compose.runtime.* |
|
|
|
|
import androidx.compose.ui.Alignment |
|
|
|
@ -18,8 +20,10 @@ import androidx.compose.ui.graphics.Color |
|
|
|
|
import androidx.compose.ui.graphics.Shape |
|
|
|
|
import androidx.compose.ui.layout.ContentScale |
|
|
|
|
import androidx.compose.ui.platform.LocalContext |
|
|
|
|
import androidx.compose.ui.platform.LocalLifecycleOwner |
|
|
|
|
import androidx.compose.ui.text.style.TextAlign |
|
|
|
|
import androidx.compose.ui.tooling.preview.Preview |
|
|
|
|
import androidx.compose.ui.unit.Dp |
|
|
|
|
import androidx.compose.ui.unit.TextUnit |
|
|
|
|
import androidx.compose.ui.unit.dp |
|
|
|
|
import androidx.compose.ui.unit.sp |
|
|
|
|
import coil.compose.AsyncImage |
|
|
|
@ -27,12 +31,18 @@ import coil.decode.BitmapFactoryDecoder |
|
|
|
|
import coil.request.ImageRequest |
|
|
|
|
import com.dfsek.feldspar.AppState |
|
|
|
|
import com.dfsek.feldspar.ui.RoomActivity |
|
|
|
|
import com.dfsek.feldspar.util.DynamicContent |
|
|
|
|
import com.dfsek.feldspar.util.compose_fixes.FixedDefaultFlingBehavior |
|
|
|
|
import com.dfsek.feldspar.util.getAvatarUrl |
|
|
|
|
import com.dfsek.feldspar.util.getPreviewText |
|
|
|
|
import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams |
|
|
|
|
import org.matrix.android.sdk.api.session.room.model.RoomSummary |
|
|
|
|
import kotlin.math.floor |
|
|
|
|
import kotlin.random.Random |
|
|
|
|
import kotlin.time.Duration |
|
|
|
|
import kotlin.time.Duration.Companion.milliseconds |
|
|
|
|
import kotlin.time.DurationUnit |
|
|
|
|
import kotlin.time.ExperimentalTime |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
val colors = listOf( |
|
|
|
@ -71,16 +81,47 @@ fun Avatar(mxUrl: String?, size: Int, clip: Shape = CircleShape, name: String? = |
|
|
|
|
contentAlignment = Alignment.Center |
|
|
|
|
) { |
|
|
|
|
name?.let { |
|
|
|
|
Text(it.substring(0, 1), |
|
|
|
|
Text( |
|
|
|
|
it.substring(0, 1), |
|
|
|
|
modifier = Modifier.align(Alignment.Center), |
|
|
|
|
fontSize = (floor(size * 0.75).sp), |
|
|
|
|
textAlign = TextAlign.Center, |
|
|
|
|
color = Color.White) |
|
|
|
|
color = Color.White |
|
|
|
|
) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Composable |
|
|
|
|
fun OnlineIndicator(room: RoomSummary, size: Dp, modifier: Modifier = Modifier) { |
|
|
|
|
val onlineColor = if (room.directUserPresence?.isCurrentlyActive == true) Color.Green else Color.Gray |
|
|
|
|
Box( |
|
|
|
|
modifier = modifier |
|
|
|
|
.size(size) |
|
|
|
|
.clip(CircleShape) |
|
|
|
|
.background(onlineColor), |
|
|
|
|
contentAlignment = Alignment.Center |
|
|
|
|
) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Composable |
|
|
|
|
fun LastOnline(room: RoomSummary, size: TextUnit, modifier: Modifier) { |
|
|
|
|
if(room.directUserPresence?.isCurrentlyActive == true) return |
|
|
|
|
room.directUserPresence?.lastActiveAgo?.let { |
|
|
|
|
it.milliseconds.toComponents { days, hours, minutes, seconds, _ -> |
|
|
|
|
if(days > 0) "$days D" |
|
|
|
|
else if(hours > 0) "$hours H" |
|
|
|
|
else if(minutes > 0) "$minutes M" |
|
|
|
|
else if(seconds > 0) "$seconds S" |
|
|
|
|
else null |
|
|
|
|
}?.let { |
|
|
|
|
Text(it, fontSize = size, color = MaterialTheme.colors.onSurface, modifier = modifier) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Composable |
|
|
|
|
fun Activity.RoomEntry(room: RoomSummary) { |
|
|
|
|
Row(modifier = Modifier.clickable { |
|
|
|
@ -90,7 +131,12 @@ fun Activity.RoomEntry(room: RoomSummary) { |
|
|
|
|
}.fillMaxWidth()) { |
|
|
|
|
val name = remember { room.displayName } |
|
|
|
|
val lastContent = remember { room.latestPreviewableEvent } |
|
|
|
|
Avatar(room.avatarUrl, AppState.Preferences.dmAvatarSize, name = room.displayName) |
|
|
|
|
Box { |
|
|
|
|
Avatar(room.avatarUrl, AppState.Preferences.dmAvatarSize, name = room.displayName) |
|
|
|
|
if (room.isDirect) { |
|
|
|
|
OnlineIndicator(room, (AppState.Preferences.dmAvatarSize * 0.25).dp, modifier = Modifier.align(Alignment.BottomEnd)) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Column { |
|
|
|
|
Text(name, fontSize = 18.sp) |
|
|
|
@ -105,20 +151,16 @@ fun Activity.RoomList( |
|
|
|
|
filter: (List<RoomSummary>) -> List<RoomSummary> |
|
|
|
|
) { |
|
|
|
|
AppState.session?.let { session -> |
|
|
|
|
val lifecycleOwner = LocalLifecycleOwner.current |
|
|
|
|
var rooms: List<RoomSummary> by remember { mutableStateOf(emptyList()) } |
|
|
|
|
LaunchedEffect(session) { |
|
|
|
|
session.roomService().getRoomSummariesLive(queryParams) |
|
|
|
|
.observe(lifecycleOwner) { |
|
|
|
|
rooms = filter(it) |
|
|
|
|
DynamicContent(session, { session.roomService().getRoomSummariesLive(queryParams) }) { |
|
|
|
|
val rooms = filter(it) |
|
|
|
|
val fling = FixedDefaultFlingBehavior.fixedFlingBehavior() |
|
|
|
|
LazyColumn(flingBehavior = fling) { |
|
|
|
|
items(rooms, key = { |
|
|
|
|
it.roomId |
|
|
|
|
}) { |
|
|
|
|
Log.d("ROOM", it.roomId) |
|
|
|
|
RoomEntry(it) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
LazyColumn { |
|
|
|
|
items(rooms, key = { |
|
|
|
|
it.roomId |
|
|
|
|
}) { |
|
|
|
|
Log.d("ROOM", it.roomId) |
|
|
|
|
RoomEntry(it) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|