Change-Id: I05f9400a9410e31bdf1534e458d560fe793b809fpull/148/head^2
parent
0a3b3af2ed
commit
d05b573f52
@ -0,0 +1 @@
|
||||
/build
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
plugins {
|
||||
id("nowinandroid.android.library")
|
||||
id("nowinandroid.android.library.compose")
|
||||
id("nowinandroid.android.library.jacoco")
|
||||
id("nowinandroid.spotless")
|
||||
}
|
||||
|
||||
android {
|
||||
defaultConfig {
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
lint {
|
||||
checkDependencies = true
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(libs.androidx.core.ktx)
|
||||
api(libs.androidx.compose.foundation)
|
||||
api(libs.androidx.compose.foundation.layout)
|
||||
api(libs.androidx.compose.material.iconsExtended)
|
||||
api(libs.androidx.compose.material3)
|
||||
debugApi(libs.androidx.compose.ui.tooling)
|
||||
api(libs.androidx.compose.ui.tooling.preview)
|
||||
api(libs.androidx.compose.ui.util)
|
||||
api(libs.androidx.compose.runtime)
|
||||
lintPublish(project(":lint"))
|
||||
androidTestImplementation(project(":core-testing"))
|
||||
}
|
@ -0,0 +1,276 @@
|
||||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.core.designsystem
|
||||
|
||||
import android.os.Build
|
||||
import androidx.compose.material3.ColorScheme
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.dynamicDarkColorScheme
|
||||
import androidx.compose.material3.dynamicLightColorScheme
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.test.junit4.createComposeRule
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.google.samples.apps.nowinandroid.core.designsystem.theme.BackgroundTheme
|
||||
import com.google.samples.apps.nowinandroid.core.designsystem.theme.DarkAndroidBackgroundTheme
|
||||
import com.google.samples.apps.nowinandroid.core.designsystem.theme.DarkAndroidColorScheme
|
||||
import com.google.samples.apps.nowinandroid.core.designsystem.theme.DarkDefaultColorScheme
|
||||
import com.google.samples.apps.nowinandroid.core.designsystem.theme.GradientColors
|
||||
import com.google.samples.apps.nowinandroid.core.designsystem.theme.LightAndroidBackgroundTheme
|
||||
import com.google.samples.apps.nowinandroid.core.designsystem.theme.LightAndroidColorScheme
|
||||
import com.google.samples.apps.nowinandroid.core.designsystem.theme.LightDefaultColorScheme
|
||||
import com.google.samples.apps.nowinandroid.core.designsystem.theme.LightDefaultGradientColors
|
||||
import com.google.samples.apps.nowinandroid.core.designsystem.theme.LocalBackgroundTheme
|
||||
import com.google.samples.apps.nowinandroid.core.designsystem.theme.LocalGradientColors
|
||||
import com.google.samples.apps.nowinandroid.core.designsystem.theme.NiaTheme
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
|
||||
/**
|
||||
* Tests [NiaTheme] using different combinations of the theme mode parameters:
|
||||
* darkTheme, dynamicColor, and androidTheme.
|
||||
*
|
||||
* It verifies that the various composition locals — [MaterialTheme], [LocalGradientColors] and
|
||||
* [LocalBackgroundTheme] — have the expected values for a given theme mode, as specified by the
|
||||
* design system.
|
||||
*/
|
||||
class ThemeTest {
|
||||
|
||||
@get:Rule
|
||||
val composeTestRule = createComposeRule()
|
||||
|
||||
@Test
|
||||
fun darkThemeFalse_dynamicColorFalse_androidThemeFalse() {
|
||||
composeTestRule.setContent {
|
||||
NiaTheme(
|
||||
darkTheme = false,
|
||||
dynamicColor = false,
|
||||
androidTheme = false
|
||||
) {
|
||||
val colorScheme = LightDefaultColorScheme
|
||||
assertColorSchemesEqual(colorScheme, MaterialTheme.colorScheme)
|
||||
val gradientColors = LightDefaultGradientColors
|
||||
assertEquals(gradientColors, LocalGradientColors.current)
|
||||
val backgroundTheme = BackgroundTheme(
|
||||
color = colorScheme.surface,
|
||||
tonalElevation = 2.dp
|
||||
)
|
||||
assertEquals(backgroundTheme, LocalBackgroundTheme.current)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun darkThemeTrue_dynamicColorFalse_androidThemeFalse() {
|
||||
composeTestRule.setContent {
|
||||
NiaTheme(
|
||||
darkTheme = true,
|
||||
dynamicColor = false,
|
||||
androidTheme = false
|
||||
) {
|
||||
val colorScheme = DarkDefaultColorScheme
|
||||
assertColorSchemesEqual(colorScheme, MaterialTheme.colorScheme)
|
||||
val gradientColors = GradientColors()
|
||||
assertEquals(gradientColors, LocalGradientColors.current)
|
||||
val backgroundTheme = BackgroundTheme(
|
||||
color = colorScheme.surface,
|
||||
tonalElevation = 2.dp
|
||||
)
|
||||
assertEquals(backgroundTheme, LocalBackgroundTheme.current)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun darkThemeFalse_dynamicColorTrue_androidThemeFalse() {
|
||||
composeTestRule.setContent {
|
||||
NiaTheme(
|
||||
darkTheme = false,
|
||||
dynamicColor = true,
|
||||
androidTheme = false
|
||||
) {
|
||||
val colorScheme = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
dynamicLightColorScheme(LocalContext.current)
|
||||
} else {
|
||||
LightDefaultColorScheme
|
||||
}
|
||||
assertColorSchemesEqual(colorScheme, MaterialTheme.colorScheme)
|
||||
val gradientColors = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
GradientColors()
|
||||
} else {
|
||||
LightDefaultGradientColors
|
||||
}
|
||||
assertEquals(gradientColors, LocalGradientColors.current)
|
||||
val backgroundTheme = BackgroundTheme(
|
||||
color = colorScheme.surface,
|
||||
tonalElevation = 2.dp
|
||||
)
|
||||
assertEquals(backgroundTheme, LocalBackgroundTheme.current)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun darkThemeTrue_dynamicColorTrue_androidThemeFalse() {
|
||||
composeTestRule.setContent {
|
||||
NiaTheme(
|
||||
darkTheme = true,
|
||||
dynamicColor = true,
|
||||
androidTheme = false
|
||||
) {
|
||||
val colorScheme = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
dynamicDarkColorScheme(LocalContext.current)
|
||||
} else {
|
||||
DarkDefaultColorScheme
|
||||
}
|
||||
assertColorSchemesEqual(colorScheme, MaterialTheme.colorScheme)
|
||||
val gradientColors = GradientColors()
|
||||
assertEquals(gradientColors, LocalGradientColors.current)
|
||||
val backgroundTheme = BackgroundTheme(
|
||||
color = colorScheme.surface,
|
||||
tonalElevation = 2.dp
|
||||
)
|
||||
assertEquals(backgroundTheme, LocalBackgroundTheme.current)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun darkThemeFalse_dynamicColorFalse_androidThemeTrue() {
|
||||
composeTestRule.setContent {
|
||||
NiaTheme(
|
||||
darkTheme = false,
|
||||
dynamicColor = false,
|
||||
androidTheme = true
|
||||
) {
|
||||
val colorScheme = LightAndroidColorScheme
|
||||
assertColorSchemesEqual(colorScheme, MaterialTheme.colorScheme)
|
||||
val gradientColors = GradientColors()
|
||||
assertEquals(gradientColors, LocalGradientColors.current)
|
||||
val backgroundTheme = LightAndroidBackgroundTheme
|
||||
assertEquals(backgroundTheme, LocalBackgroundTheme.current)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun darkThemeTrue_dynamicColorFalse_androidThemeTrue() {
|
||||
composeTestRule.setContent {
|
||||
NiaTheme(
|
||||
darkTheme = true,
|
||||
dynamicColor = false,
|
||||
androidTheme = true
|
||||
) {
|
||||
val colorScheme = DarkAndroidColorScheme
|
||||
assertColorSchemesEqual(colorScheme, MaterialTheme.colorScheme)
|
||||
val gradientColors = GradientColors()
|
||||
assertEquals(gradientColors, LocalGradientColors.current)
|
||||
val backgroundTheme = DarkAndroidBackgroundTheme
|
||||
assertEquals(backgroundTheme, LocalBackgroundTheme.current)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun darkThemeFalse_dynamicColorTrue_androidThemeTrue() {
|
||||
composeTestRule.setContent {
|
||||
NiaTheme(
|
||||
darkTheme = false,
|
||||
dynamicColor = true,
|
||||
androidTheme = true
|
||||
) {
|
||||
val colorScheme = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
dynamicLightColorScheme(LocalContext.current)
|
||||
} else {
|
||||
LightDefaultColorScheme
|
||||
}
|
||||
assertColorSchemesEqual(colorScheme, MaterialTheme.colorScheme)
|
||||
val gradientColors = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
GradientColors()
|
||||
} else {
|
||||
LightDefaultGradientColors
|
||||
}
|
||||
assertEquals(gradientColors, LocalGradientColors.current)
|
||||
val backgroundTheme = BackgroundTheme(
|
||||
color = colorScheme.surface,
|
||||
tonalElevation = 2.dp
|
||||
)
|
||||
assertEquals(backgroundTheme, LocalBackgroundTheme.current)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun darkThemeTrue_dynamicColorTrue_androidThemeTrue() {
|
||||
composeTestRule.setContent {
|
||||
NiaTheme(
|
||||
darkTheme = true,
|
||||
dynamicColor = true,
|
||||
androidTheme = true
|
||||
) {
|
||||
val colorScheme = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
dynamicDarkColorScheme(LocalContext.current)
|
||||
} else {
|
||||
DarkDefaultColorScheme
|
||||
}
|
||||
assertColorSchemesEqual(colorScheme, MaterialTheme.colorScheme)
|
||||
val gradientColors = GradientColors()
|
||||
assertEquals(gradientColors, LocalGradientColors.current)
|
||||
val backgroundTheme = BackgroundTheme(
|
||||
color = colorScheme.surface,
|
||||
tonalElevation = 2.dp
|
||||
)
|
||||
assertEquals(backgroundTheme, LocalBackgroundTheme.current)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Workaround for the fact that the NiA design system specify all color scheme values.
|
||||
*/
|
||||
private fun assertColorSchemesEqual(
|
||||
expectedColorScheme: ColorScheme,
|
||||
actualColorScheme: ColorScheme
|
||||
) {
|
||||
assertEquals(expectedColorScheme.primary, actualColorScheme.primary)
|
||||
assertEquals(expectedColorScheme.onPrimary, actualColorScheme.onPrimary)
|
||||
assertEquals(expectedColorScheme.primaryContainer, actualColorScheme.primaryContainer)
|
||||
assertEquals(expectedColorScheme.onPrimaryContainer, actualColorScheme.onPrimaryContainer)
|
||||
assertEquals(expectedColorScheme.secondary, actualColorScheme.secondary)
|
||||
assertEquals(expectedColorScheme.onSecondary, actualColorScheme.onSecondary)
|
||||
assertEquals(expectedColorScheme.secondaryContainer, actualColorScheme.secondaryContainer)
|
||||
assertEquals(
|
||||
expectedColorScheme.onSecondaryContainer,
|
||||
actualColorScheme.onSecondaryContainer
|
||||
)
|
||||
assertEquals(expectedColorScheme.tertiary, actualColorScheme.tertiary)
|
||||
assertEquals(expectedColorScheme.onTertiary, actualColorScheme.onTertiary)
|
||||
assertEquals(expectedColorScheme.tertiaryContainer, actualColorScheme.tertiaryContainer)
|
||||
assertEquals(expectedColorScheme.onTertiaryContainer, actualColorScheme.onTertiaryContainer)
|
||||
assertEquals(expectedColorScheme.error, actualColorScheme.error)
|
||||
assertEquals(expectedColorScheme.onError, actualColorScheme.onError)
|
||||
assertEquals(expectedColorScheme.errorContainer, actualColorScheme.errorContainer)
|
||||
assertEquals(expectedColorScheme.onErrorContainer, actualColorScheme.onErrorContainer)
|
||||
assertEquals(expectedColorScheme.background, actualColorScheme.background)
|
||||
assertEquals(expectedColorScheme.onBackground, actualColorScheme.onBackground)
|
||||
assertEquals(expectedColorScheme.surface, actualColorScheme.surface)
|
||||
assertEquals(expectedColorScheme.onSurface, actualColorScheme.onSurface)
|
||||
assertEquals(expectedColorScheme.surfaceVariant, actualColorScheme.surfaceVariant)
|
||||
assertEquals(expectedColorScheme.onSurfaceVariant, actualColorScheme.onSurfaceVariant)
|
||||
assertEquals(expectedColorScheme.outline, actualColorScheme.outline)
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2022 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.google.samples.apps.nowinandroid.core.designsystem">
|
||||
|
||||
</manifest>
|
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.core.designsystem.component
|
||||
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.FilterChip
|
||||
import androidx.compose.material3.FilterChipDefaults
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.ProvideTextStyle
|
||||
import androidx.compose.material3.Shapes
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.google.samples.apps.nowinandroid.core.designsystem.icon.NiaIcons
|
||||
|
||||
/**
|
||||
* Now in Android filter chip with included leading checked icon as well as text content slot.
|
||||
*
|
||||
* @param selected Whether the chip is currently checked.
|
||||
* @param onSelectedChange Called when the user clicks the chip and toggles checked.
|
||||
* @param modifier Modifier to be applied to the chip.
|
||||
* @param enabled Controls the enabled state of the chip. When `false`, this chip will not be
|
||||
* clickable and will appear disabled to accessibility services.
|
||||
* @param label The text label content.
|
||||
*/
|
||||
@Composable
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
fun NiaFilterChip(
|
||||
selected: Boolean,
|
||||
onSelectedChange: (Boolean) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
label: @Composable () -> Unit
|
||||
) {
|
||||
FilterChip(
|
||||
selected = selected,
|
||||
onClick = { onSelectedChange(!selected) },
|
||||
label = {
|
||||
ProvideTextStyle(value = MaterialTheme.typography.labelSmall) {
|
||||
label()
|
||||
}
|
||||
},
|
||||
modifier = modifier,
|
||||
enabled = enabled,
|
||||
selectedIcon = {
|
||||
Icon(
|
||||
imageVector = NiaIcons.Check,
|
||||
contentDescription = null
|
||||
)
|
||||
},
|
||||
shape = Shapes.Full,
|
||||
border = FilterChipDefaults.filterChipBorder(
|
||||
borderColor = MaterialTheme.colorScheme.onBackground,
|
||||
selectedBorderColor = MaterialTheme.colorScheme.onBackground,
|
||||
disabledBorderColor = MaterialTheme.colorScheme.onBackground.copy(
|
||||
alpha = NiaChipDefaults.DisabledChipContentAlpha
|
||||
),
|
||||
disabledSelectedBorderColor = MaterialTheme.colorScheme.onBackground.copy(
|
||||
alpha = NiaChipDefaults.DisabledChipContentAlpha
|
||||
),
|
||||
borderWidth = NiaChipDefaults.ChipBorderWidth,
|
||||
selectedBorderWidth = NiaChipDefaults.ChipBorderWidth
|
||||
),
|
||||
colors = FilterChipDefaults.filterChipColors(
|
||||
containerColor = Color.Transparent,
|
||||
labelColor = MaterialTheme.colorScheme.onBackground,
|
||||
iconColor = MaterialTheme.colorScheme.onBackground,
|
||||
disabledContainerColor = if (selected) {
|
||||
MaterialTheme.colorScheme.onBackground.copy(
|
||||
alpha = NiaChipDefaults.DisabledChipContainerAlpha
|
||||
)
|
||||
} else {
|
||||
Color.Transparent
|
||||
},
|
||||
disabledLabelColor = MaterialTheme.colorScheme.onBackground.copy(
|
||||
alpha = NiaChipDefaults.DisabledChipContentAlpha
|
||||
),
|
||||
disabledLeadingIconColor = MaterialTheme.colorScheme.onBackground.copy(
|
||||
alpha = NiaChipDefaults.DisabledChipContentAlpha
|
||||
),
|
||||
selectedContainerColor = MaterialTheme.colorScheme.primaryContainer,
|
||||
selectedLabelColor = MaterialTheme.colorScheme.onBackground,
|
||||
selectedLeadingIconColor = MaterialTheme.colorScheme.onBackground
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Now in Android chip default values.
|
||||
*/
|
||||
object NiaChipDefaults {
|
||||
const val DisabledChipContainerAlpha = 0.12f
|
||||
const val DisabledChipContentAlpha = 0.38f
|
||||
val ChipBorderWidth = 1.dp
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.core.designsystem.theme
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
||||
/**
|
||||
* Now in Android colors.
|
||||
*/
|
||||
internal val Blue10 = Color(0xFF001F29)
|
||||
internal val Blue20 = Color(0xFF003544)
|
||||
internal val Blue30 = Color(0xFF004D61)
|
||||
internal val Blue40 = Color(0xFF006781)
|
||||
internal val Blue80 = Color(0xFF5DD4FB)
|
||||
internal val Blue90 = Color(0xFFB5EAFF)
|
||||
internal val Blue95 = Color(0xFFDCF5FF)
|
||||
internal val DarkGreen10 = Color(0xFF0D1F12)
|
||||
internal val DarkGreen20 = Color(0xFF223526)
|
||||
internal val DarkGreen30 = Color(0xFF394B3C)
|
||||
internal val DarkGreen40 = Color(0xFF4F6352)
|
||||
internal val DarkGreen80 = Color(0xFFB7CCB8)
|
||||
internal val DarkGreen90 = Color(0xFFD3E8D3)
|
||||
internal val DarkGreenGray10 = Color(0xFF1A1C1A)
|
||||
internal val DarkGreenGray90 = Color(0xFFE2E3DE)
|
||||
internal val DarkGreenGray95 = Color(0xFFF0F1EC)
|
||||
internal val DarkGreenGray99 = Color(0xFFFBFDF7)
|
||||
internal val DarkPurpleGray10 = Color(0xFF201A1B)
|
||||
internal val DarkPurpleGray90 = Color(0xFFECDFE0)
|
||||
internal val DarkPurpleGray95 = Color(0xFFFAEEEF)
|
||||
internal val DarkPurpleGray99 = Color(0xFFFCFCFC)
|
||||
internal val Green10 = Color(0xFF00210B)
|
||||
internal val Green20 = Color(0xFF003919)
|
||||
internal val Green30 = Color(0xFF005227)
|
||||
internal val Green40 = Color(0xFF006D36)
|
||||
internal val Green80 = Color(0xFF0EE37C)
|
||||
internal val Green90 = Color(0xFF5AFF9D)
|
||||
internal val GreenGray30 = Color(0xFF414941)
|
||||
internal val GreenGray50 = Color(0xFF727971)
|
||||
internal val GreenGray60 = Color(0xFF8B938A)
|
||||
internal val GreenGray80 = Color(0xFFC1C9BF)
|
||||
internal val GreenGray90 = Color(0xFFDDE5DB)
|
||||
internal val Orange10 = Color(0xFF390C00)
|
||||
internal val Orange20 = Color(0xFF5D1900)
|
||||
internal val Orange30 = Color(0xFF812800)
|
||||
internal val Orange40 = Color(0xFFA23F16)
|
||||
internal val Orange80 = Color(0xFFFFB599)
|
||||
internal val Orange90 = Color(0xFFFFDBCE)
|
||||
internal val Orange95 = Color(0xFFFFEDE6)
|
||||
internal val Purple10 = Color(0xFF36003D)
|
||||
internal val Purple20 = Color(0xFF560A5E)
|
||||
internal val Purple30 = Color(0xFF702776)
|
||||
internal val Purple40 = Color(0xFF8C4190)
|
||||
internal val Purple80 = Color(0xFFFFA8FF)
|
||||
internal val Purple90 = Color(0xFFFFD5FC)
|
||||
internal val Purple95 = Color(0xFFFFEBFB)
|
||||
internal val PurpleGray30 = Color(0xFF4E444C)
|
||||
internal val PurpleGray50 = Color(0xFF7F747C)
|
||||
internal val PurpleGray60 = Color(0xFF998D96)
|
||||
internal val PurpleGray80 = Color(0xFFD0C2CC)
|
||||
internal val PurpleGray90 = Color(0xFFEDDEE8)
|
||||
internal val Red10 = Color(0xFF410001)
|
||||
internal val Red20 = Color(0xFF680003)
|
||||
internal val Red30 = Color(0xFF930006)
|
||||
internal val Red40 = Color(0xFFBA1B1B)
|
||||
internal val Red80 = Color(0xFFFFB4A9)
|
||||
internal val Red90 = Color(0xFFFFDAD4)
|
||||
internal val Teal10 = Color(0xFF001F26)
|
||||
internal val Teal20 = Color(0xFF02363F)
|
||||
internal val Teal30 = Color(0xFF214D56)
|
||||
internal val Teal40 = Color(0xFF3A656F)
|
||||
internal val Teal80 = Color(0xFFA2CED9)
|
||||
internal val Teal90 = Color(0xFFBEEAF6)
|
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.core.designsystem.theme
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.runtime.staticCompositionLocalOf
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
||||
/**
|
||||
* A class to model gradient color values for Now in Android.
|
||||
*/
|
||||
@Immutable
|
||||
data class GradientColors(
|
||||
val primary: Color = Color.Unspecified,
|
||||
val secondary: Color = Color.Unspecified,
|
||||
val tertiary: Color = Color.Unspecified,
|
||||
val neutral: Color = Color.Unspecified
|
||||
)
|
||||
|
||||
/**
|
||||
* A composition local for [GradientColors].
|
||||
*/
|
||||
val LocalGradientColors = staticCompositionLocalOf { GradientColors() }
|
@ -1,106 +0,0 @@
|
||||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.core.ui
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.selection.toggleable
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.icons.Icons.Filled
|
||||
import androidx.compose.material.icons.filled.Add
|
||||
import androidx.compose.material.icons.filled.Done
|
||||
import androidx.compose.material.ripple.rememberRipple
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.composed
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.semantics.Role
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Composable
|
||||
fun FollowButton(
|
||||
following: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
onFollowChange: ((Boolean) -> Unit)? = null,
|
||||
backgroundColor: Color = Color.Transparent,
|
||||
size: Dp = 32.dp,
|
||||
iconSize: Dp = size / 2,
|
||||
followingContentDescription: String? = null,
|
||||
notFollowingContentDescription: String? = null,
|
||||
) {
|
||||
val background = if (following) {
|
||||
MaterialTheme.colorScheme.secondaryContainer
|
||||
} else {
|
||||
backgroundColor
|
||||
}
|
||||
|
||||
Box(
|
||||
modifier = modifier.followButton(onFollowChange, following, enabled, background, size),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
if (following) {
|
||||
Icon(
|
||||
imageVector = Filled.Done,
|
||||
contentDescription = followingContentDescription,
|
||||
modifier = Modifier.size(iconSize)
|
||||
)
|
||||
} else {
|
||||
Icon(
|
||||
imageVector = Filled.Add,
|
||||
contentDescription = notFollowingContentDescription,
|
||||
modifier = Modifier.size(iconSize)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Modifier.followButton(
|
||||
onFollowChange: ((Boolean) -> Unit)?,
|
||||
following: Boolean,
|
||||
enabled: Boolean,
|
||||
background: Color,
|
||||
size: Dp
|
||||
): Modifier = composed {
|
||||
val boxModifier = if (onFollowChange != null) {
|
||||
val interactionSource = remember { MutableInteractionSource() }
|
||||
val ripple = rememberRipple(bounded = false, radius = 24.dp)
|
||||
this
|
||||
.toggleable(
|
||||
value = following,
|
||||
onValueChange = onFollowChange,
|
||||
enabled = enabled,
|
||||
role = Role.Checkbox,
|
||||
interactionSource = interactionSource,
|
||||
indication = ripple
|
||||
)
|
||||
} else {
|
||||
this
|
||||
}
|
||||
boxModifier
|
||||
.clip(CircleShape)
|
||||
.background(background)
|
||||
.size(size)
|
||||
}
|
@ -1,90 +0,0 @@
|
||||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.core.ui.component
|
||||
|
||||
import androidx.compose.foundation.selection.toggleable
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.semantics.Role
|
||||
import com.google.samples.apps.nowinandroid.core.ui.icon.NiaIcons
|
||||
|
||||
/**
|
||||
* Now in Android filter chip with included leading checked icon as well as text content slot.
|
||||
*
|
||||
* @param checked Whether the chip is currently checked.
|
||||
* @param onCheckedChange Called when the user clicks the chip and toggles checked.
|
||||
* @param modifier Modifier to be applied to the chip.
|
||||
* @param enabled Controls the enabled state of the chip. When `false`, this chip will not be
|
||||
* clickable and will appear disabled to accessibility services.
|
||||
* @param text The text label content.
|
||||
*/
|
||||
@Composable
|
||||
fun NiaFilterChip(
|
||||
checked: Boolean,
|
||||
onCheckedChange: (Boolean) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
text: @Composable () -> Unit
|
||||
) {
|
||||
// TODO: Replace with Chip when available in Compose Material 3: b/197399111
|
||||
NiaOutlinedButton(
|
||||
onClick = { onCheckedChange(!checked) },
|
||||
modifier = Modifier
|
||||
.toggleable(value = checked, enabled = enabled, role = Role.Button, onValueChange = {})
|
||||
.then(modifier),
|
||||
enabled = enabled,
|
||||
small = true,
|
||||
border = NiaButtonDefaults.outlinedButtonBorder(
|
||||
enabled = enabled,
|
||||
disabledColor = MaterialTheme.colorScheme.onBackground.copy(
|
||||
alpha = if (checked) {
|
||||
NiaButtonDefaults.DisabledButtonContentAlpha
|
||||
} else {
|
||||
NiaButtonDefaults.DisabledButtonContainerAlpha
|
||||
}
|
||||
)
|
||||
),
|
||||
colors = NiaButtonDefaults.outlinedButtonColors(
|
||||
containerColor = if (checked) {
|
||||
MaterialTheme.colorScheme.primaryContainer
|
||||
} else {
|
||||
Color.Transparent
|
||||
},
|
||||
disabledContainerColor = if (checked) {
|
||||
MaterialTheme.colorScheme.onBackground.copy(
|
||||
alpha = NiaButtonDefaults.DisabledButtonContainerAlpha
|
||||
)
|
||||
} else {
|
||||
Color.Transparent
|
||||
}
|
||||
),
|
||||
text = text,
|
||||
leadingIcon = if (checked) {
|
||||
{
|
||||
Icon(
|
||||
imageVector = NiaIcons.Check,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
)
|
||||
}
|
@ -1,108 +0,0 @@
|
||||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.core.ui.theme
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.core.graphics.ColorUtils
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
/**
|
||||
* Now in Android colors.
|
||||
*/
|
||||
val Blue10 = Color(0xFF001F29)
|
||||
val Blue20 = Color(0xFF003544)
|
||||
val Blue30 = Color(0xFF004D61)
|
||||
val Blue40 = Color(0xFF006781)
|
||||
val Blue80 = Color(0xFF5DD4FB)
|
||||
val Blue90 = Color(0xFFB5EAFF)
|
||||
val Blue95 = Color(0xFFDCF5FF)
|
||||
val DarkGreen10 = Color(0xFF0D1F12)
|
||||
val DarkGreen20 = Color(0xFF223526)
|
||||
val DarkGreen30 = Color(0xFF394B3C)
|
||||
val DarkGreen40 = Color(0xFF4F6352)
|
||||
val DarkGreen80 = Color(0xFFB7CCB8)
|
||||
val DarkGreen90 = Color(0xFFD3E8D3)
|
||||
val DarkGreenGray10 = Color(0xFF1A1C1A)
|
||||
val DarkGreenGray90 = Color(0xFFE2E3DE)
|
||||
val DarkGreenGray95 = Color(0xFFF0F1EC)
|
||||
val DarkGreenGray99 = Color(0xFFFBFDF7)
|
||||
val DarkPurpleGray10 = Color(0xFF201A1B)
|
||||
val DarkPurpleGray90 = Color(0xFFECDFE0)
|
||||
val DarkPurpleGray95 = Color(0xFFFAEEEF)
|
||||
val DarkPurpleGray99 = Color(0xFFFCFCFC)
|
||||
val Green10 = Color(0xFF00210B)
|
||||
val Green20 = Color(0xFF003919)
|
||||
val Green30 = Color(0xFF005227)
|
||||
val Green40 = Color(0xFF006D36)
|
||||
val Green80 = Color(0xFF0EE37C)
|
||||
val Green90 = Color(0xFF5AFF9D)
|
||||
val GreenGray30 = Color(0xFF414941)
|
||||
val GreenGray50 = Color(0xFF727971)
|
||||
val GreenGray60 = Color(0xFF8B938A)
|
||||
val GreenGray80 = Color(0xFFC1C9BF)
|
||||
val GreenGray90 = Color(0xFFDDE5DB)
|
||||
val Orange10 = Color(0xFF390C00)
|
||||
val Orange20 = Color(0xFF5D1900)
|
||||
val Orange30 = Color(0xFF812800)
|
||||
val Orange40 = Color(0xFFA23F16)
|
||||
val Orange80 = Color(0xFFFFB599)
|
||||
val Orange90 = Color(0xFFFFDBCE)
|
||||
val Orange95 = Color(0xFFFFEDE6)
|
||||
val Purple10 = Color(0xFF36003D)
|
||||
val Purple20 = Color(0xFF560A5E)
|
||||
val Purple30 = Color(0xFF702776)
|
||||
val Purple40 = Color(0xFF8C4190)
|
||||
val Purple80 = Color(0xFFFFA8FF)
|
||||
val Purple90 = Color(0xFFFFD5FC)
|
||||
val Purple95 = Color(0xFFFFEBFB)
|
||||
val PurpleGray30 = Color(0xFF4E444C)
|
||||
val PurpleGray50 = Color(0xFF7F747C)
|
||||
val PurpleGray60 = Color(0xFF998D96)
|
||||
val PurpleGray80 = Color(0xFFD0C2CC)
|
||||
val PurpleGray90 = Color(0xFFEDDEE8)
|
||||
val Red10 = Color(0xFF410001)
|
||||
val Red20 = Color(0xFF680003)
|
||||
val Red30 = Color(0xFF930006)
|
||||
val Red40 = Color(0xFFBA1B1B)
|
||||
val Red80 = Color(0xFFFFB4A9)
|
||||
val Red90 = Color(0xFFFFDAD4)
|
||||
val Teal10 = Color(0xFF001F26)
|
||||
val Teal20 = Color(0xFF02363F)
|
||||
val Teal30 = Color(0xFF214D56)
|
||||
val Teal40 = Color(0xFF3A656F)
|
||||
val Teal80 = Color(0xFFA2CED9)
|
||||
val Teal90 = Color(0xFFBEEAF6)
|
||||
|
||||
/**
|
||||
* Lighten the current [Color] instance to the given [luminance].
|
||||
*
|
||||
* This is needed because we can't access the token values directly. For the dynamic color theme,
|
||||
* this makes it impossible to get the 95% luminance token of the different theme colors.
|
||||
* TODO: Link to bug
|
||||
*/
|
||||
internal fun Color.lighten(luminance: Float): Color {
|
||||
val hsl = FloatArray(3)
|
||||
ColorUtils.RGBToHSL(
|
||||
(red * 256).roundToInt(),
|
||||
(green * 256).roundToInt(),
|
||||
(blue * 256).roundToInt(),
|
||||
hsl
|
||||
)
|
||||
hsl[2] = luminance
|
||||
val color = Color(ColorUtils.HSLToColor(hsl))
|
||||
return color
|
||||
}
|
@ -0,0 +1 @@
|
||||
/build
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
plugins {
|
||||
id 'java-library'
|
||||
id 'kotlin'
|
||||
id 'com.android.lint'
|
||||
}
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly libs.kotlin.stdlib
|
||||
compileOnly libs.lint.api
|
||||
}
|
@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.lint.designsystem
|
||||
|
||||
import com.android.tools.lint.client.api.UElementHandler
|
||||
import com.android.tools.lint.detector.api.Category
|
||||
import com.android.tools.lint.detector.api.Detector
|
||||
import com.android.tools.lint.detector.api.Implementation
|
||||
import com.android.tools.lint.detector.api.Issue
|
||||
import com.android.tools.lint.detector.api.JavaContext
|
||||
import com.android.tools.lint.detector.api.Scope
|
||||
import com.android.tools.lint.detector.api.Severity
|
||||
import org.jetbrains.uast.UCallExpression
|
||||
import org.jetbrains.uast.UElement
|
||||
import org.jetbrains.uast.UQualifiedReferenceExpression
|
||||
|
||||
/**
|
||||
* A detector that checks for incorrect usages of Compose Material APIs over equivalents in
|
||||
* the Now in Android design system module.
|
||||
*/
|
||||
@Suppress("UnstableApiUsage")
|
||||
class DesignSystemDetector : Detector(), Detector.UastScanner {
|
||||
|
||||
override fun getApplicableUastTypes(): List<Class<out UElement>> {
|
||||
return listOf(
|
||||
UCallExpression::class.java,
|
||||
UQualifiedReferenceExpression::class.java
|
||||
)
|
||||
}
|
||||
|
||||
override fun createUastHandler(context: JavaContext): UElementHandler {
|
||||
return object : UElementHandler() {
|
||||
override fun visitCallExpression(node: UCallExpression) {
|
||||
val name = node.methodName ?: return
|
||||
val preferredName = METHOD_NAMES[name] ?: return
|
||||
reportIssue(context, node, name, preferredName)
|
||||
}
|
||||
|
||||
override fun visitQualifiedReferenceExpression(node: UQualifiedReferenceExpression) {
|
||||
val name = node.receiver.asRenderString()
|
||||
val preferredName = RECEIVER_NAMES[name] ?: return
|
||||
reportIssue(context, node, name, preferredName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmField
|
||||
val ISSUE: Issue = Issue.create(
|
||||
id = "DesignSystem",
|
||||
briefDescription = "Design system",
|
||||
explanation = "This check highlights calls in code that use Compose Material " +
|
||||
"composables instead of equivalents from the Now in Android design system " +
|
||||
"module.",
|
||||
category = Category.CUSTOM_LINT_CHECKS,
|
||||
priority = 7,
|
||||
severity = Severity.ERROR,
|
||||
implementation = Implementation(
|
||||
DesignSystemDetector::class.java,
|
||||
Scope.JAVA_FILE_SCOPE
|
||||
)
|
||||
)
|
||||
|
||||
// Unfortunately :lint is a Java module and thus can't depend on the :core-designsystem
|
||||
// Android module, so we can't use composable function references (eg. ::Button.name)
|
||||
// instead of hardcoded names.
|
||||
val METHOD_NAMES = mapOf(
|
||||
"MaterialTheme" to "NiaTheme",
|
||||
"Button" to "NiaFilledButton",
|
||||
"OutlinedButton" to "NiaOutlinedButton",
|
||||
"TextButton" to "NiaTextButton",
|
||||
"FilterChip" to "NiaFilterChip",
|
||||
"ElevatedFilterChip" to "NiaFilterChip",
|
||||
"DropdownMenu" to "NiaDropdownMenu",
|
||||
"NavigationBar" to "NiaNavigationBar",
|
||||
"NavigationBarItem" to "NiaNavigationBarItem",
|
||||
"NavigationRail" to "NiaNavigationRail",
|
||||
"NavigationRailItem" to "NiaNavigationRailItem",
|
||||
"TabRow" to "NiaTabRow",
|
||||
"Tab" to "NiaTab",
|
||||
"IconToggleButton" to "NiaToggleButton",
|
||||
"FilledIconToggleButton" to "NiaToggleButton",
|
||||
"FilledTonalIconToggleButton" to "NiaToggleButton",
|
||||
"OutlinedIconToggleButton" to "NiaToggleButton",
|
||||
"CenterAlignedTopAppBar" to "NiaTopAppBar",
|
||||
"SmallTopAppBar" to "NiaTopAppBar",
|
||||
"MediumTopAppBar" to "NiaTopAppBar",
|
||||
"LargeTopAppBar" to "NiaTopAppBar"
|
||||
)
|
||||
val RECEIVER_NAMES = mapOf(
|
||||
"Icons" to "NiaIcons"
|
||||
)
|
||||
|
||||
fun reportIssue(
|
||||
context: JavaContext,
|
||||
node: UElement,
|
||||
name: String,
|
||||
preferredName: String
|
||||
) {
|
||||
context.report(
|
||||
ISSUE, node, context.getLocation(node),
|
||||
"Using $name instead of $preferredName"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.lint.designsystem
|
||||
|
||||
import com.android.tools.lint.client.api.IssueRegistry
|
||||
import com.android.tools.lint.client.api.Vendor
|
||||
import com.android.tools.lint.detector.api.CURRENT_API
|
||||
|
||||
/**
|
||||
* An issue registry that checks for incorrect usages of Compose Material APIs over equivalents in
|
||||
* the Now in Android design system module.
|
||||
*/
|
||||
@Suppress("UnstableApiUsage")
|
||||
class DesignSystemIssueRegistry : IssueRegistry() {
|
||||
override val issues = listOf(DesignSystemDetector.ISSUE)
|
||||
|
||||
override val api: Int = CURRENT_API
|
||||
|
||||
override val minApi: Int = 12
|
||||
|
||||
override val vendor: Vendor = Vendor(
|
||||
vendorName = "Now in Android",
|
||||
feedbackUrl = "https://github.com/android/nowinandroid/issues",
|
||||
contact = "https://github.com/android/nowinandroid"
|
||||
)
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
#
|
||||
# Copyright 2022 The Android Open Source Project
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
com.google.samples.apps.nowinandroid.lint.designsystem.DesignSystemIssueRegistry
|
Loading…
Reference in new issue