Merge remote-tracking branch 'origin/move-gplay-variant-to-ose' into move-gplay-variant-to-ose

This commit is contained in:
Arnau Mora
2025-10-25 14:16:56 +02:00
15 changed files with 625 additions and 0 deletions

View File

@@ -0,0 +1,41 @@
/*
* Copyright © All Contributors. See LICENSE and AUTHORS in the root directory for details.
*/
package at.bitfire.davdroid.di
import at.bitfire.davdroid.ui.intro.StandardAndGplayIntroPageFactory
import at.bitfire.davdroid.ui.intro.IntroPageFactory
import at.bitfire.davdroid.ui.setup.LoginTypesProvider
import at.bitfire.davdroid.ui.setup.StandardLoginTypesProvider
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ActivityComponent
import dagger.hilt.android.components.ViewModelComponent
import dagger.hilt.components.SingletonComponent
interface StandardAndGplayModules {
@Module
@InstallIn(ActivityComponent::class)
interface ForActivities {
@Binds
fun loginTypesProvider(impl: StandardLoginTypesProvider): LoginTypesProvider
}
@Module
@InstallIn(ViewModelComponent::class)
interface ForViewModels {
@Binds
fun loginTypesProvider(impl: StandardLoginTypesProvider): LoginTypesProvider
}
@Module
@InstallIn(SingletonComponent::class)
interface Global {
@Binds
fun introPageFactory(impl: StandardAndGplayIntroPageFactory): IntroPageFactory
}
}

View File

@@ -0,0 +1,148 @@
/*
* Copyright © All Contributors. See LICENSE and AUTHORS in the root directory for details.
*/
package at.bitfire.davdroid.ui
import androidx.compose.foundation.layout.Column
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.HelpCenter
import androidx.compose.material.icons.filled.CloudOff
import androidx.compose.material.icons.filled.CorporateFare
import androidx.compose.material.icons.filled.Forum
import androidx.compose.material.icons.filled.Home
import androidx.compose.material.icons.filled.Info
import androidx.compose.material.icons.filled.VolunteerActivism
import androidx.compose.material3.SnackbarHostState
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import at.bitfire.davdroid.R
import at.bitfire.davdroid.ui.ExternalUris.Homepage
import at.bitfire.davdroid.ui.ExternalUris.Social
import at.bitfire.davdroid.ui.ExternalUris.withStatParams
import javax.inject.Inject
open class StandardAccountsDrawerHandler @Inject constructor(): AccountsDrawerHandler() {
@Composable
override fun MenuEntries(
snackbarHostState: SnackbarHostState
) {
val uriHandler = LocalUriHandler.current
// Most important entries
ImportantEntries(snackbarHostState)
// News
MenuHeading(R.string.navigation_drawer_news_updates)
MenuEntry(
icon = painterResource(R.drawable.mastodon),
title = Social.fediverseHandle,
onClick = {
uriHandler.openUri(Social.fediverseUrl.toString())
}
)
// Tools
Tools()
// Support the project
MenuHeading(R.string.navigation_drawer_support_project)
Contribute(onContribute = {
uriHandler.openUri(
Homepage.baseUrl.buildUpon()
.appendPath(Homepage.PATH_OPEN_SOURCE)
.withStatParams(javaClass.simpleName)
.build().toString()
)
})
MenuEntry(
icon = Icons.Default.Forum,
title = stringResource(R.string.navigation_drawer_community),
onClick = {
uriHandler.openUri(Social.discussionsUrl.toString())
}
)
// External links
MenuHeading(R.string.navigation_drawer_external_links)
MenuEntry(
icon = Icons.Default.Home,
title = stringResource(R.string.navigation_drawer_website),
onClick = {
uriHandler.openUri(
Homepage.baseUrl
.buildUpon()
.withStatParams(javaClass.simpleName)
.build().toString())
}
)
MenuEntry(
icon = Icons.Default.Info,
title = stringResource(R.string.navigation_drawer_manual),
onClick = {
uriHandler.openUri(ExternalUris.Manual.baseUrl.toString())
}
)
MenuEntry(
icon = Icons.AutoMirrored.Default.HelpCenter,
title = stringResource(R.string.navigation_drawer_faq),
onClick = {
uriHandler.openUri(
Homepage.baseUrl.buildUpon()
.appendPath(Homepage.PATH_FAQ)
.withStatParams(javaClass.simpleName)
.build().toString()
)
}
)
MenuEntry(
icon = Icons.Default.CorporateFare,
title = stringResource(R.string.navigation_drawer_managed),
onClick = {
uriHandler.openUri(
Homepage.baseUrl.buildUpon()
.appendPath(Homepage.PATH_ORGANIZATIONS)
.appendPath(Homepage.PATH_ORGANIZATIONS_MANAGED)
.withStatParams(javaClass.simpleName)
.build().toString()
)
}
)
MenuEntry(
icon = Icons.Default.CloudOff,
title = stringResource(R.string.navigation_drawer_privacy_policy),
onClick = {
uriHandler.openUri(
Homepage.baseUrl.buildUpon()
.appendPath(Homepage.PATH_PRIVACY)
.withStatParams(javaClass.simpleName)
.build().toString()
)
}
)
}
@Composable
@Preview
fun MenuEntries_Standard_Preview() {
Column {
MenuEntries(SnackbarHostState())
}
}
@Composable
open fun Contribute(onContribute: () -> Unit) {
MenuEntry(
icon = Icons.Default.VolunteerActivism,
title = stringResource(R.string.navigation_drawer_contribute),
onClick = onContribute
)
}
}

