Push changes

This commit is contained in:
Vendicated 2022-01-19 00:55:48 +01:00
parent a6e54d97c5
commit 4bce95afc9
No known key found for this signature in database
GPG key ID: EC781ADFB93EFFA3
11 changed files with 269 additions and 32 deletions

View file

@ -51,7 +51,7 @@ android {
dependencies { dependencies {
// core dependencies // core dependencies
implementation("androidx.appcompat:appcompat:1.3.1") implementation("androidx.appcompat:appcompat:1.4.0")
implementation("androidx.core:core-ktx:1.7.0") implementation("androidx.core:core-ktx:1.7.0")
implementation("com.google.android.material:material:1.4.0") implementation("com.google.android.material:material:1.4.0")
@ -60,8 +60,8 @@ dependencies {
implementation("androidx.compose.ui:ui:${composeVersion}") implementation("androidx.compose.ui:ui:${composeVersion}")
implementation("androidx.compose.material:material:${composeVersion}") implementation("androidx.compose.material:material:${composeVersion}")
implementation("androidx.compose.ui:ui-tooling:${composeVersion}") implementation("androidx.compose.ui:ui-tooling:${composeVersion}")
implementation("androidx.constraintlayout:constraintlayout-compose:1.0.0-rc01") implementation("androidx.constraintlayout:constraintlayout-compose:1.0.0-rc02")
implementation("androidx.navigation:navigation-compose:2.4.0-beta02") implementation("androidx.navigation:navigation-compose:2.4.0-rc01")
// accompanist dependencies // accompanist dependencies
implementation("com.google.accompanist:accompanist-systemuicontroller:${accompanistVersion}") implementation("com.google.accompanist:accompanist-systemuicontroller:${accompanistVersion}")
@ -69,4 +69,6 @@ dependencies {
// other dependencies // other dependencies
implementation("com.google.code.gson:gson:2.8.7") implementation("com.google.code.gson:gson:2.8.7")
implementation("io.coil-kt:coil-compose:1.4.0")
} }

View file

@ -0,0 +1,3 @@
package com.aliucord.manager.models
data class GithubUser(val login: String, val contributions: Int)

View file

@ -9,5 +9,7 @@ import android.os.Environment
val themePreference = intPreference("theme") val themePreference = intPreference("theme")
val replaceBgPreference = boolPreference("replace_bg", true) val replaceBgPreference = boolPreference("replace_bg", true)
val devModePreference = boolPreference("dev_mode", false)
val debuggablePreference = boolPreference("debuggable", false)
val useDexFromStoragePreference = boolPreference("use_dex_from_storage") val useDexFromStoragePreference = boolPreference("use_dex_from_storage")
val dexLocationPreference = stringPreference("dex_location", Environment.getExternalStorageDirectory().absolutePath + "/Aliucord/Aliucord.dex") val dexLocationPreference = stringPreference("dex_location", Environment.getExternalStorageDirectory().absolutePath + "/Aliucord/Aliucord.dex")

View file

@ -17,13 +17,11 @@ import androidx.compose.foundation.layout.*
import androidx.compose.material.* import androidx.compose.material.*
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.Build
import androidx.compose.material.icons.filled.MoreVert import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.runtime.* import androidx.compose.runtime.*
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.HorizontalAlignmentLine
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
@ -45,7 +43,6 @@ import com.google.accompanist.permissions.PermissionRequired
import com.google.accompanist.permissions.PermissionState import com.google.accompanist.permissions.PermissionState
import com.google.accompanist.permissions.rememberPermissionState import com.google.accompanist.permissions.rememberPermissionState
import com.google.accompanist.systemuicontroller.rememberSystemUiController import com.google.accompanist.systemuicontroller.rememberSystemUiController
import org.intellij.lang.annotations.JdkConstants
class MainActivity : ComponentActivity() { class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
@ -125,13 +122,21 @@ fun MainActivityLayout() {
) )
} }
DropdownMenu(expanded = isMenuExpanded, onDismissRequest = { isMenuExpanded = false }) { DropdownMenu(expanded = isMenuExpanded, onDismissRequest = { isMenuExpanded = false }) {
DropdownMenuItem(onClick = {
isMenuExpanded = false
navController.navigate(Screen.About.route) {
popUpTo(Screen.Home.route) { saveState = true }
}
}) {
Text(stringResource(Screen.About.displayName))
}
DropdownMenuItem(onClick = { DropdownMenuItem(onClick = {
isMenuExpanded = false isMenuExpanded = false
navController.navigate(Screen.Settings.route) { navController.navigate(Screen.Settings.route) {
popUpTo(Screen.Home.route) { saveState = true } popUpTo(Screen.Home.route) { saveState = true }
} }
}) { }) {
Text(stringResource(id = Screen.Settings.displayName)) Text(stringResource(Screen.Settings.displayName))
} }
} }
} }

