Remove ComposeActivity

This commit is contained in:
MM20 2022-01-29 19:26:29 +01:00
parent 023f5c06b5
commit 05680afcd5
No known key found for this signature in database
GPG Key ID: 0B61A8F2DEAFA389
8 changed files with 0 additions and 805 deletions

View File

@ -30,17 +30,6 @@
android:resource="@xml/debug_shortcuts" />
</activity>
<activity
android:name=".activity.ComposeActivity"
android:excludeFromRecents="true"
android:launchMode="singleTask"
android:exported="true"
android:resizeableActivity="false"
android:theme="@style/LauncherTheme"
android:windowSoftInputMode="stateHidden">
</activity>
<activity
android:name=".settings.SettingsActivity"
android:label="@string/title_activity_settings"

View File

@ -1,121 +0,0 @@
package de.mm20.launcher2.ui.activity
import android.appwidget.AppWidgetHost
import android.os.Bundle
import android.view.View
import androidx.activity.compose.setContent
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.animation.*
import androidx.compose.animation.core.tween
import androidx.compose.runtime.*
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.platform.LocalContext
import androidx.core.view.WindowCompat
import androidx.core.view.doOnLayout
import androidx.navigation.navArgument
import com.google.accompanist.insets.ProvideWindowInsets
import com.google.accompanist.navigation.animation.AnimatedNavHost
import com.google.accompanist.navigation.animation.composable
import com.google.accompanist.navigation.animation.rememberAnimatedNavController
import de.mm20.launcher2.preferences.Settings
import de.mm20.launcher2.ui.LauncherTheme
import de.mm20.launcher2.ui.locals.LocalAppWidgetHost
import de.mm20.launcher2.ui.locals.LocalColorScheme
import de.mm20.launcher2.ui.locals.LocalNavController
import de.mm20.launcher2.ui.locals.LocalWindowSize
import de.mm20.launcher2.ui.screens.LauncherMainScreen
import de.mm20.launcher2.ui.screens.settings.*
import de.mm20.launcher2.ui.settings.appearance.AppearanceSettingsScreen
import de.mm20.launcher2.ui.theme.colors.*
class ComposeActivity : AppCompatActivity() {
private lateinit var widgetHost: AppWidgetHost
@OptIn(ExperimentalAnimationApi::class)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//WindowCompat.setDecorFitsSystemWindows(window, false)
widgetHost = AppWidgetHost(applicationContext, 0xacac)
WindowCompat.setDecorFitsSystemWindows(window, false)
setContent {
val navController = rememberAnimatedNavController()
val context = LocalContext.current
var windowSize by remember { mutableStateOf(Size(0f, 0f)) }
findViewById<View>(android.R.id.content).doOnLayout {
windowSize = Size(it.width.toFloat(), it.height.toFloat())
}
if (windowSize.height <= 0 || windowSize.width <= 0) return@setContent
val colorSchemePreference = Settings.AppearanceSettings.ColorScheme.Default
val colorScheme = when (colorSchemePreference) {
Settings.AppearanceSettings.ColorScheme.BlackAndWhite -> BlackWhiteColorPalette()
else -> DefaultColorPalette()
}
ProvideWindowInsets {
CompositionLocalProvider(
LocalAppWidgetHost provides widgetHost,
LocalWindowSize provides windowSize,
LocalColorScheme provides colorScheme,
LocalNavController provides navController
) {
LauncherTheme {
AnimatedNavHost(
navController = navController,
startDestination = "home",
exitTransition = { fadeOut(tween(300, 300)) },
enterTransition = { fadeIn(tween(200)) },
popEnterTransition = { fadeIn(tween(0)) },
popExitTransition = { fadeOut(tween(200)) },
) {
composable("home") {
LauncherMainScreen()
}
composable("settings") {
SettingsMainScreen()
}
composable("settings/about") {
SettingsAboutScreen()
}
composable("settings/badges") {
SettingsBadgesScreen()
}
composable("settings/accounts") {
SettingsAccountScreen()
}
composable("settings/appearance") {
AppearanceSettingsScreen()
}
composable(
"settings/license?library={libraryName}",
arguments = listOf(navArgument("libraryName") {
nullable = true
})
) {
SettingsLicenseScreen(it.arguments?.getString("libraryName"))
}
}
}
}
}
}
}
override fun onStart() {
super.onStart()
widgetHost.startListening()
}
override fun onStop() {
super.onStop()
widgetHost.stopListening()
}
}

View File