View File

@@ -0,0 +1,167 @@
/*
* Copyright © All Contributors. See LICENSE and AUTHORS in the root directory for details.
*/
package at.bitfire.davdroid.ui
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.ui.graphics.Color
@Suppress("MemberVisibilityCanBePrivate")
object M3ColorScheme {
// All colors hand-crafted because Material Theme Builder generates unbelievably ugly colors
val primaryLight = Color(0xFF7cb342)
val onPrimaryLight = Color(0xFFffffff)
val primaryContainerLight = Color(0xFFb4e47d)
val onPrimaryContainerLight = Color(0xFF232d18)
val secondaryLight = Color(0xFFff7f2a)
val onSecondaryLight = Color(0xFFFFFFFF)
val secondaryContainerLight = Color(0xFFffa565)
val onSecondaryContainerLight = Color(0xFF3a271b)
val tertiaryLight = Color(0xFF658a24)
val onTertiaryLight = Color(0xFFFFFFFF)
val tertiaryContainerLight = Color(0xFFb0d08e)
val onTertiaryContainerLight = Color(0xFF263015)
val errorLight = Color(0xFFd71717)
val onErrorLight = Color(0xFFFFFFFF)
val errorContainerLight = Color(0xFFefb6b6)
val onErrorContainerLight = Color(0xFF3a0b0b)
val backgroundLight = Color(0xFFfcfcfc)
val onBackgroundLight = Color(0xFF2a2a2a)
val surfaceLight = Color(0xFFf5f5f5)
val onSurfaceLight = Color(0xFF4d4d4d)
val surfaceVariantLight = Color(0xFFe4e4e4)
val onSurfaceVariantLight = Color(0xFF2a2a2a)
val outlineLight = Color(0xFF838383)
val outlineVariantLight = Color(0xFFd4d4d4)
val scrimLight = Color(0xFF000000)
val inverseSurfaceLight = Color(0xFF2e322b)
val inverseOnSurfaceLight = Color(0xFFfafaf8)
val inversePrimaryLight = Color(0xFFb4e47d)
val surfaceDimLight = Color(0xFFe3e3e3)
val surfaceBrightLight = Color(0xFFf9f9f9)
val surfaceContainerLowestLight = Color(0xFFFFFFFF)
val surfaceContainerLowLight = Color(0xFFfafafa)
val surfaceContainerLight = Color(0xFFf5f5f5)
val surfaceContainerHighLight = Color(0xFFf0f0ef)
val surfaceContainerHighestLight = Color(0xFFebebea)
val primaryDark = Color(0xFFc4e3a4)
val onPrimaryDark = Color(0xFF2b4310)
val primaryContainerDark = Color(0xFF7cb342)
val onPrimaryContainerDark = Color(0xFFedf5e4)
val secondaryDark = Color(0xFFe5c3ac)
val onSecondaryDark = Color(0xFF3e332e)
val secondaryContainerDark = Color(0xFFff7f2a)
val onSecondaryContainerDark = Color(0xFFffeadb)
val tertiaryDark = Color(0xFFc6e597)
val onTertiaryDark = Color(0xFF4b661b)
val tertiaryContainerDark = Color(0xFF658a24)
val onTertiaryContainerDark = Color(0xFFf0f8e2)
val errorDark = Color(0xFFf6d0d0)
val onErrorDark = Color(0xFF4f1212)
val errorContainerDark = Color(0xFFe93434)
val onErrorContainerDark = Color(0xFFfcdede)
val backgroundDark = Color(0xFF1a1a1a)
val onBackgroundDark = Color(0xFFf0f0f0)
val surfaceDark = Color(0xFF292929)
val onSurfaceDark = Color(0xFFdedede)
val surfaceVariantDark = Color(0xFF363636)
val onSurfaceVariantDark = Color(0xFFededed)
val outlineDark = Color(0xFFa3a3a3)
val outlineVariantDark = Color(0xFF7cb342)
val scrimDark = Color(0xFF000000)
val inverseSurfaceDark = Color(0xFFdbdbdb)
val inverseOnSurfaceDark = Color(0xFF292929)
val inversePrimaryDark = Color(0xFF7cb342)
val surfaceDimDark = Color(0xFF333333)
val surfaceBrightDark = Color(0xFF4d4d4d)
val surfaceContainerLowestDark = Color(0xFF141414)
val surfaceContainerLowDark = Color(0xFF1f1f1f)
val surfaceContainerDark = Color(0xff3a3a3a)
val surfaceContainerHighDark = Color(0xFF383838)
val surfaceContainerHighestDark = Color(0xFF434343)
// Copied from Material Theme Builder: Theme.kt
val lightScheme = lightColorScheme(
primary = primaryLight,
onPrimary = onPrimaryLight,
primaryContainer = primaryContainerLight,
onPrimaryContainer = onPrimaryContainerLight,
secondary = secondaryLight,
onSecondary = onSecondaryLight,
secondaryContainer = secondaryContainerLight,
onSecondaryContainer = onSecondaryContainerLight,
tertiary = tertiaryLight,
onTertiary = onTertiaryLight,
tertiaryContainer = tertiaryContainerLight,
onTertiaryContainer = onTertiaryContainerLight,
error = errorLight,
onError = onErrorLight,
errorContainer = errorContainerLight,
onErrorContainer = onErrorContainerLight,
background = backgroundLight,
onBackground = onBackgroundLight,
surface = surfaceLight,
onSurface = onSurfaceLight,
surfaceVariant = surfaceVariantLight,
onSurfaceVariant = onSurfaceVariantLight,
outline = outlineLight,
outlineVariant = outlineVariantLight,
scrim = scrimLight,
inverseSurface = inverseSurfaceLight,
inverseOnSurface = inverseOnSurfaceLight,
inversePrimary = inversePrimaryLight,
surfaceDim = surfaceDimLight,
surfaceBright = surfaceBrightLight,
surfaceContainerLowest = surfaceContainerLowestLight,
surfaceContainerLow = surfaceContainerLowLight,
surfaceContainer = surfaceContainerLight,
surfaceContainerHigh = surfaceContainerHighLight,
surfaceContainerHighest = surfaceContainerHighestLight,
)
val darkScheme = darkColorScheme(
primary = primaryDark,
onPrimary = onPrimaryDark,
primaryContainer = primaryContainerDark,
onPrimaryContainer = onPrimaryContainerDark,
secondary = secondaryDark,
onSecondary = onSecondaryDark,
secondaryContainer = secondaryContainerDark,
onSecondaryContainer = onSecondaryContainerDark,
tertiary = tertiaryDark,
onTertiary = onTertiaryDark,
tertiaryContainer = tertiaryContainerDark,
onTertiaryContainer = onTertiaryContainerDark,
error = errorDark,
onError = onErrorDark,
errorContainer = errorContainerDark,
onErrorContainer = onErrorContainerDark,
background = backgroundDark,
onBackground = onBackgroundDark,
surface = surfaceDark,
onSurface = onSurfaceDark,
surfaceVariant = surfaceVariantDark,
onSurfaceVariant = onSurfaceVariantDark,
outline = outlineDark,
outlineVariant = outlineVariantDark,
scrim = scrimDark,
inverseSurface = inverseSurfaceDark,
inverseOnSurface = inverseOnSurfaceDark,
inversePrimary = inversePrimaryDark,
surfaceDim = surfaceDimDark,
surfaceBright = surfaceBrightDark,
surfaceContainerLowest = surfaceContainerLowestDark,
surfaceContainerLow = surfaceContainerLowDark,
surfaceContainer = surfaceContainerDark,
surfaceContainerHigh = surfaceContainerHighDark,
surfaceContainerHighest = surfaceContainerHighestDark,
)
}