View file

@ -9,6 +9,7 @@ import androidx.annotation.StringRes
import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import com.aliucord.manager.R import com.aliucord.manager.R
import com.aliucord.manager.ui.screens.AboutScreen
import com.aliucord.manager.ui.screens.HomeScreen import com.aliucord.manager.ui.screens.HomeScreen
import com.aliucord.manager.ui.screens.PluginsScreen import com.aliucord.manager.ui.screens.PluginsScreen
import com.aliucord.manager.ui.screens.SettingsScreen import com.aliucord.manager.ui.screens.SettingsScreen
@ -20,7 +21,7 @@ sealed class Screen(
) { ) {
companion object { companion object {
// NOTE: without lazy it doesn't work, kotlin moment https://youtrack.jetbrains.com/issue/KT-8970 // NOTE: without lazy it doesn't work, kotlin moment https://youtrack.jetbrains.com/issue/KT-8970
val SCREENS by lazy { listOf(Home, Settings, Plugins) } val SCREENS by lazy { listOf(Home, Settings, Plugins, About) }
} }
object Home : Screen( object Home : Screen(
@ -29,6 +30,12 @@ sealed class Screen(
{ HomeScreen() } { HomeScreen() }
) )
object About : Screen(
"About",
R.string.about,
{ AboutScreen() }
)
object Settings : Screen( object Settings : Screen(
"settings", "settings",
R.string.settings, R.string.settings,

View file

@ -0,0 +1,136 @@
package com.aliucord.manager.ui.screens
import android.util.Log
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.GridCells
import androidx.compose.foundation.lazy.LazyVerticalGrid
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.runtime.*
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import coil.compose.rememberImagePainter
import coil.transform.CircleCropTransformation
import com.aliucord.manager.BuildConfig
import com.aliucord.manager.R
import com.aliucord.manager.models.GithubUser
import com.aliucord.manager.utils.Github
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@ExperimentalFoundationApi
@OptIn(ExperimentalMaterialApi::class)
@Composable
@Preview
fun AboutScreen() {
val coroutineScope = rememberCoroutineScope { Dispatchers.IO }
val modifier = Modifier.padding(8.dp)
val contributors = remember { mutableStateOf<Array<GithubUser>?>(null) }
Column(modifier = Modifier.padding(16.dp)) {
Column(
modifier = Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
stringResource(R.string.team),
style = MaterialTheme.typography.h4,
)
UserEntry("Juby210", "Fox")
UserEntry("torvalds", "Epic")
UserEntry("cyyynthia", "PSA: Uninstall Client mods by Cynthia")
}
Column(
modifier = modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
stringResource(R.string.contributors),
style = MaterialTheme.typography.h4,
)
if (contributors.value == null) {
Text(
stringResource(R.string.loading)
)
LaunchedEffect(null) {
coroutineScope.launch {
try {
contributors.value = Github.contributors
} catch (err: Throwable) {
Log.e(BuildConfig.TAG, "Failed to load contributors", err)
}
}
}
} else {
LazyVerticalGrid(
cells = GridCells.Adaptive(48.dp)
) {
items(contributors.value!!) {
ContributorEntry(it.login)
}
}
}
}
}
}
@Composable
fun UserEntry(name: String, roles: String) {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp, 8.dp), shape = RoundedCornerShape(15.dp)
) {
Column(modifier = Modifier.padding(16.dp, 8.dp)) {
Row(verticalAlignment = Alignment.CenterVertically) {
Image(
painter = rememberImagePainter(
data = "https://github.com/$name.png",
builder = {
transformations(CircleCropTransformation())
}
),
contentDescription = null,
modifier = Modifier
.size(48.dp)
.padding(end = 8.dp)
)
Column {
Text(
name,
style = MaterialTheme.typography.h6,
)
Text(roles)
}
}
}
}
}
@Composable
fun ContributorEntry(name: String) {
val handler = LocalUriHandler.current
Image(
painter = rememberImagePainter(
data = "https://github.com/$name.png",
),
contentDescription = null,
modifier = Modifier
.size(48.dp)
.clickable { handler.openUri("https://github.com/$name") }
)
}

View file

@ -52,7 +52,7 @@ fun PluginsScreen() {
// TODO - make this get pluginEnabled from Aliucord preferences somehow // TODO - make this get pluginEnabled from Aliucord preferences somehow
val isChecked = remember { mutableStateOf(true) } val isChecked = remember { mutableStateOf(true) }
var showDeleteDialog by remember { mutableStateOf(false) } var showDeleteDialog by remember { mutableStateOf(false) }
var showChangelogDialog = remember { mutableStateOf(false) } val showChangelogDialog = remember { mutableStateOf(false) }
if (showDeleteDialog) { if (showDeleteDialog) {
AlertDialog( AlertDialog(

View file

@ -11,18 +11,13 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material.* import androidx.compose.material.*
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.aliucord.manager.R import com.aliucord.manager.R
import com.aliucord.manager.preferences.dexLocationPreference import com.aliucord.manager.preferences.*
import com.aliucord.manager.preferences.replaceBgPreference
import com.aliucord.manager.preferences.themePreference
import com.aliucord.manager.preferences.useDexFromStoragePreference
import com.aliucord.manager.ui.components.ExposedDropdownMenu import com.aliucord.manager.ui.components.ExposedDropdownMenu
private val themes = arrayOf("System", "Light", "Dark", "Black") private val themes = arrayOf("System", "Light", "Dark", "Black")
@ -54,23 +49,49 @@ fun SettingsScreen() {
}, },
modifier = modifier.clickable { replaceBgPreference.set(!replaceBgPreference.get()) } modifier = modifier.clickable { replaceBgPreference.set(!replaceBgPreference.get()) }
) )
val udfs = useDexFromStoragePreference.get()
val devModeOn = devModePreference.get()
ListItem( ListItem(
text = { Text(stringResource(R.string.use_dex_from_storage)) }, text = { Text(stringResource(R.string.developer_mode)) },
trailing = { trailing = {
Checkbox( Checkbox(
checked = udfs, checked = devModeOn,
onCheckedChange = useDexFromStoragePreference::set onCheckedChange = devModePreference::set
) )
}, },
modifier = modifier.clickable { useDexFromStoragePreference.set(!useDexFromStoragePreference.get()) } modifier = modifier
)
val color = if (udfs) Color.Unspecified else MaterialTheme.colors.onBackground.copy(ContentAlpha.disabled)
ListItem(
text = { Text(stringResource(R.string.dex_location), color = color) },
secondaryText = { Text(dexLocationPreference.get(), color = color) },
modifier = if (udfs) modifier.clickable { /*TODO*/ } else modifier
) )
if (devModeOn) {
ListItem(
text = { Text(stringResource(R.string.debuggable)) },
trailing = {
Checkbox(
checked = debuggablePreference.get(),
onCheckedChange = debuggablePreference::set
)
},
modifier = modifier
)
val udfs = useDexFromStoragePreference.get()
ListItem(
text = { Text(stringResource(R.string.use_dex_from_storage)) },
trailing = {
Checkbox(
checked = udfs,
onCheckedChange = useDexFromStoragePreference::set
)
},
modifier = modifier.clickable { useDexFromStoragePreference.set(!useDexFromStoragePreference.get()) }
)
val color =
if (udfs) Color.Unspecified else MaterialTheme.colors.onBackground.copy(ContentAlpha.disabled)
ListItem(
text = { Text(stringResource(R.string.dex_location), color = color) },
secondaryText = { Text(dexLocationPreference.get(), color = color) },
modifier = if (udfs) modifier.clickable { /*TODO*/ } else modifier
)
}
Button( Button(
onClick = { /*TODO*/ }, onClick = { /*TODO*/ },
Modifier Modifier

View file

@ -0,0 +1,39 @@
package com.aliucord.manager.utils
import android.app.DownloadManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.net.Uri
import java.io.File
import java.util.concurrent.CountDownLatch
object Downloader {
fun download(ctx: Context, url: String, file: File) {
val dm = ctx.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
val latch = CountDownLatch(1)
with (DownloadReceiver(ctx, latch)) {
ctx.registerReceiver(this, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE))
downloadId = DownloadManager.Request(Uri.parse(url)).run {
setTitle("AliucordManager")
setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
setDestinationUri(Uri.fromFile(file))
dm.enqueue(this)
}
}
latch.await()
}
}
class DownloadReceiver(private val ctx: Context, private val latch: CountDownLatch) : BroadcastReceiver() {
var downloadId = 0L
override fun onReceive(context: Context, intent: Intent) {
val id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1)
if (downloadId == id) {
latch.countDown()
ctx.unregisterReceiver(this)
}
}
}

View file

@ -6,6 +6,7 @@
package com.aliucord.manager.utils package com.aliucord.manager.utils
import com.aliucord.manager.models.Commit import com.aliucord.manager.models.Commit
import com.aliucord.manager.models.GithubUser
import com.google.gson.Gson import com.google.gson.Gson
import com.google.gson.reflect.TypeToken import com.google.gson.reflect.TypeToken
import java.io.InputStreamReader import java.io.InputStreamReader
@ -18,6 +19,7 @@ object Github {
private const val repo = "Aliucord" private const val repo = "Aliucord"
private const val commitsUrl = "https://api.github.com/repos/$org/$repo/commits" private const val commitsUrl = "https://api.github.com/repos/$org/$repo/commits"
private const val contributorsUrl = "https://api.github.com/repos/$org/$repo/contributors"
private const val dataUrl = "https://raw.githubusercontent.com/$org/$repo/builds/data.json" private const val dataUrl = "https://raw.githubusercontent.com/$org/$repo/builds/data.json"
fun checkForUpdates() { fun checkForUpdates() {
@ -30,21 +32,35 @@ object Github {
private val commitsCache = HashMap<String, Array<Commit>>() private val commitsCache = HashMap<String, Array<Commit>>()
private val commitsType = object : TypeToken<Array<Commit>>() {}.type private val commitsType = object : TypeToken<Array<Commit>>() {}.type
private val contributorsType = object : TypeToken<Array<GithubUser>>() {}.type
private val gson = Gson() private val gson = Gson()
fun getCommits(params: Map<String, String>?): Array<Commit> { fun getCommits(params: Map<String, String>?): Array<Commit> {
// return emptyArray() // return emptyArray()
val query = params?.map { it.key + "=" + it.value }?.joinToString("&", "?") ?: "" val query = params?.map { it.key + "=" + it.value }?.joinToString("&", "?") ?: ""
if (commitsCache.containsKey(query)) return commitsCache[query] ?: emptyArray() if (commitsCache.containsKey(query)) return commitsCache[query] ?: emptyArray()
val res = gson.fromJson<Array<Commit>>( val res = InputStreamReader(URL(commitsUrl + query).openStream()).use {
InputStreamReader(URL(commitsUrl + query).openStream()), gson.fromJson<Array<Commit>>(
commitsType it,
) commitsType
)
}
commitsCache[query] = res commitsCache[query] = res
return res return res
} }
val contributors: Array<GithubUser> by lazy {
InputStreamReader(URL(contributorsUrl).openStream()).use { stream ->
gson.fromJson<Array<GithubUser>>(
stream,
contributorsType
).apply {
sortByDescending { it.contributions }
}
}
}
fun getDownloadUrl(ref: String, file: String): String { fun getDownloadUrl(ref: String, file: String): String {
return "'https://raw.githubusercontent.com/${org}/${repo}/${ref}/${file}"; return "https://raw.githubusercontent.com/${org}/${repo}/${ref}/${file}";
} }
} }

View file

@ -25,4 +25,10 @@
<string name="install">Install</string> <string name="install">Install</string>
<string name="reinstall">Reinstall</string> <string name="reinstall">Reinstall</string>
<string name="update">Update</string> <string name="update">Update</string>
<string name="developer_mode">Enable Developer Mode</string>
<string name="debuggable">Make Aliucord debuggable</string>
<string name="about">About</string>
<string name="team">Team</string>
<string name="contributors">Contributors</string>
<string name="loading">Loading...</string>
</resources> </resources>