mirror of
https://github.com/jrpie/Launcher.git
synced 2025-05-17 07:51:06 +02:00
new meta, holy butts we've got ourselves some Jetpack Compose
This commit is contained in:
parent
656c7cdbea
commit
8040d22fca
3 changed files with 248 additions and 124 deletions
|
@ -88,27 +88,22 @@ dependencies {
|
|||
implementation(libs.androidx.activity.ktx)
|
||||
implementation(libs.androidx.appcompat)
|
||||
implementation(platform(libs.androidx.compose.bom))
|
||||
implementation(libs.androidx.compose.material)
|
||||
implementation(libs.androidx.compose.material3)
|
||||
implementation(libs.androidx.compose.runtime)
|
||||
implementation(libs.androidx.compose.ui.graphics)
|
||||
implementation(libs.androidx.constraintlayout)
|
||||
implementation(libs.androidx.core.ktx)
|
||||
implementation(libs.androidx.gridlayout)
|
||||
// implementation(libs.androidx.lifecycle.runtime.ktx)
|
||||
// implementation(libs.androidx.material3)
|
||||
implementation(libs.androidx.palette.ktx)
|
||||
implementation(libs.androidx.preference.ktx)
|
||||
implementation(libs.androidx.recyclerview)
|
||||
// implementation(libs.androidx.ui)
|
||||
// implementation(libs.androidx.ui.graphics)
|
||||
// implementation(libs.androidx.ui.tooling.preview)
|
||||
implementation(libs.google.material)
|
||||
implementation(libs.kotlinx.serialization.json)
|
||||
implementation(libs.jonahbauer.android.preference.annotations)
|
||||
implementation(libs.androidx.ui.tooling.preview.android)
|
||||
kapt(libs.jonahbauer.android.preference.annotations)
|
||||
testImplementation(libs.junit)
|
||||
// androidTestImplementation(platform(libs.androidx.compose.bom))
|
||||
androidTestImplementation(libs.androidx.espresso.core)
|
||||
// androidTestImplementation(libs.androidx.junit)
|
||||
androidTestImplementation(libs.androidx.test.ext.junit)
|
||||
// androidTestImplementation(libs.androidx.ui.test.junit4)
|
||||
// debugImplementation(libs.androidx.ui.test.manifest)
|
||||
// debugImplementation(libs.androidx.ui.tooling)
|
||||
}
|
|
@ -1,18 +1,35 @@
|
|||
package de.jrpie.android.launcher.ui.settings.meta
|
||||
|
||||
import android.app.AlertDialog
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Button
|
||||
import android.widget.TextView
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Warning
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.platform.ComposeView
|
||||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.DialogProperties
|
||||
import androidx.fragment.app.Fragment
|
||||
import de.jrpie.android.launcher.BuildConfig
|
||||
import de.jrpie.android.launcher.R
|
||||
import de.jrpie.android.launcher.copyToClipboard
|
||||
import de.jrpie.android.launcher.databinding.SettingsMetaBinding
|
||||
import de.jrpie.android.launcher.getDeviceInfo
|
||||
import de.jrpie.android.launcher.openInBrowser
|
||||
import de.jrpie.android.launcher.openTutorial
|
||||
|
@ -30,13 +47,21 @@ import de.jrpie.android.launcher.ui.UIObject
|
|||
*/
|
||||
class SettingsFragmentMeta : Fragment(), UIObject {
|
||||
|
||||
private lateinit var binding: SettingsMetaBinding
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
binding = SettingsMetaBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
return ComposeView(requireContext()).apply {
|
||||
setContent {
|
||||
MaterialTheme {
|
||||
SettingsMetaScreen(
|
||||
context = requireContext(),
|
||||
onResetConfirmed = { requireActivity().finish() }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
|
@ -45,99 +70,204 @@ class SettingsFragmentMeta : Fragment(), UIObject {
|
|||
}
|
||||
|
||||
override fun setOnClicks() {
|
||||
// No longer needed as click handlers are defined in Compose
|
||||
}
|
||||
}
|
||||
|
||||
fun bindURL(view: View, urlRes: Int) {
|
||||
view.setOnClickListener {
|
||||
openInBrowser(
|
||||
getString(urlRes),
|
||||
requireContext()
|
||||
// Here we define what the settings meta screen looks like
|
||||
@Composable
|
||||
fun SettingsMetaScreen(
|
||||
context: Context,
|
||||
onResetConfirmed: () -> Unit
|
||||
) {
|
||||
val openAlertDialog = remember { mutableStateOf(false) }
|
||||
|
||||
// Here we tell the screen to lay out the settings buttons in a column.
|
||||
// This could also be a row, but that's hella ugly in this use case.
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(16.dp)
|
||||
.verticalScroll(rememberScrollState()),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
// View Tutorial
|
||||
SettingsButton(
|
||||
text = stringResource(R.string.settings_meta_show_tutorial),
|
||||
onClick = { openTutorial(context) }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
binding.settingsMetaButtonViewTutorial.setOnClickListener {
|
||||
openTutorial(requireContext())
|
||||
// Reset Settings
|
||||
SettingsButton(
|
||||
text = stringResource(R.string.settings_meta_reset),
|
||||
onClick = { openAlertDialog.value = true }
|
||||
)
|
||||
|
||||
SettingsButtonSpacer()
|
||||
|
||||
// View Code
|
||||
SettingsButton(
|
||||
text = stringResource(R.string.settings_meta_view_code),
|
||||
onClick = { openInBrowser(context.getString(R.string.settings_meta_link_github), context) }
|
||||
)
|
||||
|
||||
// Report a Bug (Placeholder for dialog, simplified for now)
|
||||
SettingsButton(
|
||||
text = stringResource(R.string.settings_meta_report_bug),
|
||||
onClick = {
|
||||
// Simplified: Directly open bug report link
|
||||
// TODO: Implement Compose dialog for bug reporting if needed
|
||||
openInBrowser(context.getString(R.string.settings_meta_report_bug_link), context)
|
||||
}
|
||||
)
|
||||
|
||||
// prompting for settings-reset confirmation
|
||||
binding.settingsMetaButtonResetSettings.setOnClickListener {
|
||||
AlertDialog.Builder(this.requireContext(), R.style.AlertDialogCustom)
|
||||
.setTitle(getString(R.string.settings_meta_reset))
|
||||
.setMessage(getString(R.string.settings_meta_reset_confirm))
|
||||
.setPositiveButton(
|
||||
android.R.string.ok
|
||||
) { _, _ ->
|
||||
resetPreferences(this.requireContext())
|
||||
requireActivity().finish()
|
||||
}
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.setIcon(android.R.drawable.ic_dialog_alert)
|
||||
.show()
|
||||
SettingsButtonSpacer()
|
||||
|
||||
// Join Chat
|
||||
SettingsButton(
|
||||
text = stringResource(R.string.settings_meta_join_chat),
|
||||
onClick = { openInBrowser(context.getString(R.string.settings_meta_chat_url), context) }
|
||||
)
|
||||
|
||||
// Contact Fork Developer
|
||||
SettingsButton(
|
||||
text = stringResource(R.string.settings_meta_fork_contact),
|
||||
onClick = { openInBrowser(context.getString(R.string.settings_meta_fork_contact_url), context) }
|
||||
)
|
||||
|
||||
// Donate
|
||||
SettingsButton(
|
||||
text = stringResource(R.string.settings_meta_donate),
|
||||
onClick = { openInBrowser(context.getString(R.string.settings_meta_donate_url), context) }
|
||||
)
|
||||
|
||||
SettingsButtonSpacer()
|
||||
|
||||
// Privacy Policy
|
||||
SettingsButton(
|
||||
text = stringResource(R.string.settings_meta_privacy),
|
||||
onClick = { openInBrowser(context.getString(R.string.settings_meta_privacy_url), context) }
|
||||
)
|
||||
|
||||
// Legal Info
|
||||
SettingsButton(
|
||||
text = stringResource(R.string.settings_meta_licenses),
|
||||
onClick = {
|
||||
context.startActivity(Intent(context, LegalInfoActivity::class.java))
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
// view code
|
||||
bindURL(binding.settingsMetaButtonViewCode, R.string.settings_meta_link_github)
|
||||
|
||||
// report a bug
|
||||
binding.settingsMetaButtonReportBug.setOnClickListener {
|
||||
// Version
|
||||
Text(
|
||||
text = BuildConfig.VERSION_NAME,
|
||||
// TODO: Implement matching font to Launcher Appearance font
|
||||
textAlign = TextAlign.Right,
|
||||
color = colorResource(R.color.finnmglasTheme_text_color),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth(1f)
|
||||
.padding(
|
||||
top = 16.dp,
|
||||
bottom = 8.dp,
|
||||
end = 8.dp
|
||||
)
|
||||
.clickable {
|
||||
val deviceInfo = getDeviceInfo()
|
||||
AlertDialog.Builder(context, R.style.AlertDialogCustom).apply {
|
||||
setView(R.layout.dialog_report_bug)
|
||||
setTitle(R.string.dialog_report_bug_title)
|
||||
setPositiveButton(R.string.dialog_report_bug_create_report) { _, _ ->
|
||||
openInBrowser(
|
||||
getString(R.string.settings_meta_report_bug_link),
|
||||
requireContext()
|
||||
copyToClipboard(context, deviceInfo)
|
||||
}
|
||||
)
|
||||
}
|
||||
setNegativeButton(R.string.dialog_cancel) { _, _ -> }
|
||||
}.create().also { it.show() }.apply {
|
||||
val info = findViewById<TextView>(R.id.dialog_report_bug_device_info)
|
||||
val buttonClipboard = findViewById<Button>(R.id.dialog_report_bug_button_clipboard)
|
||||
val buttonSecurity = findViewById<Button>(R.id.dialog_report_bug_button_security)
|
||||
info.text = deviceInfo
|
||||
buttonClipboard.setOnClickListener {
|
||||
copyToClipboard(requireContext(), deviceInfo)
|
||||
}
|
||||
info.setOnClickListener {
|
||||
copyToClipboard(requireContext(), deviceInfo)
|
||||
}
|
||||
buttonSecurity.setOnClickListener {
|
||||
openInBrowser(
|
||||
getString(R.string.settings_meta_report_vulnerability_link),
|
||||
requireContext()
|
||||
|
||||
// Reset Settings Dialog
|
||||
if (openAlertDialog.value) {
|
||||
AlertDialogResetSettings(
|
||||
onDismissRequest = { openAlertDialog.value = false },
|
||||
onConfirmation = {
|
||||
openAlertDialog.value = false
|
||||
resetPreferences(context)
|
||||
onResetConfirmed()
|
||||
},
|
||||
dialogTitle = stringResource(R.string.settings_meta_reset),
|
||||
dialogText = stringResource(R.string.settings_meta_reset_confirm),
|
||||
icon = Icons.Default.Warning
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// join chat
|
||||
bindURL(binding.settingsMetaButtonJoinChat, R.string.settings_meta_chat_url)
|
||||
|
||||
// contact developer
|
||||
// bindURL(binding.settingsMetaButtonContact, R.string.settings_meta_contact_url)
|
||||
|
||||
// contact fork developer
|
||||
bindURL(binding.settingsMetaButtonForkContact, R.string.settings_meta_fork_contact_url)
|
||||
|
||||
// donate
|
||||
bindURL(binding.settingsMetaButtonDonate, R.string.settings_meta_donate_url)
|
||||
|
||||
// privacy policy
|
||||
bindURL(binding.settingsMetaButtonPrivacy, R.string.settings_meta_privacy_url)
|
||||
|
||||
// legal info
|
||||
binding.settingsMetaButtonLicenses.setOnClickListener {
|
||||
startActivity(Intent(this.context, LegalInfoActivity::class.java))
|
||||
}
|
||||
|
||||
// version
|
||||
binding.settingsMetaTextVersion.text = BuildConfig.VERSION_NAME
|
||||
binding.settingsMetaTextVersion.setOnClickListener {
|
||||
val deviceInfo = getDeviceInfo()
|
||||
copyToClipboard(requireContext(), deviceInfo)
|
||||
}
|
||||
|
||||
// Here we define what a settings button looks like
|
||||
@Composable
|
||||
fun SettingsButton(
|
||||
text: String,
|
||||
onClick: () -> Unit
|
||||
) {
|
||||
Button(
|
||||
onClick = onClick,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
contentPadding = PaddingValues(8.dp),
|
||||
shape = RoundedCornerShape(4.dp),
|
||||
// TODO: colors can be changed to match the dynamic system theme
|
||||
// https://developer.android.com/codelabs/jetpack-compose-theming#0
|
||||
colors = ButtonDefaults.buttonColors(
|
||||
containerColor = colorResource(R.color.finnmglasTheme_accent_color),
|
||||
contentColor = colorResource(R.color.finnmglasTheme_text_color)
|
||||
)
|
||||
) {
|
||||
Text(
|
||||
text = text,
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
modifier = Modifier.align(Alignment.CenterVertically),
|
||||
color = colorResource(R.color.finnmglasTheme_text_color)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Here we define some space to put between the buttons
|
||||
@Composable
|
||||
fun SettingsButtonSpacer() {
|
||||
Spacer(modifier = Modifier.height(48.dp))
|
||||
}
|
||||
|
||||
// Here we define what an alert dialog looks like
|
||||
@Composable
|
||||
fun AlertDialogResetSettings(
|
||||
onDismissRequest: () -> Unit,
|
||||
onConfirmation: () -> Unit,
|
||||
dialogTitle: String,
|
||||
dialogText: String,
|
||||
icon: ImageVector
|
||||
) {
|
||||
AlertDialog(
|
||||
icon = {
|
||||
Icon(
|
||||
imageVector = icon,
|
||||
contentDescription = stringResource(android.R.string.dialog_alert_title),
|
||||
tint = MaterialTheme.colorScheme.error
|
||||
)
|
||||
},
|
||||
title = {
|
||||
Text(text = dialogTitle)
|
||||
},
|
||||
text = {
|
||||
Text(text = dialogText)
|
||||
},
|
||||
onDismissRequest = onDismissRequest,
|
||||
confirmButton = {
|
||||
TextButton(
|
||||
onClick = onConfirmation
|
||||
)
|
||||
{
|
||||
Text(stringResource(android.R.string.ok))
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
TextButton(
|
||||
onClick = onDismissRequest
|
||||
) {
|
||||
Text(stringResource(android.R.string.cancel))
|
||||
}
|
||||
},
|
||||
properties = DialogProperties(
|
||||
dismissOnBackPress = true,
|
||||
dismissOnClickOutside = true
|
||||
)
|
||||
)
|
||||
}
|
|
@ -1,26 +1,27 @@
|
|||
[versions]
|
||||
activity = "1.10.1"
|
||||
activity-ktx = "1.8.0"
|
||||
activity-ktx = "1.10.1"
|
||||
activityCompose = "1.10.1"
|
||||
agp = "8.10.0"
|
||||
android-preference-annotations = "1.1.2"
|
||||
appcompat = "1.7.0"
|
||||
composeBom = "2025.05.00"
|
||||
constraintlayout = "2.2.0"
|
||||
core-ktx = "1.15.0"
|
||||
compose-latest = "1.8.1"
|
||||
constraintlayout = "2.2.1"
|
||||
core-ktx = "1.16.0"
|
||||
espresso-core = "3.6.1"
|
||||
gridlayout = "1.0.0"
|
||||
gridlayout = "1.1.0"
|
||||
junit = "4.13.2"
|
||||
junitVersion = "1.2.1"
|
||||
kapt = "1.8.10"
|
||||
kotlin = "2.1.0"
|
||||
kotlinx-serialization-json = "1.7.3"
|
||||
# lifecycleRuntimeKtx = "2.9.0"
|
||||
material = "1.12.0"
|
||||
palette-ktx = "1.0.0"
|
||||
preference-ktx = "1.2.1"
|
||||
recyclerview = "1.4.0"
|
||||
serialization = "1.8.10"
|
||||
uiToolingPreviewAndroid = "1.8.1"
|
||||
|
||||
[libraries]
|
||||
# AndroidX dependencies
|
||||
|
@ -29,18 +30,16 @@ androidx-activity-compose = { group = "androidx.activity", name = "activity-comp
|
|||
androidx-activity-ktx = { group = "androidx.activity", name = "activity-ktx", version.ref = "activity-ktx" }
|
||||
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
|
||||
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
|
||||
androidx-compose-material = { module = "androidx.compose.material:material", version.ref = "compose-latest" }
|
||||
androidx-compose-material3 = { module = "androidx.compose.material3:material3" }
|
||||
androidx-compose-runtime = { module = "androidx.compose.runtime:runtime" }
|
||||
androidx-compose-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" }
|
||||
androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
|
||||
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "core-ktx" }
|
||||
androidx-gridlayout = { group = "androidx.gridlayout", name = "gridlayout", version.ref = "gridlayout" }
|
||||
androidx-palette-ktx = { group = "androidx.palette", name = "palette-ktx", version.ref = "palette-ktx" }
|
||||
androidx-preference-ktx = { group = "androidx.preference", name = "preference-ktx", version.ref = "preference-ktx" }
|
||||
androidx-recyclerview = { group = "androidx.recyclerview", name = "recyclerview", version.ref = "recyclerview" }
|
||||
# androidx-ui = { group = "androidx.compose.ui", name = "ui" }
|
||||
# androidx-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" }
|
||||
# androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
|
||||
# androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
|
||||
# androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
|
||||
# androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
|
||||
|
||||
# Google Material
|
||||
google-material = { group = "com.google.android.material", name = "material", version.ref = "material" }
|
||||
|
@ -53,9 +52,9 @@ jonahbauer-android-preference-annotations = { group = "eu.jonahbauer", name = "a
|
|||
|
||||
# Testing dependencies
|
||||
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
||||
# androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
|
||||
androidx-test-ext-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
|
||||
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espresso-core" }
|
||||
androidx-ui-tooling-preview-android = { group = "androidx.compose.ui", name = "ui-tooling-preview-android", version.ref = "uiToolingPreviewAndroid" }
|
||||
|
||||
[plugins]
|
||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue