Compare commits
No commits in common. "e70049f1f5feafd4389a93699df6ca0b9accc1b5" and "dc588a045d1076d82fc5de3cd522cf7f50749c24" have entirely different histories.
e70049f1f5
...
dc588a045d
6
.idea/copyright/profiles_settings.xml
generated
6
.idea/copyright/profiles_settings.xml
generated
@ -1,3 +1,7 @@
|
||||
<component name="CopyrightManager">
|
||||
<settings default="My" />
|
||||
<settings default="My">
|
||||
<module2copyright>
|
||||
<element module="All" copyright="My" />
|
||||
</module2copyright>
|
||||
</settings>
|
||||
</component>
|
8
.idea/deploymentTargetSelector.xml
generated
8
.idea/deploymentTargetSelector.xml
generated
@ -4,14 +4,6 @@
|
||||
<selectionStates>
|
||||
<SelectionState runConfigName="app">
|
||||
<option name="selectionMode" value="DROPDOWN" />
|
||||
<DropdownSelection timestamp="2025-02-22T11:46:39.159466074Z">
|
||||
<Target type="DEFAULT_BOOT">
|
||||
<handle>
|
||||
<DeviceId pluginId="PhysicalDevice" identifier="serial=22163a3c" />
|
||||
</handle>
|
||||
</Target>
|
||||
</DropdownSelection>
|
||||
<DialogSelection />
|
||||
</SelectionState>
|
||||
</selectionStates>
|
||||
</component>
|
||||
|
2
.idea/kotlinc.xml
generated
2
.idea/kotlinc.xml
generated
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="KotlinJpsPluginSettings">
|
||||
<option name="version" value="2.0.21" />
|
||||
<option name="version" value="2.0.0" />
|
||||
</component>
|
||||
</project>
|
@ -1,14 +1,13 @@
|
||||
/*
|
||||
* Created by sweetbread on 22.02.2025, 15:45
|
||||
* Created by sweetbread on 21.02.2025, 12:01
|
||||
* Copyright (c) 2025. All rights reserved.
|
||||
* Last modified 22.02.2025, 14:56
|
||||
* Last modified 21.02.2025, 12:01
|
||||
*/
|
||||
|
||||
plugins {
|
||||
alias(libs.plugins.android.application)
|
||||
alias(libs.plugins.kotlin.android)
|
||||
alias(libs.plugins.kotlin.compose)
|
||||
id("com.google.devtools.ksp")
|
||||
}
|
||||
|
||||
android {
|
||||
@ -35,11 +34,11 @@ android {
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = "17"
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
buildFeatures {
|
||||
compose = true
|
||||
@ -65,18 +64,11 @@ dependencies {
|
||||
|
||||
// Ktor - web client
|
||||
implementation(libs.ktor.client.core)
|
||||
implementation(libs.ktor.client.okhttp)
|
||||
implementation(libs.ktor.client.logging)
|
||||
implementation(libs.ktor.client.cio)
|
||||
|
||||
// Coil - image loader
|
||||
implementation(libs.coil.compose)
|
||||
implementation(libs.coil.network.okhttp)
|
||||
|
||||
// Room - database
|
||||
implementation(libs.androidx.room.runtime)
|
||||
implementation(libs.androidx.lifecycle.viewmodel.ktx)
|
||||
implementation(libs.androidx.room.ktx)
|
||||
ksp(libs.androidx.room.compiler)
|
||||
|
||||
// Others
|
||||
implementation(libs.splitties.base) // Syntax sugar
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Created by sweetbread on 22.02.2025, 15:45
|
||||
~ Created by sweetbread on 21.02.2025, 12:08
|
||||
~ Copyright (c) 2025. All rights reserved.
|
||||
~ Last modified 22.02.2025, 14:00
|
||||
~ Last modified 21.02.2025, 12:07
|
||||
-->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
@ -22,7 +22,13 @@
|
||||
tools:targetApi="31">
|
||||
<activity
|
||||
android:name=".ui.activity.Login"
|
||||
android:exported="false"
|
||||
android:label="@string/title_activity_login"
|
||||
android:theme="@style/Theme.PixelDragon" />
|
||||
<activity
|
||||
android:name=".ui.activity.MainActivity"
|
||||
android:exported="true"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/Theme.PixelDragon">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
@ -30,11 +36,6 @@
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".ui.activity.MainActivity"
|
||||
android:exported="false"
|
||||
android:theme="@style/Theme.PixelDragon" />
|
||||
</application>
|
||||
|
||||
</manifest>
|
@ -1,55 +1,43 @@
|
||||
/*
|
||||
* Created by sweetbread on 22.02.2025, 15:45
|
||||
* Created by sweetbread on 21.02.2025, 12:01
|
||||
* Copyright (c) 2025. All rights reserved.
|
||||
* Last modified 22.02.2025, 15:45
|
||||
* Last modified 21.02.2025, 12:01
|
||||
*/
|
||||
|
||||
package ru.risdeveau.pixeldragon
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import androidx.room.Room
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.engine.cio.CIO
|
||||
import io.ktor.client.engine.cio.endpoint
|
||||
import io.ktor.client.plugins.cache.HttpCache
|
||||
import io.ktor.client.plugins.logging.LogLevel
|
||||
import io.ktor.client.plugins.logging.Logger
|
||||
import io.ktor.client.plugins.logging.Logging
|
||||
import ru.risdeveau.pixeldragon.api.getMe
|
||||
import ru.risdeveau.pixeldragon.db.AppDatabase
|
||||
import splitties.init.appCtx
|
||||
|
||||
val client = HttpClient {
|
||||
install(Logging) {
|
||||
logger = object : Logger {
|
||||
override fun log(message: String) {
|
||||
Log.i("Ktor", message)
|
||||
}
|
||||
val client = HttpClient(CIO) {
|
||||
engine {
|
||||
endpoint {
|
||||
maxConnectionsPerRoute = 100
|
||||
pipelineMaxSize = 20
|
||||
keepAliveTime = 30000
|
||||
connectTimeout = 15000
|
||||
connectAttempts = 5
|
||||
}
|
||||
level = LogLevel.ALL
|
||||
}
|
||||
|
||||
install(HttpCache)
|
||||
}
|
||||
|
||||
val accountData = appCtx.getSharedPreferences("settings", Context.MODE_PRIVATE)
|
||||
lateinit var homeserver: String
|
||||
lateinit var baseUrl: String
|
||||
lateinit var urlBase: String
|
||||
lateinit var token: String
|
||||
|
||||
suspend fun initCheck(): Boolean {
|
||||
Log.d("initCheck", "checking...")
|
||||
|
||||
if (!accountData.contains("token")) return false
|
||||
if (!accountData.contains("homeserver")) return false
|
||||
|
||||
token = accountData.getString("token", "").toString()
|
||||
homeserver = accountData.getString("homeserver", "").toString()
|
||||
baseUrl = "https://$homeserver/_matrix/client/v3"
|
||||
urlBase = "https://${accountData.getString("homeserver", "")}/_matrix/client/v3"
|
||||
|
||||
return getMe() != null
|
||||
}
|
||||
|
||||
val db = Room.databaseBuilder(
|
||||
appCtx,
|
||||
AppDatabase::class.java, "database"
|
||||
).build()
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Created by sweetbread
|
||||
* Copyright (c) 2025. All rights reserved.
|
||||
* Last modified 22.02.2025, 19:52
|
||||
*/
|
||||
|
||||
package ru.risdeveau.pixeldragon.api
|
||||
|
||||
import io.ktor.client.request.bearerAuth
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.statement.bodyAsText
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import org.json.JSONObject
|
||||
import ru.risdeveau.pixeldragon.baseUrl
|
||||
import ru.risdeveau.pixeldragon.client
|
||||
import ru.risdeveau.pixeldragon.db
|
||||
import ru.risdeveau.pixeldragon.db.Room
|
||||
import ru.risdeveau.pixeldragon.token
|
||||
|
||||
//fun getRooms(): List<Room> {
|
||||
// return db.roomDoa().getAllJoined()
|
||||
//}
|
||||
//
|
||||
//fun updateRooms(): List<Room> {
|
||||
//
|
||||
//}
|
||||
|
||||
suspend fun getRooms(): List<String> {
|
||||
val r = client.get("$baseUrl/joined_rooms")
|
||||
{ bearerAuth(token) }
|
||||
val rooms = JSONObject(r.bodyAsText()).getJSONArray("joined_rooms")
|
||||
return List<String>(
|
||||
rooms.length()
|
||||
) { i -> rooms.getString(i) }
|
||||
}
|
||||
|
||||
suspend fun getRoom(rid: String): Room {
|
||||
var room = db.roomDoa().getById(rid)
|
||||
if (room == null) {
|
||||
val name = getState(rid, "m.room.name", "name")
|
||||
val type = getState(rid, "m.room.create", "type") ?: "m.room"
|
||||
val creator = getState(rid, "m.room.create", "creator")
|
||||
val avatar = getState(rid, "m.room.avatar", "url")
|
||||
room = Room(rid, name, type, creator, null, avatar, null, true)
|
||||
db.roomDoa().insert(room)
|
||||
}
|
||||
|
||||
return room
|
||||
}
|
||||
|
||||
private suspend fun getState(rid: String, state: String, key: String): String? {
|
||||
val r = client.get("$baseUrl/rooms/$rid/state/$state") { bearerAuth(token) }
|
||||
if (r.status != HttpStatusCode.OK) return null
|
||||
val json = JSONObject(r.bodyAsText())
|
||||
if (!json.has(key)) return null
|
||||
return json.getString(key)
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Created by sweetbread on 22.02.2025, 17:28
|
||||
* Created by sweetbread on 21.02.2025, 12:01
|
||||
* Copyright (c) 2025. All rights reserved.
|
||||
* Last modified 22.02.2025, 17:28
|
||||
* Last modified 21.02.2025, 12:01
|
||||
*/
|
||||
|
||||
package ru.risdeveau.pixeldragon.api
|
||||
@ -11,7 +11,6 @@ import io.ktor.client.statement.bodyAsText
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
import ru.risdeveau.pixeldragon.client
|
||||
import ru.risdeveau.pixeldragon.homeserver
|
||||
|
||||
suspend fun isMatrixServer(url: String): Boolean {
|
||||
val r = try { client.get("https://$url/.well-known/matrix/client") }
|
||||
@ -21,11 +20,4 @@ suspend fun isMatrixServer(url: String): Boolean {
|
||||
catch (_: JSONException) { return false }
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
fun mxcToUrl(mxc: String): String {
|
||||
val pattern = Regex("mxc://([-a-zA-Z0-9@:%._+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6})/([a-zA-Z]+)")
|
||||
val match = pattern.find(mxc)
|
||||
|
||||
return "https://$homeserver/_matrix/client/v1/media/download/${match?.groupValues[1]}/${match?.groupValues[2]}"
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Created by sweetbread on 22.02.2025, 15:45
|
||||
* Created by sweetbread on 21.02.2025, 12:09
|
||||
* Copyright (c) 2025. All rights reserved.
|
||||
* Last modified 22.02.2025, 15:45
|
||||
* Last modified 21.02.2025, 12:01
|
||||
*/
|
||||
|
||||
package ru.risdeveau.pixeldragon.api
|
||||
@ -18,10 +18,10 @@ import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.http.contentType
|
||||
import org.json.JSONObject
|
||||
import ru.risdeveau.pixeldragon.accountData
|
||||
import ru.risdeveau.pixeldragon.baseUrl
|
||||
import ru.risdeveau.pixeldragon.client
|
||||
import ru.risdeveau.pixeldragon.initCheck
|
||||
import ru.risdeveau.pixeldragon.token
|
||||
import ru.risdeveau.pixeldragon.urlBase
|
||||
import splitties.init.appCtx
|
||||
|
||||
data class Me (val userId: String, val deviceId: String)
|
||||
@ -30,7 +30,7 @@ data class Me (val userId: String, val deviceId: String)
|
||||
* This func is to validate the token
|
||||
*/
|
||||
suspend fun getMe(): Me? {
|
||||
val r = client.get("$baseUrl/account/whoami") { bearerAuth(token) }
|
||||
val r = client.get("$urlBase/account/whoami") { bearerAuth(token) }
|
||||
if (r.status != HttpStatusCode.OK) {
|
||||
Log.e("getMe", r.bodyAsText())
|
||||
return null
|
||||
|
@ -1,81 +0,0 @@
|
||||
/*
|
||||
* Created by sweetbread
|
||||
* Copyright (c) 2025. All rights reserved.
|
||||
* Last modified 22.02.2025, 19:49
|
||||
*/
|
||||
|
||||
package ru.risdeveau.pixeldragon.db
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Database
|
||||
import androidx.room.Delete
|
||||
import androidx.room.Embedded
|
||||
import androidx.room.Entity
|
||||
import androidx.room.Insert
|
||||
import androidx.room.Junction
|
||||
import androidx.room.PrimaryKey
|
||||
import androidx.room.Query
|
||||
import androidx.room.Relation
|
||||
import androidx.room.RoomDatabase
|
||||
|
||||
@Entity
|
||||
data class Room(
|
||||
@PrimaryKey val roomId: String,
|
||||
val name: String?,
|
||||
val type: String,
|
||||
val creatorId: String?,
|
||||
val createTime: Long?,
|
||||
val avatarUrl: String?,
|
||||
val members: Int?,
|
||||
val joined: Boolean
|
||||
)
|
||||
|
||||
@Dao
|
||||
interface RoomDao {
|
||||
// @Query("SELECT * FROM room")
|
||||
// fun getAll(): List<User>
|
||||
|
||||
// @Query("SELECT * FROM user WHERE uid IN (:userIds)")
|
||||
// fun loadAllByIds(userIds: IntArray): List<User>
|
||||
|
||||
// @Query("SELECT * FROM user WHERE first_name LIKE :first AND " +
|
||||
// "last_name LIKE :last LIMIT 1")
|
||||
// fun findByName(first: String, last: String): User
|
||||
|
||||
@Query("SELECT * FROM room WHERE roomId LIKE :rid LIMIT 1")
|
||||
fun getById(rid: String): Room?
|
||||
|
||||
// @Transaction
|
||||
// @Query("SELECT * FROM room WHERE ")
|
||||
// fun getSpace(rid: String): Space
|
||||
|
||||
@Query("SELECT * FROM room WHERE joined = 1 AND roomId NOT IN (SELECT roomId FROM SpaceToRoom)")
|
||||
fun getAllJoined(): List<Room>
|
||||
|
||||
@Insert
|
||||
fun insert(vararg rooms: Room)
|
||||
|
||||
@Delete
|
||||
fun delete(room: Room)
|
||||
}
|
||||
|
||||
@Entity(primaryKeys = ["spaceId", "roomId"])
|
||||
data class SpaceToRoom(
|
||||
val spaceId: String,
|
||||
val roomId: String
|
||||
)
|
||||
|
||||
data class Space(
|
||||
@Embedded val space: Room,
|
||||
@Relation(
|
||||
parentColumn = "spaceId",
|
||||
entityColumn = "roomId",
|
||||
associateBy = Junction(SpaceToRoom::class)
|
||||
)
|
||||
val children: List<Room>
|
||||
)
|
||||
|
||||
@Database(entities = [Room::class, SpaceToRoom::class, User::class], version = 1)
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
abstract fun roomDoa(): RoomDao
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
/*
|
||||
* Created by sweetbread on 22.02.2025, 15:45
|
||||
* Copyright (c) 2025. All rights reserved.
|
||||
* Last modified 21.02.2025, 13:38
|
||||
*/
|
||||
|
||||
package ru.risdeveau.pixeldragon.db
|
||||
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
|
||||
@Entity
|
||||
data class User(
|
||||
@PrimaryKey val uid: String,
|
||||
@ColumnInfo(name = "name") val name: String?,
|
||||
@ColumnInfo(name = "avatar") val avatar: String?
|
||||
)
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Created by sweetbread on 22.02.2025, 15:45
|
||||
* Created by sweetbread on 21.02.2025, 12:08
|
||||
* Copyright (c) 2025. All rights reserved.
|
||||
* Last modified 22.02.2025, 15:45
|
||||
* Last modified 21.02.2025, 12:08
|
||||
*/
|
||||
|
||||
package ru.risdeveau.pixeldragon.ui.activity
|
||||
@ -35,25 +35,15 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.text.input.PasswordVisualTransformation
|
||||
import androidx.compose.ui.unit.dp
|
||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import ru.risdeveau.pixeldragon.api.isMatrixServer
|
||||
import ru.risdeveau.pixeldragon.api.login
|
||||
import ru.risdeveau.pixeldragon.initCheck
|
||||
import ru.risdeveau.pixeldragon.ui.theme.PixelDragonTheme
|
||||
import splitties.activities.start
|
||||
|
||||
class Login : ComponentActivity() {
|
||||
@OptIn(DelicateCoroutinesApi::class)
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
|
||||
GlobalScope.launch {
|
||||
if (initCheck()) start<MainActivity>()
|
||||
}
|
||||
|
||||
enableEdgeToEdge()
|
||||
setContent {
|
||||
PixelDragonTheme {
|
||||
@ -66,10 +56,7 @@ class Login : ComponentActivity() {
|
||||
SnackbarHost(hostState = snackbarHostState)
|
||||
}
|
||||
) { innerPadding ->
|
||||
Box(
|
||||
Modifier
|
||||
.fillMaxSize()
|
||||
.padding(innerPadding)) {
|
||||
Box(Modifier.fillMaxSize().padding(innerPadding)) {
|
||||
LoginField(
|
||||
Modifier.align(Alignment.Center),
|
||||
{ start<MainActivity>() },
|
||||
@ -132,10 +119,11 @@ fun LoginField(modifier: Modifier = Modifier, ok: () -> Unit, err: () -> Unit) {
|
||||
Button(
|
||||
enabled = hmsValid && !login.isEmpty() && !pass.isEmpty(),
|
||||
onClick = {
|
||||
scope.launch {
|
||||
if (login(homeserver, login, pass)) ok()
|
||||
else err()
|
||||
}
|
||||
var loginSuccess = false
|
||||
scope.launch { loginSuccess = login(homeserver, login, pass) }
|
||||
|
||||
if (loginSuccess) ok()
|
||||
else err()
|
||||
}
|
||||
) {
|
||||
Text("Login")
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Created by sweetbread
|
||||
* Created by sweetbread on 21.02.2025, 12:08
|
||||
* Copyright (c) 2025. All rights reserved.
|
||||
* Last modified 22.02.2025, 20:24
|
||||
* Last modified 21.02.2025, 12:07
|
||||
*/
|
||||
|
||||
package ru.risdeveau.pixeldragon.ui.activity
|
||||
@ -10,56 +10,31 @@ import android.os.Bundle
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.LinearProgressIndicator
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.material3.TopAppBarDefaults.topAppBarColors
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.unit.dp
|
||||
import coil3.compose.SubcomposeAsyncImage
|
||||
import coil3.network.NetworkHeaders
|
||||
import coil3.network.httpHeaders
|
||||
import coil3.request.ImageRequest
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import ru.risdeveau.pixeldragon.api.getRoom
|
||||
import ru.risdeveau.pixeldragon.api.getRooms
|
||||
import ru.risdeveau.pixeldragon.api.mxcToUrl
|
||||
import ru.risdeveau.pixeldragon.db.Room
|
||||
import ru.risdeveau.pixeldragon.token
|
||||
import ru.risdeveau.pixeldragon.initCheck
|
||||
import ru.risdeveau.pixeldragon.ui.theme.PixelDragonTheme
|
||||
import splitties.init.appCtx
|
||||
import splitties.activities.start
|
||||
|
||||
class MainActivity : ComponentActivity() {
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@OptIn(ExperimentalMaterial3Api::class, DelicateCoroutinesApi::class)
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
GlobalScope.launch {
|
||||
if (!initCheck()) start<Login>()
|
||||
}
|
||||
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
enableEdgeToEdge()
|
||||
@ -79,123 +54,28 @@ class MainActivity : ComponentActivity() {
|
||||
)
|
||||
},
|
||||
) { innerPadding ->
|
||||
RoomList(Modifier.padding(innerPadding))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun RoomList(modifier: Modifier = Modifier) {
|
||||
var list by remember { mutableStateOf(listOf<String>()) }
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
val listState = rememberLazyListState()
|
||||
|
||||
// if (itemState.scrollToTop) {
|
||||
// LaunchedEffect(coroutineScope) {
|
||||
// Log.e("TAG", "TopCoinsScreen: scrollToTop" )
|
||||
// listState.scrollToItem(0)
|
||||
// }
|
||||
// }
|
||||
|
||||
LaunchedEffect(true) {
|
||||
coroutineScope.launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
list = getRooms()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LazyColumn(modifier = modifier, state = listState) {
|
||||
items(list) { rid ->
|
||||
RoomItem(rid = rid)
|
||||
}
|
||||
|
||||
item {
|
||||
if (list.isEmpty()) {
|
||||
Text("You have no rooms")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun RoomItem(modifier: Modifier = Modifier, rid: String) {
|
||||
var room by remember { mutableStateOf<Room?>(null) }
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
LaunchedEffect(true) {
|
||||
scope.launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
room = getRoom(rid)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (room != null) {
|
||||
Row(
|
||||
modifier
|
||||
.padding(8.dp)
|
||||
.height(80.dp)
|
||||
.fillMaxWidth()
|
||||
.background(MaterialTheme.colorScheme.primaryContainer, RoundedCornerShape(16.dp))
|
||||
.padding(8.dp)
|
||||
) {
|
||||
SubcomposeAsyncImage(
|
||||
modifier = Modifier
|
||||
.padding(end = 4.dp)
|
||||
.height(64.dp)
|
||||
.width(64.dp)
|
||||
.let {
|
||||
if (room!!.type == "m.space")
|
||||
it.clip(RoundedCornerShape(12.dp))
|
||||
else
|
||||
it.clip(CircleShape)
|
||||
},
|
||||
model = ImageRequest.Builder(appCtx)
|
||||
.data(mxcToUrl(room!!.avatarUrl ?: ""))
|
||||
.httpHeaders(
|
||||
NetworkHeaders.Builder()
|
||||
.set("Authorization", "Bearer $token")
|
||||
.set("Cache-Control", "max-age=86400")
|
||||
.build()
|
||||
Greeting(
|
||||
name = "Android",
|
||||
modifier = Modifier.padding(innerPadding)
|
||||
)
|
||||
.build(),
|
||||
contentDescription = room!!.roomId,
|
||||
contentScale = ContentScale.Crop,
|
||||
loading = {
|
||||
CircularProgressIndicator()
|
||||
}
|
||||
)
|
||||
Column {
|
||||
Text(
|
||||
room!!.name ?: "Unnamed",
|
||||
maxLines = 1,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
fontSize = MaterialTheme.typography.titleLarge.fontSize
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Row(
|
||||
modifier
|
||||
.padding(8.dp)
|
||||
.height(80.dp)
|
||||
.fillMaxWidth()
|
||||
.background(MaterialTheme.colorScheme.primaryContainer, RoundedCornerShape(16.dp))
|
||||
.padding(8.dp)
|
||||
) {
|
||||
LinearProgressIndicator(Modifier.fillMaxWidth())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//@Preview(showBackground = true)
|
||||
//@Composable
|
||||
//fun GreetingPreview() {
|
||||
// PixelDragonTheme {
|
||||
// RoomItem()
|
||||
// }
|
||||
//}
|
||||
@Composable
|
||||
fun Greeting(name: String, modifier: Modifier = Modifier) {
|
||||
Text(
|
||||
text = "Hello $name!",
|
||||
modifier = modifier
|
||||
)
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
fun GreetingPreview() {
|
||||
PixelDragonTheme {
|
||||
Greeting("Android")
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Created by sweetbread on 22.02.2025, 15:45
|
||||
* Created by sweetbread on 21.02.2025, 12:00
|
||||
* Copyright (c) 2025. All rights reserved.
|
||||
* Last modified 21.02.2025, 12:21
|
||||
* Last modified 21.02.2025, 12:00
|
||||
*/
|
||||
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
@ -9,5 +9,4 @@ plugins {
|
||||
alias(libs.plugins.android.application) apply false
|
||||
alias(libs.plugins.kotlin.android) apply false
|
||||
alias(libs.plugins.kotlin.compose) apply false
|
||||
id("com.google.devtools.ksp") version "2.0.21-1.0.27" apply false
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
[versions]
|
||||
agp = "8.7.3"
|
||||
coil = "3.1.0"
|
||||
kotlin = "2.0.21"
|
||||
kotlin = "2.0.0"
|
||||
coreKtx = "1.15.0"
|
||||
junit = "4.13.2"
|
||||
junitVersion = "1.2.1"
|
||||
@ -10,15 +10,10 @@ ktor = "3.1.0"
|
||||
lifecycleRuntimeKtx = "2.8.7"
|
||||
activityCompose = "1.10.0"
|
||||
composeBom = "2025.02.00"
|
||||
room = "2.6.1"
|
||||
splittiesFunPackAndroidBase = "3.0.0"
|
||||
|
||||
[libraries]
|
||||
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
||||
androidx-lifecycle-viewmodel-ktx = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "room" }
|
||||
androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "room" }
|
||||
androidx-room-ktx = { module = "androidx.room:room-ktx", version.ref = "room" }
|
||||
androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "room" }
|
||||
coil-compose = { module = "io.coil-kt.coil3:coil-compose", version.ref = "coil" }
|
||||
coil-network-okhttp = { module = "io.coil-kt.coil3:coil-network-okhttp", version.ref = "coil" }
|
||||
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
||||
@ -34,9 +29,8 @@ androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-toolin
|
||||
androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
|
||||
androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
|
||||
androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
|
||||
ktor-client-okhttp = { module = "io.ktor:ktor-client-okhttp", version.ref = "ktor" }
|
||||
ktor-client-cio = { module = "io.ktor:ktor-client-cio", version.ref = "ktor" }
|
||||
ktor-client-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor" }
|
||||
ktor-client-logging = { module = "io.ktor:ktor-client-logging", version.ref = "ktor" }
|
||||
splitties-base = { module = "com.louiscad.splitties:splitties-fun-pack-android-base", version.ref = "splittiesFunPackAndroidBase" }
|
||||
|
||||
[plugins]
|
||||
|
Loading…
x
Reference in New Issue
Block a user