Merge branch 'release/4.7.0' into main

This commit is contained in:
Rafał Kobyłko 2023-09-06 18:44:04 +02:00
commit d5c390634e
216 changed files with 5558 additions and 371 deletions

View File

@ -5,6 +5,7 @@ plugins {
alias(libs.plugins.kotlinSerialization)
alias(libs.plugins.kotlinParcelize)
alias(libs.plugins.kotlinKapt)
alias(libs.plugins.ksp)
id("com.google.gms.google-services")
id("com.google.firebase.crashlytics")
}

View File

@ -1,6 +1,7 @@
package com.twofasapp.ui.main
import android.app.Activity
import androidx.activity.compose.BackHandler
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.material.ExperimentalMaterialApi
@ -14,9 +15,14 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.platform.LocalContext
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import com.google.accompanist.navigation.material.BottomSheetNavigator
import com.google.accompanist.navigation.material.ExperimentalMaterialNavigationApi
import com.google.accompanist.navigation.material.bottomSheet
import com.twofasapp.android.navigation.Modal
import com.twofasapp.android.navigation.NavAnimation
import com.twofasapp.android.navigation.NavArg
import com.twofasapp.android.navigation.Screen
import com.twofasapp.android.navigation.clearGraphBackStack
import com.twofasapp.android.navigation.intentFor
import com.twofasapp.android.navigation.withArg
@ -31,9 +37,15 @@ import com.twofasapp.feature.browserext.notification.BrowserExtGraph
import com.twofasapp.feature.browserext.notification.browserExtNavigation
import com.twofasapp.feature.externalimport.navigation.ExternalImportGraph
import com.twofasapp.feature.externalimport.navigation.externalImportNavigation
import com.twofasapp.feature.home.navigation.GuideInitRoute
import com.twofasapp.feature.home.navigation.GuidePagerRoute
import com.twofasapp.feature.home.navigation.GuidesRoute
import com.twofasapp.feature.home.navigation.HomeGraph
import com.twofasapp.feature.home.navigation.HomeNavigationListener
import com.twofasapp.feature.home.navigation.HomeNode
import com.twofasapp.feature.home.navigation.NotificationsGraph
import com.twofasapp.feature.home.navigation.homeNavigation
import com.twofasapp.feature.home.navigation.notificationsNavigation
import com.twofasapp.feature.home.ui.services.add.AddServiceModal
import com.twofasapp.feature.home.ui.services.focus.FocusServiceModal
import com.twofasapp.feature.home.ui.services.focus.FocusServiceModalNavArg
@ -70,6 +82,12 @@ internal fun MainNavHost(
var recentlyAddedService by remember { mutableStateOf<RecentlyAddedService?>(null) }
BackHandler(enabled = bottomSheetNavigator.navigatorSheetState.isVisible) {
scope.launch {
navController.popBackStack()
}
}
ModalBottomSheet(
onDismissRequest = {
if (recentlyAddedService != null) {
@ -82,7 +100,9 @@ internal fun MainNavHost(
NavHost(
navController = navController,
startDestination = startDestination
startDestination = startDestination,
enterTransition = NavAnimation.Enter,
exitTransition = NavAnimation.Exit,
) {
startupNavigation(
@ -120,17 +140,21 @@ internal fun MainNavHost(
navController.navigate(TrashGraph.route)
}
override fun openNotifications() {
navController.navigate(NotificationsGraph.route)
}
override fun openAbout() {
navController.navigate(AboutGraph.route)
}
override fun openAddServiceModal() {
recentlyAddedService = null
navController.navigate(ModalNavigation.AddService.route)
navController.navigate(Modal.AddService.route)
}
override fun openFocusServiceModal(id: Long) {
navController.navigate(ModalNavigation.FocusService.route.replace("{id}", id.toString()))
navController.navigate(Modal.FocusService.route.replace("{id}", id.toString()))
}
}
)
@ -151,18 +175,21 @@ internal fun MainNavHost(
)
appSettingsNavigation()
notificationsNavigation()
trashNavigation(navController = navController)
aboutNavigation(navController = navController)
browserExtNavigation(navController = navController)
securityNavigation(navController = navController)
bottomSheet(ModalNavigation.AddService.route) {
bottomSheet(Modal.AddService.route, listOf(NavArg.AddServiceInitRoute)) {
AddServiceModal(
onAddedSuccessfully = { recentlyAddedService = it }
initRoute = it.arguments?.getString(NavArg.AddServiceInitRoute.name),
onAddedSuccessfully = { recentlyAddedService = it },
openGuides = { navController.navigate(Screen.Guides.route) }
)
}
bottomSheet(ModalNavigation.FocusService.route, listOf(FocusServiceModalNavArg.ServiceId)) {
bottomSheet(Modal.FocusService.route, listOf(FocusServiceModalNavArg.ServiceId)) {
FocusServiceModal(
openService = {
navController.navigate(ServiceGraph.route.withArg(ServiceNavArg.ServiceId, it))
@ -170,6 +197,41 @@ internal fun MainNavHost(
}
)
}
composable(Screen.Guides.route) {
GuidesRoute(
openGuide = { navController.navigate(Screen.GuideInit.routeWithArgs(NavArg.Guide to it.name)) }
)
}
composable(Screen.GuideInit.route, listOf(NavArg.Guide)) {
GuideInitRoute(
guide = enumValueOf(it.arguments!!.getString(NavArg.Guide.name)!!),
openGuide = { guide, guideVariantIndex ->
navController.navigate(
Screen.GuidePager.routeWithArgs(
NavArg.Guide to guide.name,
NavArg.GuideVariantIndex to guideVariantIndex,
)
)
}
)
}
composable(Screen.GuidePager.route, listOf(NavArg.Guide, NavArg.GuideVariantIndex)) {
GuidePagerRoute(
guide = enumValueOf(it.arguments!!.getString(NavArg.Guide.name)!!),
guideVariantIndex = it.arguments!!.getInt(NavArg.GuideVariantIndex.name),
openAddScan = {
navController.popBackStack(HomeNode.Services.route, false)
navController.navigate(Modal.AddService.route)
},
openAddManually = {
navController.popBackStack(HomeNode.Services.route, false)
navController.navigate(Modal.AddService.routeWithArgs(NavArg.AddServiceInitRoute to "manual"))
},
)
}
}
}
}

View File

@ -7,12 +7,14 @@ import androidx.compose.material.rememberModalBottomSheetState
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.core.app.NotificationManagerCompat
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.NamedNavArgument
import androidx.navigation.NavHostController
import androidx.navigation.compose.rememberNavController
import com.google.accompanist.navigation.material.BottomSheetNavigator
@ -25,6 +27,7 @@ import com.twofasapp.designsystem.TwTheme
import com.twofasapp.feature.home.navigation.HomeGraph
import com.twofasapp.feature.startup.navigation.StartupGraph
import org.koin.androidx.compose.koinViewModel
import timber.log.Timber
@OptIn(ExperimentalMaterialNavigationApi::class, ExperimentalMaterialApi::class)
@Composable
@ -55,6 +58,22 @@ internal fun MainScreen(
val bottomSheetNavigator = remember { BottomSheetNavigator(sheetState) }
val navController: NavHostController = rememberNavController(bottomSheetNavigator)
val context = LocalContext.current
LaunchedEffect(Unit){
navController.addOnDestinationChangedListener { _, destination, arguments ->
val argumentsLog: String = if (destination.arguments.isEmpty()) {
""
} else {
"args=" + destination.arguments.map {
@Suppress("DEPRECATION")
"${it.key}=${arguments?.get(it.key)}"
}.toString()
}
Timber.tag("NavController").d("route=${destination.route} $argumentsLog")
}
}
if (uiState.startDestination != null && uiState.selectedTheme != null) {
CompositionLocalProvider(
LocalAppTheme provides when (uiState.selectedTheme!!) {

View File

@ -37,6 +37,10 @@ internal class MainViewModel(
val uiState: MutableStateFlow<MainUiState> = MutableStateFlow(MainUiState())
init {
launchScoped {
sessionRepository.markAppInstalled()
}
launchScoped {
val destination = when (sessionRepository.isOnboardingDisplayed()) {
true -> MainUiState.StartDestination.Home
@ -58,7 +62,7 @@ internal class MainViewModel(
}
launchScoped {
runSafely { notificationsRepository.fetchNotifications() }
runSafely { notificationsRepository.fetchNotifications(sessionRepository.getAppInstallTimestamp()) }
}
launchScoped {

View File

@ -1,7 +0,0 @@
package com.twofasapp.ui.main
sealed class ModalNavigation(val route: String) {
object FocusService : ModalNavigation("modal/focusservice/{id}")
object AddService : ModalNavigation("modal/addservice")
}

View File

@ -9,4 +9,6 @@
<locale android:name="uk" />
<locale android:name="it" />
<locale android:name="pl" />
<locale android:name="id" />
<locale android:name="nl" />
</locale-config>

View File

@ -7,8 +7,11 @@ import androidx.activity.compose.setContent
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.MaterialTheme
@ -16,6 +19,7 @@ import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
@ -29,6 +33,7 @@ import com.twofasapp.data.session.SettingsRepository
import com.twofasapp.design.theme.ThemeState
import com.twofasapp.designsystem.MainAppTheme
import com.twofasapp.designsystem.TwTheme
import com.twofasapp.designsystem.common.TwSwitch
import com.twofasapp.designsystem.common.TwTopAppBar
import com.twofasapp.resources.R
import com.twofasapp.services.domain.model.Service
@ -85,10 +90,46 @@ class BrowserExtensionRequestActivity : BaseComponentActivity() {
}
LazyColumn(modifier = modifier) {
item { HeaderItem(browserName = uiState.browserName, payload.domain, modifier = Modifier.animateItemPlacement()) }
item {
HeaderItem(
browserName = uiState.browserName,
domain = payload.domain,
modifier = Modifier.animateItemPlacement()
)
}
item {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 12.dp)
.clickable {
viewModel.updateSaveMyChoice(uiState.saveMyChoice.not())
}
.padding(horizontal = 16.dp, vertical = 4.dp),
verticalAlignment = Alignment.CenterVertically,
) {
Text(
text = stringResource(id = R.string.browser__save_choice),
color = TwTheme.color.onSurfacePrimary,
style = TwTheme.typo.body1,
modifier = Modifier.weight(1f)
)
Spacer(modifier = Modifier.width(8.dp))
TwSwitch(
checked = uiState.saveMyChoice,
onCheckedChange = { viewModel.updateSaveMyChoice(it) },
)
}
}
if (uiState.suggestedServices.isNotEmpty()) {
item { SectionItem(title = stringResource(id = R.string.extension__services_suggested_header), modifier = Modifier.animateItemPlacement()) }
item {
SectionItem(
title = stringResource(id = R.string.extension__services_suggested_header),
modifier = Modifier.animateItemPlacement()
)
}
items(uiState.suggestedServices, key = { it.id }) {
ServiceItem(
@ -132,7 +173,7 @@ class BrowserExtensionRequestActivity : BaseComponentActivity() {
text = stringResource(id = R.string.browser__request_source_description).format(browserName, domain),
modifier = modifier
.fillMaxWidth()
.padding(start = 72.dp, end = 16.dp, top = 24.dp, bottom = 24.dp),
.padding(16.dp),
style = MaterialTheme.typography.bodyMedium.copy(color = TwTheme.color.onSurfacePrimary)
)
}

View File

@ -6,4 +6,5 @@ data class BrowserExtensionRequestUiState(
val browserName: String = "",
val suggestedServices: List<Service> = emptyList(),
val otherServices: List<Service> = emptyList(),
val saveMyChoice: Boolean = false,
)

View File

@ -10,7 +10,6 @@ import com.twofasapp.services.domain.AssignServiceDomainCase
import com.twofasapp.services.domain.GetServicesCase
import com.twofasapp.services.domain.model.Service
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
@ -23,8 +22,7 @@ internal class BrowserExtensionRequestViewModel(
private val browserExtRepository: BrowserExtRepository,
) : BaseViewModel() {
private val _uiState = MutableStateFlow(BrowserExtensionRequestUiState())
val uiState = _uiState.asStateFlow()
val uiState = MutableStateFlow(BrowserExtensionRequestUiState())
fun init(
extensionId: String,
@ -38,7 +36,7 @@ internal class BrowserExtensionRequestViewModel(
val suggestedServices =
matchedServices.plus(DomainMatcher.findServicesSuggestedForDomain(services, domain).minus(matchedServices.toSet()))
_uiState.update { state ->
uiState.update { state ->
state.copy(
browserName = browsers.find { it.id == extensionId }?.name.orEmpty(),
suggestedServices = suggestedServices,
@ -55,9 +53,15 @@ internal class BrowserExtensionRequestViewModel(
onFinish: () -> Unit
) {
viewModelScope.launch(dispatchers.io()) {
assignServiceDomainCase(service, domain)
if (uiState.value.saveMyChoice) {
assignServiceDomainCase(service, domain)
}
browserExtRepository.deleteTokenRequest(requestId)
onFinish.invoke()
}
}
fun updateSaveMyChoice(checked: Boolean) {
uiState.update { it.copy(saveMyChoice = checked) }
}
}

View File

@ -2,12 +2,12 @@ package com.twofasapp.buildlogic.version
object AppConfig {
const val minSdk = 23
const val targetSdk = 33
const val compileSdk = 33
const val targetSdk = 34
const val compileSdk = 34
private const val verMajor = 4
private const val verMinor = 6
private const val verPatch = 3
private const val verMinor = 7
private const val verPatch = 0
private const val verInternal = 0
const val versionCode = verMajor * 1000000 + verMinor * 10000 + verPatch * 100 + verInternal

View File

@ -0,0 +1,13 @@
package com.twofasapp.android.navigation
import androidx.navigation.NamedNavArgument
sealed class Modal(val route: String) {
fun routeWithArgs(vararg args: Pair<NamedNavArgument, Any>): String {
return route.replaceArgsInRoute(*args)
}
data object FocusService : Modal("modal/focusservice/{id}")
data object AddService : Modal("modal/addservice?init={${NavArg.AddServiceInitRoute.name}}")
}

View File

@ -0,0 +1,18 @@
package com.twofasapp.android.navigation
import androidx.compose.animation.AnimatedContentTransitionScope
import androidx.compose.animation.EnterTransition
import androidx.compose.animation.ExitTransition
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.navigation.NavBackStackEntry
object NavAnimation {
val Enter: (AnimatedContentTransitionScope<NavBackStackEntry>.() -> EnterTransition) =
{ fadeIn(animationSpec = tween(250)) }
val Exit: (AnimatedContentTransitionScope<NavBackStackEntry>.() -> ExitTransition) =
{ fadeOut(animationSpec = tween(250)) }
}

View File

@ -0,0 +1,10 @@
package com.twofasapp.android.navigation
import androidx.navigation.NavType
import androidx.navigation.navArgument
object NavArg {
val AddServiceInitRoute = navArgument("AddServiceInitRoute") { type = NavType.StringType; nullable = true; defaultValue = null }
val Guide = navArgument("Guide") { type = NavType.StringType; }
val GuideVariantIndex = navArgument("GuideVariantIndex") { type = NavType.IntType; }
}

View File

@ -23,4 +23,10 @@ fun NamedNavArgument.withDefault(any: Any?): NamedNavArgument {
fun <T> SavedStateHandle.getOrThrow(key: String): T {
return get<T>(key) ?: throw IllegalNavArgException(key)
}
internal fun String.replaceArgsInRoute(vararg args: Pair<NamedNavArgument, Any>): String {
var routeWithArgs = this
args.forEach { arg -> routeWithArgs = routeWithArgs.withArg(arg.first, arg.second) }
return routeWithArgs
}

View File

@ -0,0 +1,14 @@
package com.twofasapp.android.navigation
import androidx.navigation.NamedNavArgument
sealed class Screen(val route: String) {
fun routeWithArgs(vararg args: Pair<NamedNavArgument, Any>): String {
return route.replaceArgsInRoute(*args)
}
data object Guides : Screen("guides")
data object GuideInit : Screen("guides/init?guide={${NavArg.Guide.name}}")
data object GuidePager : Screen("guides/pager?guide={${NavArg.Guide.name}}&variant={${NavArg.GuideVariantIndex.name}}")
}

View File

@ -64,4 +64,5 @@ object TwIcons {
val Screenshot @Composable get() = painterResource(R.drawable.ic_screenshot)
val Keyboard @Composable get() = painterResource(R.drawable.ic_keyboard)
val Panorama @Composable get() = painterResource(R.drawable.ic_panorama)
val Guide @Composable get() = painterResource(R.drawable.ic_guide)
}

View File

@ -1,7 +1,10 @@
package com.twofasapp.designsystem.internal
import androidx.compose.runtime.Composable
import androidx.compose.runtime.staticCompositionLocalOf
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.luminance
import com.twofasapp.designsystem.TwTheme
abstract class ThemeColors {
abstract val background: Color
@ -31,14 +34,19 @@ abstract class ThemeColors {
val accentLightBlue: Color = Color(0xFF7F9CFF)
val accentIndigo: Color = Color(0xFF5E5CE6)
val accentPurple: Color = Color(0xFFD95DDC)
val accentPurple: Color = Color(0xFF8C49DE)
val accentTurquoise: Color = Color(0xFF2FCFBC)
val accentGreen: Color = Color(0xFF03BF38)
val accentRed: Color = Color(0xFFED1C24)
val accentOrange: Color = Color(0xFFFF7A00)
val accentYellow: Color = Color(0xFFFFBA0A)
val accentPink: Color = Color(0xFFca49de)
val accentBrown: Color = Color(0xFFbd8857)
}
val LocalThemeColors = staticCompositionLocalOf<ThemeColors> {
ThemeColorsLight()
}
@Composable
fun isDarkTheme() = TwTheme.color.background.luminance() < 0.5

View File

@ -8,6 +8,7 @@ import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.sp
import com.twofasapp.designsystem.R
import com.twofasapp.designsystem.TwTheme
@Immutable
@Stable

View File

@ -140,6 +140,7 @@ fun DsService(
ServiceInfo(
text = state.info,
textStyles = textStyles,
style = style,
modifier = Modifier.fillMaxWidth(),
)

View File

@ -64,6 +64,7 @@ fun DsServiceModal(
ServiceInfo(
text = state.info,
textStyles = ServiceTextDefaults.modal(),
style = ServiceStyle.Default,
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp)

View File

@ -49,7 +49,7 @@ fun DsServiceSimple(
Column(Modifier.weight(1f)) {
ServiceName(text = state.name)
ServiceInfo(text = state.info)
ServiceInfo(text = state.info, spacer = false)
}
content()

View File

@ -3,7 +3,8 @@ package com.twofasapp.designsystem.service.atoms
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
@ -11,6 +12,7 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.twofasapp.designsystem.TwTheme
import com.twofasapp.designsystem.service.ServiceStyle
import com.twofasapp.locale.TwLocale
@Composable
@ -25,7 +27,7 @@ internal fun ServiceName(
color = TwTheme.color.onSurfacePrimary,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
modifier = modifier,
modifier = modifier.padding(bottom = 2.dp),
)
}
@ -33,6 +35,8 @@ internal fun ServiceName(
@Composable
internal fun ServiceInfo(
text: String?,
style: ServiceStyle = ServiceStyle.Default,
spacer: Boolean = true,
modifier: Modifier = Modifier,
textStyles: ServiceTextStyle = ServiceTextDefaults.default(),
) {
@ -45,8 +49,17 @@ internal fun ServiceInfo(
overflow = TextOverflow.Ellipsis,
modifier = modifier,
)
} else {
Spacer(Modifier.width(4.dp))
}
if (spacer) {
Spacer(
Modifier.size(
when (style) {
ServiceStyle.Default -> 12.dp
ServiceStyle.Compact -> 2.dp
}
)
)
}
}
@ -55,6 +68,6 @@ internal fun ServiceInfo(
private fun Preview() {
Column {
ServiceName(text = TwLocale.strings.placeholder, modifier = Modifier.fillMaxWidth())
ServiceInfo(text = TwLocale.strings.placeholderMedium, modifier = Modifier.fillMaxWidth())
ServiceInfo(text = TwLocale.strings.placeholderMedium, modifier = Modifier.fillMaxWidth(), style = ServiceStyle.Default)
}
}

View File

@ -1,9 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="248dp"
android:height="204dp"
android:viewportWidth="248"
android:viewportHeight="204">
android:width="128dp"
android:height="128dp"
android:viewportWidth="128"
android:viewportHeight="128">
<path
android:pathData="M221.9,51.3c0.1,2.2 0.1,4.3 0.1,6.5c0,66.7 -50.8,143.7 -143.7,143.7v0c-27.4,0 -54.3,-7.8 -77.4,-22.6c4,0.5 8,0.7 12,0.7c22.7,0 44.8,-7.6 62.7,-21.7c-21.6,-0.4 -40.6,-14.5 -47.2,-35.1c7.6,1.5 15.4,1.2 22.8,-0.9c-23.6,-4.8 -40.5,-25.5 -40.5,-49.5c0,-0.2 0,-0.4 0,-0.6c7,3.9 14.9,6.1 22.9,6.3c-22.2,-14.8 -29,-44.3 -15.6,-67.4c25.6,31.5 63.5,50.7 104.1,52.8c-4.1,-17.5 1.5,-35.9 14.6,-48.2c20.3,-19.1 52.3,-18.1 71.4,2.2c11.3,-2.2 22.1,-6.4 32.1,-12.3c-3.8,11.7 -11.7,21.6 -22.2,27.9c10,-1.2 19.8,-3.9 29,-8C240.4,35.3 231.8,44.1 221.9,51.3z"
android:fillColor="#FFFFFF"/>
android:pathData="M97.3,12H114.94L76.4,56.05L121.74,116H86.24L58.43,79.64L26.61,116H8.96L50.19,68.88L6.69,12H43.09L68.23,45.23L97.3,12ZM91.11,105.44H100.89L37.78,22.01H27.29L91.11,105.44Z"
android:fillColor="#ffffff"/>
</vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:fillColor="#FF000000"
android:pathData="M248,688q53.57,0 104.28,12.5T452,738v-427q-45,-30 -97.62,-46.5Q301.76,248 248,248q-38,0 -74.5,9.5T100,281v434q31,-14 70.5,-20.5T248,688ZM512,738q50,-25 98,-37.5T712,688q38,0 78.5,6t69.5,16v-429q-34,-18 -71.82,-25.5Q750.35,248 712,248q-54,0 -104.5,16.5T512,311v427ZM484.5,842q-7.64,0 -16.57,-1.5Q459,839 452,834q-46,-29 -97.86,-46Q302.27,771 248,771q-34.15,0 -67.07,9.5Q148,790 115,801q-33.1,17 -65.55,-2.16Q17,779.68 17,741v-462q0,-25 11,-46.3 11,-21.3 33,-32.7 44,-19.5 90.39,-27.75 46.39,-8.25 94.55,-8.25Q310,164 370,181.5T482,236q51,-36 110,-54t122.06,-18q47.81,0 93.88,9T898,200q22,11.4 33.5,32.7Q943,254 943,279v473q0,36.94 -33,52.97Q877,821 844,801q-32,-12 -64.9,-21 -32.9,-9 -67.03,-9 -53.35,0 -102.21,17.5Q561,806 516,834q-6,5 -14.93,6.5 -8.93,1.5 -16.57,1.5ZM276,499Z"/>
</vector>

View File

@ -1,4 +1,9 @@
<vector android:height="123.3871dp" android:viewportHeight="204"
android:viewportWidth="248" android:width="150dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#1D9BF0" android:pathData="M221.95,51.29c0.15,2.17 0.15,4.34 0.15,6.53c0,66.73 -50.8,143.69 -143.69,143.69v-0.04C50.97,201.51 24.1,193.65 1,178.83c3.99,0.48 8,0.72 12.02,0.73c22.74,0.02 44.83,-7.61 62.72,-21.66c-21.61,-0.41 -40.56,-14.5 -47.18,-35.07c7.57,1.46 15.37,1.16 22.8,-0.87C27.8,117.2 10.85,96.5 10.85,72.46c0,-0.22 0,-0.43 0,-0.64c7.02,3.91 14.88,6.08 22.92,6.32C11.58,63.31 4.74,33.79 18.14,10.71c25.64,31.55 63.47,50.73 104.08,52.76c-4.07,-17.54 1.49,-35.92 14.61,-48.25c20.34,-19.12 52.33,-18.14 71.45,2.19c11.31,-2.23 22.15,-6.38 32.07,-12.26c-3.77,11.69 -11.66,21.62 -22.2,27.93c10.01,-1.18 19.79,-3.86 29,-7.95C240.37,35.29 231.83,44.14 221.95,51.29z"/>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="128dp"
android:height="128dp"
android:viewportWidth="128"
android:viewportHeight="128">
<path
android:pathData="M97.3,12H114.94L76.4,56.05L121.74,116H86.24L58.43,79.64L26.61,116H8.96L50.19,68.88L6.69,12H43.09L68.23,45.23L97.3,12ZM91.11,105.44H100.89L37.78,22.01H27.29L91.11,105.44Z"
android:fillColor="#000000"/>
</vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Some files were not shown because too many files have changed in this diff Show More