View File

@@ -0,0 +1,22 @@
/*
* Copyright © All Contributors. See LICENSE and AUTHORS in the root directory for details.
*/
package at.bitfire.davdroid.ui.intro
import javax.inject.Inject
class StandardAndGplayIntroPageFactory @Inject constructor(
batteryOptimizationsPage: BatteryOptimizationsPage,
permissionsIntroPage: PermissionsIntroPage,
tasksIntroPage: TasksIntroPage
): IntroPageFactory {
override val introPages = arrayOf(
WelcomePage(),
tasksIntroPage,
permissionsIntroPage,
batteryOptimizationsPage
)
}

View File

@@ -0,0 +1,121 @@
/*
* Copyright © All Contributors. See LICENSE and AUTHORS in the root directory for details.
*/
package at.bitfire.davdroid.ui.setup
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.RadioButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.core.text.HtmlCompat
import at.bitfire.davdroid.R
import at.bitfire.davdroid.ui.ExternalUris
import at.bitfire.davdroid.ui.ExternalUris.withStatParams
import at.bitfire.davdroid.ui.UiUtils.toAnnotatedString
import at.bitfire.davdroid.ui.composable.Assistant
@Composable
fun StandardLoginTypePage(
selectedLoginType: LoginType,
onSelectLoginType: (LoginType) -> Unit,
@Suppress("unused") // for build variants
setInitialLoginInfo: (LoginInfo) -> Unit,
onContinue: () -> Unit = {}
) {
Assistant(
nextLabel = stringResource(R.string.login_continue),
nextEnabled = true,
onNext = onContinue
) {
Column(Modifier.padding(8.dp)) {
Text(
stringResource(R.string.login_generic_login),
style = MaterialTheme.typography.headlineSmall,
modifier = Modifier.padding(vertical = 8.dp)
)
for (type in StandardLoginTypesProvider.genericLoginTypes)
LoginTypeSelector(
title = stringResource(type.title),
selected = type == selectedLoginType,
onSelect = { onSelectLoginType(type) }
)
Text(
stringResource(R.string.login_provider_login),
style = MaterialTheme.typography.headlineSmall,
modifier = Modifier.padding(top = 16.dp, bottom = 8.dp)
)
for (type in StandardLoginTypesProvider.specificLoginTypes)
LoginTypeSelector(
title = stringResource(type.title),
selected = type == selectedLoginType,
onSelect = { onSelectLoginType(type) }
)
HorizontalDivider(Modifier.padding(vertical = 12.dp))
val privacyPolicy = ExternalUris.Homepage.baseUrl.buildUpon()
.appendPath(ExternalUris.Homepage.PATH_PRIVACY)
.withStatParams("StandardLoginTypePage")
.build().toString()
val privacy = HtmlCompat.fromHtml(
stringResource(R.string.login_privacy_hint, stringResource(R.string.app_name), privacyPolicy),
HtmlCompat.FROM_HTML_MODE_COMPACT)
Text(
text = privacy.toAnnotatedString(),
style = MaterialTheme.typography.bodyMedium
)
}
}
}
@Composable
fun LoginTypeSelector(
title: String,
selected: Boolean,
onSelect: () -> Unit = {}
) {
Column {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.clickable(onClick = onSelect)
.padding(bottom = 4.dp)
) {
RadioButton(
selected = selected,
onClick = onSelect
)
Text(
title,
style = MaterialTheme.typography.bodyLarge,
modifier = Modifier.weight(1f)
)
}
}
}
@Composable
@Preview
fun StandardLoginTypePage_Preview() {
StandardLoginTypePage(
selectedLoginType = StandardLoginTypesProvider.genericLoginTypes.first(),
onSelectLoginType = {},
setInitialLoginInfo = {},
onContinue = {}
)
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright © All Contributors. See LICENSE and AUTHORS in the root directory for details.
*/
package at.bitfire.davdroid.ui.setup
import android.content.Intent
import androidx.compose.material3.SnackbarHostState
import androidx.compose.runtime.Composable
import at.bitfire.davdroid.ui.setup.LoginTypesProvider.LoginAction
import java.util.logging.Logger
import javax.inject.Inject
class StandardLoginTypesProvider @Inject constructor(
private val logger: Logger
) : LoginTypesProvider {
companion object {
val genericLoginTypes = listOf(
UrlLogin,
EmailLogin,
AdvancedLogin
)
val specificLoginTypes = listOf(
FastmailLogin,
GoogleLogin,
NextcloudLogin
)
}
override val defaultLoginType = UrlLogin
override fun intentToInitialLoginType(intent: Intent): LoginAction =
intent.data?.normalizeScheme().let { uri ->
when {
intent.hasExtra(LoginActivity.EXTRA_LOGIN_FLOW) ->
LoginAction(NextcloudLogin, true)
uri?.scheme == "mailto" ->
LoginAction(EmailLogin, true)
listOf("caldavs", "carddavs", "davx5", "http", "https").any { uri?.scheme == it } ->
LoginAction(UrlLogin, true)
else -> {
logger.warning("Did not understand login intent: $intent")
LoginAction(defaultLoginType, false) // Don't skip login type page if intent is unclear
}
}
}
@Composable
override fun LoginTypePage(
snackbarHostState: SnackbarHostState,
selectedLoginType: LoginType,
onSelectLoginType: (LoginType) -> Unit,
setInitialLoginInfo: (LoginInfo) -> Unit,
onContinue: () -> Unit
) {
StandardLoginTypePage(
selectedLoginType = selectedLoginType,
onSelectLoginType = onSelectLoginType,
setInitialLoginInfo = setInitialLoginInfo,
onContinue = onContinue
)
}
}

View File

@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<!--suppress AndroidUnknownAttribute -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:viewportWidth="108"
android:viewportHeight="108"
android:width="108dp"
android:height="108dp">
<group
android:translateX="-213.3939"
android:translateY="-709.5244">
<group
android:scaleX="0.0662553"
android:scaleY="0.0662553"
android:translateX="233.5464"
android:translateY="729.8276">
<path
android:pathData="M282.78183 280.50711l-85.53115 -85.53116 -0.00001 228.08306 228.08306 0 -85.53115 -85.53114c94.36922 -94.36921 247.75506 -94.36951 342.12458 0.00001 28.79533 28.79533 49.03756 48.10677 59.87183 84.60006l83.25028 0c-12.82982 -57.30603 -41.34018 -96.85969 -86.10134 -141.62083 -126.01589 -126.0159 -330.15022 -126.0159 -456.1661 0zm399.14533 399.14532c-94.36952 94.36952 -247.75535 94.36921 -342.12458 0 -28.79562 -28.79564 -49.03816 -48.10677 -59.8718 -84.60006l-83.25029 0c12.82949 57.30571 41.33988 96.85938 86.10134 141.62083 126.01588 126.0159 330.15021 126.0159 456.1661 0l85.53115 85.53115 0.00001 -228.08305 -228.08307 0z"
android:fillColor="#ffffff" />
<path
android:pathData="M201.33878 550.34595l27.70423 0c25.78414 0 44.43649 -13.44067 44.43649 -44.98509 0 -31.54442 -18.65235 -44.16219 -45.80799 -44.16219l-26.33273 0zm23.58974 -18.92666l0 -51.29397 1.3715 0c12.89207 0 23.04114 4.38879 23.04114 25.23554 0 20.84675 -10.14907 26.05843 -23.04114 26.05843z"
android:fillColor="#ffffff" />
<path
android:pathData="M311.13854 507.00666c2.1944 -8.50328 4.38879 -19.20096 6.30889 -28.25283l0.5486 0c2.19439 8.91472 4.38879 19.74955 6.58318 28.25283l1.50865 6.17173 -16.45796 0zm-34.28741 43.33929l24.13834 0 4.38879 -18.92666 24.96124 0 4.38878 18.92666 24.96124 0 -27.15563 -89.14728 -28.52713 0z"
android:fillColor="#ffffff" />
<path
android:pathData="M380.56703 550.34595l28.52713 0 26.33273 -89.14728 -24.13834 0 -9.05188 38.9505c-2.33154 9.46333 -4.11449 18.65236 -6.58318 28.25283l-0.5486 0c-2.46869 -9.60047 -4.11449 -18.7895 -6.58318 -28.25283l-9.32618 -38.9505 -24.96124 0z"
android:fillColor="#ffffff" />
<path
android:pathData="M449.1301 596.08783l39.35586 0 6.19081 -15.47702c2.4321 -6.41191 5.0853 -12.82382 7.51741 -19.01463l0.8844 0c3.3165 6.19081 6.41191 12.82382 9.72841 19.01463l8.84401 15.47702 40.68246 0 -33.16504 -53.06408 31.39624 -57.48608 -39.35586 0 -5.3064 15.47703c-1.98991 6.1908 -4.64311 12.82381 -6.63301 19.01462l-0.8844 0c-2.87431 -6.19081 -5.96971 -12.82382 -8.84402 -19.01462l-7.95961 -15.47703 -40.68245 0 31.39624 53.06408z"
android:fillColor="#ffffff" />
<path
android:pathData="M601.43782 509.37229c18.53926 0 34.49164 -11.78465 34.49164 -32.19221 0 -19.25783 -13.50922 -28.16817 -29.3179 -28.16817 -3.01801 0 -5.46117 0.28743 -8.62291 1.43715l1.14972 -13.2218 32.76707 0 0 -20.69499 -54.03691 0 -2.29945 46.85116 10.63493 6.89832c5.46117 -3.44916 7.76062 -4.31145 12.64693 -4.31145 7.18576 0 12.35951 4.02402 12.35951 11.78464 0 8.04806 -4.88632 11.78465 -13.50923 11.78465 -6.6109 0 -12.93437 -3.73659 -18.39554 -8.62291l-10.92236 15.52124c7.47319 7.47319 18.10812 12.93437 33.0545 12.93437z"
android:fillColor="#ffffff" />
</group>
</group>
</vector>

View File

@@ -0,0 +1,8 @@
<!-- drawable/mastodon.xml -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:width="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path android:fillColor="#6364FF" android:pathData="M20.94,14C20.66,15.41 18.5,16.96 15.97,17.26C14.66,17.41 13.37,17.56 12,17.5C9.75,17.39 8,16.96 8,16.96V17.58C8.32,19.8 10.22,19.93 12.03,20C13.85,20.05 15.47,19.54 15.47,19.54L15.55,21.19C15.55,21.19 14.27,21.87 12,22C10.75,22.07 9.19,21.97 7.38,21.5C3.46,20.45 2.78,16.26 2.68,12L2.67,8.57C2.67,4.23 5.5,2.96 5.5,2.96C6.95,2.3 9.41,2 11.97,2H12.03C14.59,2 17.05,2.3 18.5,2.96C18.5,2.96 21.33,4.23 21.33,8.57C21.33,8.57 21.37,11.78 20.94,14M18,8.91C18,7.83 17.7,7 17.15,6.35C16.59,5.72 15.85,5.39 14.92,5.39C13.86,5.39 13.05,5.8 12.5,6.62L12,7.5L11.5,6.62C10.94,5.8 10.14,5.39 9.07,5.39C8.15,5.39 7.41,5.72 6.84,6.35C6.29,7 6,7.83 6,8.91V14.17H8.1V9.06C8.1,8 8.55,7.44 9.46,7.44C10.46,7.44 10.96,8.09 10.96,9.37V12.16H13.03V9.37C13.03,8.09 13.53,7.44 14.54,7.44C15.44,7.44 15.89,8 15.89,9.06V14.17H18V8.91Z" />
</vector>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/primaryColor" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<network-security-config xmlns:tools="http://schemas.android.com/tools">
<base-config cleartextTrafficPermitted="true" tools:ignore="InsecureBaseConfiguration">
<trust-anchors>
<certificates src="system"/>
<certificates src="user" tools:ignore="AcceptsUserCertificates" />
</trust-anchors>
</base-config>
</network-security-config>