@ -1,148 +0,0 @@
package de.mm20.launcher2.ui.screens
import androidx.activity.compose.BackHandler
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.rememberScrollState
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import com.google.accompanist.insets.systemBarsPadding
import com.google.accompanist.pager.ExperimentalPagerApi
import com.google.accompanist.pager.HorizontalPager
import com.google.accompanist.pager.rememberPagerState
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import de.mm20.launcher2.ui.component.NavBarEffects
import de.mm20.launcher2.ui.component.SearchBar
import de.mm20.launcher2.ui.component.SearchColumn
import de.mm20.launcher2.ui.component.WidgetColumn
import de.mm20.launcher2.ui.locals.LocalWindowSize
import de.mm20.launcher2.ui.toPixels
import kotlinx.coroutines.InternalCoroutinesApi
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.launch
@OptIn(
ExperimentalAnimationApi::class,
ExperimentalPagerApi::class,
InternalCoroutinesApi::class
)
@Composable
fun LauncherMainScreen() {
val systemUiController = rememberSystemUiController()
val pagerState = rememberPagerState()
val searchColumnState = rememberLazyListState()
val widgetColumnState = rememberScrollState()
val isLightTheme = androidx.compose.material.MaterialTheme.colors.isLight
val windowHeight = LocalWindowSize.current.height
LaunchedEffect(pagerState) {
val offsetFlow = snapshotFlow { pagerState.currentPageOffset + pagerState.currentPage }
val scrollFlow = snapshotFlow { widgetColumnState.value }
offsetFlow.combine(scrollFlow) { pageOffset, scrollValue ->
pageOffset > 0.5f || scrollValue > windowHeight / 2
}.collect { proposeDarkIcons ->
if (proposeDarkIcons) {
systemUiController.setSystemBarsColor(
color = Color.Transparent,
isNavigationBarContrastEnforced = false,
darkIcons = isLightTheme
)
} else {
systemUiController.setStatusBarColor(
color = Color.Transparent,
darkIcons = false //TODO Add preference to control that
)
systemUiController.setNavigationBarColor(
color = Color.Transparent,
navigationBarContrastEnforced = false,
darkIcons = false //TODO Add preference to control that
)
}
}
}
var searchBarOffset by remember { mutableStateOf(0f) }
var lastWidgetScrollPosition by remember { mutableStateOf(0) }
searchBarOffset = run {
val lastScrollPos = lastWidgetScrollPosition
val scrollPos = widgetColumnState.value
lastWidgetScrollPosition = scrollPos
(searchBarOffset - (lastScrollPos - scrollPos) / 100.dp.toPixels()).coerceIn(0f, 1f)
}
val scope = rememberCoroutineScope()
Box(
modifier = Modifier
.fillMaxSize()
) {
BackHandler {
scope.launch {
if (pagerState.currentPage > 0) {
pagerState.animateScrollToPage(0)
} else if (widgetColumnState.value > 0) {
widgetColumnState.animateScrollTo(0)
}
}
}
NavBarEffects(
modifier = Modifier.fillMaxSize()
)
HorizontalPager(
state = pagerState,
modifier = Modifier.fillMaxSize(),
count = 2
) { page ->
when (page) {
0 -> WidgetColumn(
modifier = Modifier.fillMaxSize(),
scrollState = widgetColumnState
)
1 -> SearchColumn(
modifier = Modifier.fillMaxSize(),
listState = searchColumnState
)
}
}
val scope = rememberCoroutineScope()
SearchBar(
modifier = Modifier
.systemBarsPadding()
.padding(8.dp),
pagerState = pagerState,
widgetColumnState = widgetColumnState,
offScreen = searchBarOffset,
onFocus = {
scope.launch {
pagerState.animateScrollToPage(1)
}
}
)
}
}
enum class Page {
Home, Search
}
enum class SwipeState {
Initial,
Swiping
}

View File

@ -1,170 +0,0 @@
package de.mm20.launcher2.ui.screens.settings
import android.content.Intent
import android.net.Uri
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Info
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.core.content.FileProvider
import de.mm20.launcher2.crashreporter.CrashReporter
import de.mm20.launcher2.debug.DebugInformationDumper
import de.mm20.launcher2.ktx.tryStartActivity
import de.mm20.launcher2.licenses.OpenSourceLicenses
import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.component.preferences.Preference
import de.mm20.launcher2.ui.component.preferences.PreferenceCategory
import de.mm20.launcher2.ui.component.preferences.PreferenceScreen
import de.mm20.launcher2.ui.icons.Fdroid
import de.mm20.launcher2.ui.icons.GitHub
import de.mm20.launcher2.ui.icons.Telegram
import de.mm20.launcher2.ui.locals.LocalNavController
import kotlinx.coroutines.launch
import java.io.File
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SettingsAboutScreen() {
val context = LocalContext.current
val navController = LocalNavController.current
val scope = rememberCoroutineScope()
PreferenceScreen(
title = stringResource(id = R.string.preference_screen_about),
) {
item {
PreferenceCategory {
val version = context.packageManager.getPackageInfo(
context.packageName,
0
).versionName
Preference(
title = stringResource(id = R.string.preference_version),
summary = version
)
}
}
item {
PreferenceCategory(title = stringResource(id = R.string.preference_category_license)) {
Preference(
icon = Icons.Rounded.Info,
title = stringResource(id = R.string.preference_about_license),
summary = stringResource(id = R.string.preference_about_license_summary),
onClick = {
navController?.navigate("settings/license")
}
)
}
}
item {
PreferenceCategory(title = stringResource(id = R.string.preference_category_links)) {
Preference(
icon = Icons.Rounded.Telegram,
title = stringResource(id = R.string.preference_about_telegram),
summary = "t.me/Kvaesitso",
onClick = {
context.startActivity(Intent(Intent.ACTION_VIEW).apply {
data = Uri.parse("https://t.me/Kvaesitso")
})
}
)
Preference(
icon = Icons.Rounded.Fdroid,
title = stringResource(id = R.string.preference_about_fdroid),
summary = "github.com/MM2-0/fdroid",
onClick = {
context.startActivity(Intent(Intent.ACTION_VIEW).apply {
data =
Uri.parse("https://raw.githubusercontent.com/MM2-0/fdroid/master/fdroid/repo")
})
}
)
Preference(
icon = Icons.Rounded.GitHub,
title = "GitHub",
summary = "github.com/MM2-0/Kvaesitso",
onClick = {
context.startActivity(Intent(Intent.ACTION_VIEW).apply {
data = Uri.parse("https://github.com/MM2-0/Kvaesitso")
})
}
)
}
}
item {
PreferenceCategory(title = stringResource(id = R.string.preference_category_debug)) {
Preference(
title = stringResource(id = R.string.preference_crash_reporter),
onClick = {
context.startActivity(CrashReporter.getLaunchIntent())
}
)
Preference(
title = stringResource(id = R.string.preference_export_debug),
onClick = {
scope.launch {
val path = DebugInformationDumper().dump(context)
/*val result = scaffoldState.snackbarHostState.showSnackbar(
context.getString(R.string.debug_export_information_file, path),
actionLabel = context.getString(R.string.menu_share),
duration = SnackbarDuration.Long
)
if (result == SnackbarResult.ActionPerformed) {
context.tryStartActivity(Intent(Intent.ACTION_SEND).apply {
type = "text/plain"
putExtra(
Intent.EXTRA_STREAM, FileProvider.getUriForFile(
context,
context.applicationContext.packageName + ".fileprovider",
File(path)
)
)
})
}*/
}
}
)
Preference(
title = stringResource(id = R.string.preference_export_databases),
onClick = {
scope.launch {
val path = DebugInformationDumper().exportDatabases(context)
/*val result = scaffoldState.snackbarHostState.showSnackbar(
context.getString(R.string.debug_export_information_file, path),
actionLabel = context.getString(R.string.menu_share),
duration = SnackbarDuration.Long
)
if (result == SnackbarResult.ActionPerformed) {
context.tryStartActivity(Intent(Intent.ACTION_SEND).apply {
type = "application/x-sqlite3"
putExtra(
Intent.EXTRA_STREAM, FileProvider.getUriForFile(
context,
context.applicationContext.packageName + ".fileprovider",
File(path)
)
)
})
}*/
}
}
)
}
}
item {
PreferenceCategory(title = stringResource(id = R.string.preference_category_licenses)) {
for (library in OpenSourceLicenses.sortedBy { it.name.lowercase() }) {
Preference(
title = library.name,
summary = library.description,
onClick = {
navController?.navigate("settings/license?library=${library.name}")
}
)
}
}
}
}
}

View File

@ -1,173 +0,0 @@
package de.mm20.launcher2.ui.screens.settings
import android.app.Activity
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.runtime.*
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import de.mm20.launcher2.gservices.GoogleAccount
import de.mm20.launcher2.gservices.GoogleApiHelper
import de.mm20.launcher2.msservices.MicrosoftGraphApiHelper
import de.mm20.launcher2.msservices.MsUser
import de.mm20.launcher2.nextcloud.NcUser
import de.mm20.launcher2.nextcloud.NextcloudApiHelper
import de.mm20.launcher2.owncloud.OcUser
import de.mm20.launcher2.owncloud.OwncloudClient
import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.component.preferences.Preference
import de.mm20.launcher2.ui.component.preferences.PreferenceCategory
import de.mm20.launcher2.ui.component.preferences.PreferenceScreen
import kotlinx.coroutines.launch
@Composable
fun SettingsAccountScreen() {
val context = LocalContext.current
val scope = rememberCoroutineScope()
PreferenceScreen(title = stringResource(id = R.string.preference_screen_services)) {
item {
PreferenceCategory(title = stringResource(id = R.string.preference_category_services_nextcloud)) {
val client = remember { NextcloudApiHelper(context) }
var account by remember { mutableStateOf<NcUser?>(null) }
LaunchedEffect(null) {
account = client.getLoggedInUser()
}
val launcher =
rememberLauncherForActivityResult(contract = ActivityResultContracts.StartActivityForResult()) {
scope.launch {
account = client.getLoggedInUser()
}
}
Preference(
title = account?.let {
stringResource(id = R.string.preference_signin_logout)
} ?: stringResource(id = R.string.preference_nextcloud_signin),
summary = account?.let {
stringResource(
id = R.string.preference_signin_user,
it.displayName
)
} ?: stringResource(id = R.string.preference_nextcloud_signin_summary),
onClick = {
if (account == null) {
launcher.launch(client.getLoginIntent())
} else {
scope.launch {
client.logout()
account = null
}
}
}
)
}
PreferenceCategory(title = stringResource(id = R.string.preference_category_services_owncloud)) {
val client = remember { OwncloudClient(context) }
var account by remember { mutableStateOf<OcUser?>(null) }
LaunchedEffect(null) {
account = client.getLoggedInUser()
}
val launcher =
rememberLauncherForActivityResult(contract = ActivityResultContracts.StartActivityForResult()) {
scope.launch {
account = client.getLoggedInUser()
}
}
Preference(
title = account?.let {
stringResource(id = R.string.preference_signin_logout)
} ?: stringResource(id = R.string.preference_owncloud_signin),
summary = account?.let {
stringResource(
id = R.string.preference_signin_user,
it.displayName
)
} ?: stringResource(id = R.string.preference_owncloud_signin_summary),
onClick = {
if (account == null) {
launcher.launch(client.getLoginIntent())
} else {
scope.launch {
client.logout()
account = null
}
}
}
)
}
PreferenceCategory(title = stringResource(id = R.string.preference_category_services_google)) {
val client = remember { GoogleApiHelper.getInstance(context) }
var account by remember { mutableStateOf<GoogleAccount?>(null) }
LaunchedEffect(null) {
account = client.getAccount()
}
Preference(
title = account?.let {
stringResource(id = R.string.preference_signin_logout)
} ?: stringResource(id = R.string.preference_google_signin),
summary = if (client.isAvailable()) {
account?.let {
stringResource(
id = R.string.preference_signin_user,
it.name
)
} ?: stringResource(id = R.string.preference_google_signin_summary)
} else {
stringResource(id = R.string.feature_not_available, stringResource(R.string.app_name))
},
onClick = {
if (account == null) {
scope.launch {
client.login(context as Activity)
account = client.getAccount()
}
} else {
client.logout()
account = null
}
},
enabled = client.isAvailable()
)
}
PreferenceCategory(title = stringResource(id = R.string.preference_category_services_microsoft)) {
val client = remember { MicrosoftGraphApiHelper.getInstance(context) }
var account by remember { mutableStateOf<MsUser?>(null) }
LaunchedEffect(null) {
account = client.getUser()
}
Preference(
title = account?.let {
stringResource(id = R.string.preference_signin_logout)
} ?: stringResource(id = R.string.preference_ms_signin),
summary = if (client.isAvailable()) {
account?.let {
stringResource(
id = R.string.preference_signin_user,
it.name
)
} ?: stringResource(id = R.string.preference_ms_signin_summary)
} else {
stringResource(id = R.string.feature_not_available, stringResource(R.string.app_name))
},
onClick = {
if (account == null) {
scope.launch {
client.login(context as Activity)
account = client.getUser()
}
} else {
scope.launch {
client.logout()
account = null
}
}
},
enabled = client.isAvailable()
)
}
}
}
}

View File

@ -1,17 +0,0 @@
package de.mm20.launcher2.ui.screens.settings
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.res.stringResource
import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.component.preferences.PreferenceScreen
@Composable
fun SettingsBadgesScreen() {
val scope = rememberCoroutineScope()
PreferenceScreen(
title = stringResource(id = R.string.preference_screen_badges)
) {
}
}

View File

@ -1,93 +0,0 @@
package de.mm20.launcher2.ui.screens.settings
import android.content.Intent
import android.net.Uri
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Icon
import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.OpenInBrowser
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import de.mm20.launcher2.licenses.AppLicense
import de.mm20.launcher2.licenses.OpenSourceLicenses
import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.component.preferences.PreferenceCategory
import de.mm20.launcher2.ui.component.preferences.PreferenceScreen
@Composable
fun SettingsLicenseScreen(libraryName: String? = null) {
val context = LocalContext.current
val library = if (libraryName == null) {
AppLicense.get(context)
} else {
OpenSourceLicenses.first { it.name == libraryName }
}
PreferenceScreen(title = stringResource(id = R.string.preference_screen_about)) {
item {
PreferenceCategory {
Column(
modifier = Modifier.padding(16.dp)
) {
Text(text = library.name, style = MaterialTheme.typography.titleMedium)
library.description?.let { Text(text = it) }
}
CompositionLocalProvider(
LocalContentColor provides MaterialTheme.colorScheme.primary
) {
Row(
modifier = Modifier
.fillMaxWidth()
.clickable {
context.startActivity(Intent(Intent.ACTION_VIEW).apply {
data = Uri.parse(library.url)
})
}
.padding(all = 16.dp),
verticalAlignment = Alignment.CenterVertically,
) {
Icon(imageVector = Icons.Rounded.OpenInBrowser, contentDescription = null)
Text(
modifier = Modifier.padding(start = 8.dp),
text = stringResource(id = R.string.open_webpage),
style = MaterialTheme.typography.labelMedium
)
}
}
}
}
item {
PreferenceCategory {
Column(
modifier = Modifier.padding(16.dp)
) {
Text(
text = stringResource(id = library.licenseName),
style = MaterialTheme.typography.titleMedium
)
library.copyrightNote?.let {
Text(
text = it,
modifier = Modifier.padding(vertical = 4.dp)
)
}
Text(
text = context.resources.openRawResource(library.licenseText).reader()
.readText()
)
}
}
}
}
}

View File

@ -1,72 +0,0 @@
package de.mm20.launcher2.ui.screens.settings
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.component.preferences.Preference
import de.mm20.launcher2.ui.component.preferences.PreferenceCategory
import de.mm20.launcher2.ui.component.preferences.PreferenceScreen
import de.mm20.launcher2.ui.icons.NotificationBadge
import de.mm20.launcher2.ui.locals.LocalNavController
@Composable
fun SettingsMainScreen() {
val navController = LocalNavController.current
PreferenceScreen(
title = stringResource(id = R.string.title_activity_settings)
) {
item {
PreferenceCategory {
Preference(
icon = Icons.Rounded.Palette,
title = stringResource(id = R.string.preference_screen_appearance),
summary = stringResource(id = R.string.preference_screen_appearance_summary),
onClick = {
navController?.navigate("settings/appearance")
}
)
Preference(
icon = Icons.Rounded.Search,
title = stringResource(id = R.string.preference_screen_search),
summary = stringResource(id = R.string.preference_screen_search_summary)
)
Preference(
icon = Icons.Rounded.NotificationBadge,
title = stringResource(id = R.string.preference_screen_badges),
summary = stringResource(id = R.string.preference_screen_badges_summary),
onClick = {
navController?.navigate("settings/badges")
}
)
Preference(
icon = Icons.Rounded.LightMode,
title = stringResource(id = R.string.preference_screen_weatherwidget),
summary = stringResource(id = R.string.preference_screen_weather_summary)
)
Preference(
icon = Icons.Rounded.Today,
title = stringResource(id = R.string.preference_screen_calendarwidget),
summary = stringResource(id = R.string.preference_screen_calendar_summary)
)
Preference(
icon = Icons.Rounded.AccountBox,
title = stringResource(id = R.string.preference_screen_services),
summary = stringResource(id = R.string.preference_screen_services_summary),
onClick = {
navController?.navigate("settings/accounts")
}
)
Preference(
icon = Icons.Rounded.Info,
title = stringResource(id = R.string.preference_screen_about),
summary = stringResource(id = R.string.preference_screen_about_summary),
onClick = {
navController?.navigate("settings/about")
}
)
}
}
}
}