Skip to content

Commit

Permalink
Merge pull request #31 from InkApplications/weather
Browse files Browse the repository at this point in the history
Add weather widget
  • Loading branch information
ReneeVandervelde authored Sep 1, 2024
2 parents 86c71bf + b533478 commit 3969628
Show file tree
Hide file tree
Showing 13 changed files with 241 additions and 36 deletions.
16 changes: 12 additions & 4 deletions render-compose/api/android/render-compose.api
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ public final class ink/ui/render/compose/renderer/SymbolsKt {
public static final fun getResource-TN8vZ0Q (Ljava/lang/String;)Lorg/jetbrains/compose/resources/DrawableResource;
}

public final class ink/ui/render/compose/renderer/WeatherRendererKt {
public static final fun getWeatherRenderer ()Link/ui/render/compose/renderer/ElementRenderer;
}

public final class ink/ui/render/compose/theme/ColorVariant {
public static final field $stable I
public synthetic fun <init> (JJJJJJJJJILkotlin/jvm/internal/DefaultConstructorMarker;)V
Expand Down Expand Up @@ -85,15 +89,19 @@ public final class ink/ui/render/compose/theme/ComposeRenderThemeKt {

public final class ink/ui/render/compose/theme/SizingVariant {
public static final field $stable I
public synthetic fun <init> (FFILkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun <init> (FFLkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun <init> (FFFFILkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun <init> (FFFFLkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1-D9Ej5fM ()F
public final fun component2-D9Ej5fM ()F
public final fun copy-YgX7TsA (FF)Link/ui/render/compose/theme/SizingVariant;
public static synthetic fun copy-YgX7TsA$default (Link/ui/render/compose/theme/SizingVariant;FFILjava/lang/Object;)Link/ui/render/compose/theme/SizingVariant;
public final fun component3-D9Ej5fM ()F
public final fun component4-D9Ej5fM ()F
public final fun copy-a9UjIt4 (FFFF)Link/ui/render/compose/theme/SizingVariant;
public static synthetic fun copy-a9UjIt4$default (Link/ui/render/compose/theme/SizingVariant;FFFFILjava/lang/Object;)Link/ui/render/compose/theme/SizingVariant;
public fun equals (Ljava/lang/Object;)Z
public final fun getBorders-D9Ej5fM ()F
public final fun getCorners-D9Ej5fM ()F
public final fun getHintIcons-D9Ej5fM ()F
public final fun getWidgetIcons-D9Ej5fM ()F
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
Expand Down
16 changes: 12 additions & 4 deletions render-compose/api/jvm/render-compose.api
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ public final class ink/ui/render/compose/renderer/SymbolsKt {
public static final fun getResource-TN8vZ0Q (Ljava/lang/String;)Lorg/jetbrains/compose/resources/DrawableResource;
}

public final class ink/ui/render/compose/renderer/WeatherRendererKt {
public static final fun getWeatherRenderer ()Link/ui/render/compose/renderer/ElementRenderer;
}

public final class ink/ui/render/compose/theme/ColorVariant {
public static final field $stable I
public synthetic fun <init> (JJJJJJJJJILkotlin/jvm/internal/DefaultConstructorMarker;)V
Expand Down Expand Up @@ -85,15 +89,19 @@ public final class ink/ui/render/compose/theme/ComposeRenderThemeKt {

public final class ink/ui/render/compose/theme/SizingVariant {
public static final field $stable I
public synthetic fun <init> (FFILkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun <init> (FFLkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun <init> (FFFFILkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun <init> (FFFFLkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1-D9Ej5fM ()F
public final fun component2-D9Ej5fM ()F
public final fun copy-YgX7TsA (FF)Link/ui/render/compose/theme/SizingVariant;
public static synthetic fun copy-YgX7TsA$default (Link/ui/render/compose/theme/SizingVariant;FFILjava/lang/Object;)Link/ui/render/compose/theme/SizingVariant;
public final fun component3-D9Ej5fM ()F
public final fun component4-D9Ej5fM ()F
public final fun copy-a9UjIt4 (FFFF)Link/ui/render/compose/theme/SizingVariant;
public static synthetic fun copy-a9UjIt4$default (Link/ui/render/compose/theme/SizingVariant;FFFFILjava/lang/Object;)Link/ui/render/compose/theme/SizingVariant;
public fun equals (Ljava/lang/Object;)Z
public final fun getBorders-D9Ej5fM ()F
public final fun getCorners-D9Ej5fM ()F
public final fun getHintIcons-D9Ej5fM ()F
public final fun getWidgetIcons-D9Ej5fM ()F
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class ComposeRenderer(
MenuRowRenderer,
SpinnerRenderer,
IconRenderer,
WeatherRenderer,
)
private val uiRenderer = CompositeElementRenderer(renderers + builtInRenderers)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@ import androidx.compose.animation.Animatable
import androidx.compose.animation.core.tween
import androidx.compose.foundation.*
import androidx.compose.foundation.interaction.*
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.BasicText
import androidx.compose.runtime.*
Expand Down Expand Up @@ -87,7 +84,9 @@ fun Button(
painterResource(leadingSymbol.resource),
colorFilter = ColorFilter.tint(theme.colors.forSentiment(sentiment)),
contentDescription = null,
modifier = Modifier.padding(end = theme.spacing.item.takeIf { text.isNotEmpty() } ?: 0.dp),
modifier = Modifier
.padding(end = theme.spacing.item.takeIf { text.isNotEmpty() } ?: 0.dp)
.size(theme.sizing.hintIcons),
)
}
if (latched) {
Expand Down Expand Up @@ -115,7 +114,9 @@ fun Button(
painterResource(trailingSymbol.resource),
colorFilter = ColorFilter.tint(theme.colors.forSentiment(sentiment)),
contentDescription = null,
modifier = Modifier.padding(start = theme.spacing.item.takeIf { text.isNotEmpty() } ?: 0.dp),
modifier = Modifier
.padding(start = theme.spacing.item.takeIf { text.isNotEmpty() } ?: 0.dp)
.size(theme.sizing.hintIcons),
)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package ink.ui.render.compose.renderer

import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.size
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ColorFilter
import ink.ui.structures.elements.IconElement
import org.jetbrains.compose.resources.painterResource
Expand All @@ -10,5 +12,6 @@ internal val IconRenderer = renderer<IconElement> { theme, element ->
painterResource(element.symbol.resource),
colorFilter = ColorFilter.tint(theme.colors.forSentiment(element.sentiment)),
contentDescription = null,
modifier = Modifier.size(theme.sizing.hintIcons),
)
}
Original file line number Diff line number Diff line change
@@ -1,42 +1,65 @@
package ink.ui.render.compose.renderer

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import ink.ui.render.compose.theme.ComposeRenderTheme
import ink.ui.structures.Positioning
import ink.ui.structures.GroupingStyle
import ink.ui.structures.elements.ElementList
import ink.ui.structures.elements.Orientation
import ink.ui.structures.elements.UiElement
import ink.ui.structures.render.RenderResult

internal object ListRenderer: ElementRenderer {
@Composable
override fun render(element: UiElement, theme: ComposeRenderTheme, parent: ElementRenderer): RenderResult {
when (element) {
is ElementList -> Column(
if (element !is ElementList) return RenderResult.Skipped

when (element.orientation) {
Orientation.Vertical -> Column(
horizontalAlignment = when (element.positioning) {
Positioning.Start -> Alignment.Start
Positioning.Center -> Alignment.CenterHorizontally
},
) {
element.items.forEachIndexed { index, item ->
parent.render(item, theme, parent)
if (element.groupingStyle != GroupingStyle.Unified && index != 0 && index != element.items.size - 1) {
val spacing = when (element.groupingStyle) {
GroupingStyle.Items -> theme.spacing.item
GroupingStyle.Sections -> theme.spacing.sectionSpacing
GroupingStyle.Unified -> throw IllegalStateException()
}
Spacer(modifier = Modifier.height(spacing))
}
renderElements(element, theme, parent)
}
Orientation.Horizontal -> Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = when (element.positioning) {
Positioning.Start -> Arrangement.Start
Positioning.Center -> Arrangement.Center
},
modifier = Modifier.let {
if (element.positioning == Positioning.Center) {
it.fillMaxWidth()
} else it
}
) {
renderElements(element, theme, parent)
}
else -> return RenderResult.Skipped
}
return RenderResult.Rendered
}

@Composable
private fun renderElements(
element: ElementList,
theme: ComposeRenderTheme,
parent: ElementRenderer
) {
element.items.forEachIndexed { index, item ->
parent.render(item, theme, parent)
if (element.groupingStyle != GroupingStyle.Unified && index != 0 && index != element.items.size - 1) {
val spacing = when (element.groupingStyle) {
GroupingStyle.Items -> theme.spacing.item
GroupingStyle.Sections -> theme.spacing.sectionSpacing
GroupingStyle.Unified -> throw IllegalStateException()
}
Spacer(modifier = Modifier.height(spacing))
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package ink.ui.render.compose.renderer

import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.text.BasicText
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ColorFilter
import ink.ui.structures.Sentiment
import ink.ui.structures.Symbol
import ink.ui.structures.elements.WeatherElement
import org.jetbrains.compose.resources.painterResource

val WeatherRenderer = renderer<WeatherElement> { theme, element ->
Box(
contentAlignment = Alignment.Center,
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
) {
val title = element.title
if (title != null) {
BasicText(
text = title,
style = theme.typography.caption.copy(color = theme.colors.foreground),
)
}

when (element.condition) {
WeatherElement.Condition.Clear -> Image(
painterResource(Symbol.Sunshine.resource),
colorFilter = ColorFilter.tint(theme.colors.forSentiment(Sentiment.Nominal)),
contentDescription = element.condition.description,
modifier = Modifier.size(theme.sizing.widgetIcons).padding(theme.spacing.item)
)

WeatherElement.Condition.Cloudy -> Image(
painterResource(Symbol.Cloud.resource),
colorFilter = ColorFilter.tint(theme.colors.forSentiment(Sentiment.Nominal)),
contentDescription = element.condition.description,
modifier = Modifier.size(theme.sizing.widgetIcons).padding(theme.spacing.item)
)

WeatherElement.Condition.Rainy -> Image(
painterResource(Symbol.Rain.resource),
colorFilter = ColorFilter.tint(theme.colors.forSentiment(Sentiment.Nominal)),
contentDescription = element.condition.description,
modifier = Modifier.size(theme.sizing.widgetIcons).padding(theme.spacing.item)
)
}

BasicText(element.temperature, style = theme.typography.body.copy(color = theme.colors.foreground))

val secondaryTemperature = element.secondaryTemperature
if (secondaryTemperature != null) {
BasicText(secondaryTemperature, style = theme.typography.caption.copy(color = theme.colors.foreground))
}
}
}
}

private val WeatherElement.Condition.description get() = when (this) {
WeatherElement.Condition.Clear -> "Clear"
WeatherElement.Condition.Cloudy -> "Cloudy"
WeatherElement.Condition.Rainy -> "Rainy"
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,21 @@ data class SizingVariant(
* Standard corner radius used for UI elements.
*/
val corners: Dp = 4.dp,

/**
* Sizing for icons used in a hint-context such as a button or
* informational status.
*
* These are less prominent than [widgetIcons], and are explained in
* context other than the icon itself.
*/
val hintIcons: Dp = 24.dp,

/**
* Sizing for informational widget icons such as weather iconography.
*
* These icons convey important information that is not provided through
* other context, and thus are more prominent than [hintIcons].
*/
val widgetIcons: Dp = 56.dp,
)
17 changes: 17 additions & 0 deletions sample-android/src/main/kotlin/example/SampleScreen.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package example

import ink.ui.structures.Positioning
import ink.ui.structures.Sentiment
import ink.ui.structures.Symbol
import ink.ui.structures.TextStyle
Expand Down Expand Up @@ -81,6 +82,22 @@ val SampleScreen = ScrollingListLayout(
),
onClick = {},
),
ElementList(
items = listOf(
WeatherElement(
temperature = "72",
condition = WeatherElement.Condition.Clear,
),
WeatherElement(
title = "Sun",
temperature = "72",
secondaryTemperature = "60",
condition = WeatherElement.Condition.Rainy,
),
),
positioning = Positioning.Center,
orientation = Orientation.Horizontal,
),
SpinnerElement(
value = "5",
onNextValue = {},
Expand Down
Loading

0 comments on commit 3969628

Please sign in to comment.