Merge remote-tracking branch 'upstream/yeh'
This commit is contained in:
commit
b05ae80894
11 changed files with 268 additions and 26 deletions
|
|
@ -51,7 +51,7 @@ android {
|
|||
|
||||
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("com.google.android.material:material:1.4.0")
|
||||
|
||||
|
|
@ -60,8 +60,8 @@ dependencies {
|
|||
implementation("androidx.compose.ui:ui:${composeVersion}")
|
||||
implementation("androidx.compose.material:material:${composeVersion}")
|
||||
implementation("androidx.compose.ui:ui-tooling:${composeVersion}")
|
||||
implementation("androidx.constraintlayout:constraintlayout-compose:1.0.0-rc01")
|
||||
implementation("androidx.navigation:navigation-compose:2.4.0-beta02")
|
||||
implementation("androidx.constraintlayout:constraintlayout-compose:1.0.0-rc02")
|
||||
implementation("androidx.navigation:navigation-compose:2.4.0-rc01")
|
||||
|
||||
// accompanist dependencies
|
||||
implementation("com.google.accompanist:accompanist-systemuicontroller:${accompanistVersion}")
|
||||
|
|
@ -69,4 +69,6 @@ dependencies {
|
|||
|
||||
// other dependencies
|
||||
implementation("com.google.code.gson:gson:2.8.7")
|
||||
implementation("io.coil-kt:coil-compose:1.4.0")
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
package com.aliucord.manager.models
|
||||
|
||||
data class GithubUser(val login: String, val contributions: Int)
|
||||
|
|
@ -9,5 +9,7 @@ import android.os.Environment
|
|||
|
||||
val themePreference = intPreference("theme")
|
||||
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 dexLocationPreference = stringPreference("dex_location", Environment.getExternalStorageDirectory().absolutePath + "/Aliucord/Aliucord.dex")
|
||||
|
|
|
|||
|
|
@ -123,13 +123,21 @@ fun MainActivityLayout() {
|
|||
)
|
||||
}
|
||||
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 = {
|
||||
isMenuExpanded = false
|
||||
navController.navigate(Screen.Settings.route) {
|
||||
popUpTo(Screen.Home.route) { saveState = true }
|
||||
}
|
||||
}) {
|
||||
Text(stringResource(id = Screen.Settings.displayName))
|
||||
Text(stringResource(Screen.Settings.displayName))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import androidx.annotation.StringRes
|
|||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.runtime.Composable
|
||||
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.PluginsScreen
|
||||
import com.aliucord.manager.ui.screens.SettingsScreen
|
||||
|
|
@ -20,7 +21,7 @@ sealed class Screen(
|
|||
) {
|
||||
companion object {
|
||||
// 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(
|
||||
|
|
@ -29,6 +30,12 @@ sealed class Screen(
|
|||
{ HomeScreen() }
|
||||
)
|
||||
|
||||
object About : Screen(
|
||||
"About",
|
||||
R.string.about,
|
||||
{ AboutScreen() }
|
||||
)
|
||||
|
||||
object Settings : Screen(
|
||||
"settings",
|
||||
R.string.settings,
|
||||
|
|
|
|||
136
app/src/main/java/com/aliucord/manager/ui/screens/AboutScreen.kt
Normal file
136
app/src/main/java/com/aliucord/manager/ui/screens/AboutScreen.kt
Normal 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") }
|
||||
)
|
||||
}
|
||||
|
|
@ -154,4 +154,4 @@ fun PluginsScreen() {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,10 +17,7 @@ import androidx.compose.ui.res.stringResource
|
|||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.aliucord.manager.R
|
||||
import com.aliucord.manager.preferences.dexLocationPreference
|
||||
import com.aliucord.manager.preferences.replaceBgPreference
|
||||
import com.aliucord.manager.preferences.themePreference
|
||||
import com.aliucord.manager.preferences.useDexFromStoragePreference
|
||||
import com.aliucord.manager.preferences.*
|
||||
import com.aliucord.manager.ui.components.ExposedDropdownMenu
|
||||
|
||||
private val themes = arrayOf("System", "Light", "Dark", "Black")
|
||||
|
|
@ -52,23 +49,49 @@ fun SettingsScreen() {
|
|||
},
|
||||
modifier = modifier.clickable { replaceBgPreference.set(!replaceBgPreference.get()) }
|
||||
)
|
||||
val udfs = useDexFromStoragePreference.get()
|
||||
|
||||
val devModeOn = devModePreference.get()
|
||||
ListItem(
|
||||
text = { Text(stringResource(R.string.use_dex_from_storage)) },
|
||||
text = { Text(stringResource(R.string.developer_mode)) },
|
||||
trailing = {
|
||||
Checkbox(
|
||||
checked = udfs,
|
||||
onCheckedChange = useDexFromStoragePreference::set
|
||||
checked = devModeOn,
|
||||
onCheckedChange = devModePreference::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
|
||||
modifier = 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(
|
||||
onClick = { /*TODO*/ },
|
||||
Modifier
|
||||
|
|
|
|||
39
app/src/main/java/com/aliucord/manager/utils/Downloader.kt
Normal file
39
app/src/main/java/com/aliucord/manager/utils/Downloader.kt
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@
|
|||
package com.aliucord.manager.utils
|
||||
|
||||
import com.aliucord.manager.models.Commit
|
||||
import com.aliucord.manager.models.GithubUser
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import java.io.InputStreamReader
|
||||
|
|
@ -18,6 +19,7 @@ object Github {
|
|||
private const val repo = "Aliucord"
|
||||
|
||||
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"
|
||||
|
||||
fun checkForUpdates() {
|
||||
|
|
@ -30,21 +32,35 @@ object Github {
|
|||
|
||||
private val commitsCache = HashMap<String, Array<Commit>>()
|
||||
private val commitsType = object : TypeToken<Array<Commit>>() {}.type
|
||||
private val contributorsType = object : TypeToken<Array<GithubUser>>() {}.type
|
||||
private val gson = Gson()
|
||||
|
||||
fun getCommits(params: Map<String, String>?): Array<Commit> {
|
||||
// return emptyArray()
|
||||
val query = params?.map { it.key + "=" + it.value }?.joinToString("&", "?") ?: ""
|
||||
if (commitsCache.containsKey(query)) return commitsCache[query] ?: emptyArray()
|
||||
val res = gson.fromJson<Array<Commit>>(
|
||||
InputStreamReader(URL(commitsUrl + query).openStream()),
|
||||
commitsType
|
||||
)
|
||||
val res = InputStreamReader(URL(commitsUrl + query).openStream()).use {
|
||||
gson.fromJson<Array<Commit>>(
|
||||
it,
|
||||
commitsType
|
||||
)
|
||||
}
|
||||
commitsCache[query] = 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 {
|
||||
return "'https://raw.githubusercontent.com/${org}/${repo}/${ref}/${file}";
|
||||
return "https://raw.githubusercontent.com/${org}/${repo}/${ref}/${file}";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,4 +25,10 @@
|
|||
<string name="install">Install</string>
|
||||
<string name="reinstall">Reinstall</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>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue