From 345f5eff92d64791b1d5e60fc7ca043ec831ab0b Mon Sep 17 00:00:00 2001 From: MM20 <15646950+MM2-0@users.noreply.github.com> Date: Mon, 28 Feb 2022 22:48:36 +0100 Subject: [PATCH] Add battery part --- i18n/src/main/res/values/strings.xml | 6 + .../mm20/launcher2/ui/icons/BatteryIcons.kt | 538 ++++++++++++++++++ .../launcher/widgets/clock/ClockWidgetVM.kt | 8 +- .../clock/parts/BatteryPartProvider.kt | 193 +++++++ 4 files changed, 740 insertions(+), 5 deletions(-) create mode 100644 ui/src/main/java/de/mm20/launcher2/ui/icons/BatteryIcons.kt create mode 100644 ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/clock/parts/BatteryPartProvider.kt diff --git a/i18n/src/main/res/values/strings.xml b/i18n/src/main/res/values/strings.xml index b1ef31ce..41ab65d9 100644 --- a/i18n/src/main/res/values/strings.xml +++ b/i18n/src/main/res/values/strings.xml @@ -540,4 +540,10 @@ You haven\'t connected a Google account yet Connect account + + Charging + + Full in %1$s minute + Full in %1$s minutes + \ No newline at end of file diff --git a/ui/src/main/java/de/mm20/launcher2/ui/icons/BatteryIcons.kt b/ui/src/main/java/de/mm20/launcher2/ui/icons/BatteryIcons.kt new file mode 100644 index 00000000..45d2b5b0 --- /dev/null +++ b/ui/src/main/java/de/mm20/launcher2/ui/icons/BatteryIcons.kt @@ -0,0 +1,538 @@ +package de.mm20.launcher2.ui.icons + +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.materialIcon +import androidx.compose.material.icons.materialPath +import androidx.compose.ui.graphics.vector.group + +val Icons.Rounded.Battery0Bar + get() = materialIcon("Icons.Rounded.Battery0Bar") { + materialPath { + moveTo(17f, 5f) + verticalLineToRelative(16f) + curveToRelative(0f, 0.55f, -0.45f, 1f, -1f, 1f) + horizontalLineTo(8f) + curveToRelative(-0.55f, 0f, -1f, -0.45f, -1f, -1f) + verticalLineTo(5f) + curveToRelative(0f, -0.55f, 0.45f, -1f, 1f, -1f) + horizontalLineToRelative(2f) + verticalLineTo(3f) + curveToRelative(0f, -0.55f, 0.45f, -1f, 1f, -1f) + horizontalLineToRelative(2f) + curveToRelative(0.55f, 0f, 1f, 0.45f, 1f, 1f) + verticalLineToRelative(1f) + horizontalLineToRelative(2f) + curveTo(16.55f, 4f, 17f, 4.45f, 17f, 5f) + close() + moveTo(15f, 6f) + horizontalLineTo(9f) + verticalLineToRelative(14f) + horizontalLineToRelative(6f) + verticalLineTo(6f) + close() + } + } + +val Icons.Rounded.Battery1Bar + get() = materialIcon("Icons.Rounded.Battery1Bar") { + materialPath { + moveTo(17f, 5f) + verticalLineToRelative(16f) + curveToRelative(0f, 0.55f, -0.45f, 1f, -1f, 1f) + horizontalLineTo(8f) + curveToRelative(-0.55f, 0f, -1f, -0.45f, -1f, -1f) + verticalLineTo(5f) + curveToRelative(0f, -0.55f, 0.45f, -1f, 1f, -1f) + horizontalLineToRelative(2f) + verticalLineTo(3f) + curveToRelative(0f, -0.55f, 0.45f, -1f, 1f, -1f) + horizontalLineToRelative(2f) + curveToRelative(0.55f, 0f, 1f, 0.45f, 1f, 1f) + verticalLineToRelative(1f) + horizontalLineToRelative(2f) + curveTo(16.55f, 4f, 17f, 4.45f, 17f, 5f) + close() + moveTo(15f, 6f) + horizontalLineTo(9f) + verticalLineToRelative(12f) + horizontalLineToRelative(6f) + verticalLineTo(6f) + close() + } + } + +val Icons.Rounded.Battery2Bar + get() = materialIcon("Icons.Rounded.Battery2Bar") { + materialPath { + moveTo(17f, 5f) + verticalLineToRelative(16f) + curveToRelative(0f, 0.55f, -0.45f, 1f, -1f, 1f) + horizontalLineTo(8f) + curveToRelative(-0.55f, 0f, -1f, -0.45f, -1f, -1f) + verticalLineTo(5f) + curveToRelative(0f, -0.55f, 0.45f, -1f, 1f, -1f) + horizontalLineToRelative(2f) + verticalLineTo(3f) + curveToRelative(0f, -0.55f, 0.45f, -1f, 1f, -1f) + horizontalLineToRelative(2f) + curveToRelative(0.55f, 0f, 1f, 0.45f, 1f, 1f) + verticalLineToRelative(1f) + horizontalLineToRelative(2f) + curveTo(16.55f, 4f, 17f, 4.45f, 17f, 5f) + close() + moveTo(15f, 6f) + horizontalLineTo(9f) + verticalLineToRelative(10f) + horizontalLineToRelative(6f) + verticalLineTo(6f) + close() + } + } + +val Icons.Rounded.Battery3Bar + get() = materialIcon("Icons.Rounded.Battery3Bar") { + materialPath { + moveTo(17f, 5f) + verticalLineToRelative(16f) + curveToRelative(0f, 0.55f, -0.45f, 1f, -1f, 1f) + horizontalLineTo(8f) + curveToRelative(-0.55f, 0f, -1f, -0.45f, -1f, -1f) + verticalLineTo(5f) + curveToRelative(0f, -0.55f, 0.45f, -1f, 1f, -1f) + horizontalLineToRelative(2f) + verticalLineTo(3f) + curveToRelative(0f, -0.55f, 0.45f, -1f, 1f, -1f) + horizontalLineToRelative(2f) + curveToRelative(0.55f, 0f, 1f, 0.45f, 1f, 1f) + verticalLineToRelative(1f) + horizontalLineToRelative(2f) + curveTo(16.55f, 4f, 17f, 4.45f, 17f, 5f) + close() + moveTo(15f, 6f) + horizontalLineTo(9f) + verticalLineToRelative(8f) + horizontalLineToRelative(6f) + verticalLineTo(6f) + close() + } + } + +val Icons.Rounded.Battery4Bar + get() = materialIcon("Icons.Rounded.Battery4Bar") { + materialPath { + moveTo(17f, 5f) + verticalLineToRelative(16f) + curveToRelative(0f, 0.55f, -0.45f, 1f, -1f, 1f) + horizontalLineTo(8f) + curveToRelative(-0.55f, 0f, -1f, -0.45f, -1f, -1f) + verticalLineTo(5f) + curveToRelative(0f, -0.55f, 0.45f, -1f, 1f, -1f) + horizontalLineToRelative(2f) + verticalLineTo(3f) + curveToRelative(0f, -0.55f, 0.45f, -1f, 1f, -1f) + horizontalLineToRelative(2f) + curveToRelative(0.55f, 0f, 1f, 0.45f, 1f, 1f) + verticalLineToRelative(1f) + horizontalLineToRelative(2f) + curveTo(16.55f, 4f, 17f, 4.45f, 17f, 5f) + close() + moveTo(15f, 6f) + horizontalLineTo(9f) + verticalLineToRelative(6f) + horizontalLineToRelative(6f) + verticalLineTo(6f) + close() + } + } + +val Icons.Rounded.Battery5Bar + get() = materialIcon("Icons.Rounded.Battery5Bar") { + materialPath { + moveTo(17f, 5f) + verticalLineToRelative(16f) + curveToRelative(0f, 0.55f, -0.45f, 1f, -1f, 1f) + horizontalLineTo(8f) + curveToRelative(-0.55f, 0f, -1f, -0.45f, -1f, -1f) + verticalLineTo(5f) + curveToRelative(0f, -0.55f, 0.45f, -1f, 1f, -1f) + horizontalLineToRelative(2f) + verticalLineTo(3f) + curveToRelative(0f, -0.55f, 0.45f, -1f, 1f, -1f) + horizontalLineToRelative(2f) + curveToRelative(0.55f, 0f, 1f, 0.45f, 1f, 1f) + verticalLineToRelative(1f) + horizontalLineToRelative(2f) + curveTo(16.55f, 4f, 17f, 4.45f, 17f, 5f) + close() + moveTo(15f, 6f) + horizontalLineTo(9f) + verticalLineToRelative(4f) + horizontalLineToRelative(6f) + verticalLineTo(6f) + close() + } + } + +val Icons.Rounded.Battery6Bar + get() = materialIcon("Icons.Rounded.Battery6Bar") { + materialPath { + moveTo(17f, 5f) + verticalLineToRelative(16f) + curveToRelative(0f, 0.55f, -0.45f, 1f, -1f, 1f) + horizontalLineTo(8f) + curveToRelative(-0.55f, 0f, -1f, -0.45f, -1f, -1f) + verticalLineTo(5f) + curveToRelative(0f, -0.55f, 0.45f, -1f, 1f, -1f) + horizontalLineToRelative(2f) + verticalLineTo(3f) + curveToRelative(0f, -0.55f, 0.45f, -1f, 1f, -1f) + horizontalLineToRelative(2f) + curveToRelative(0.55f, 0f, 1f, 0.45f, 1f, 1f) + verticalLineToRelative(1f) + horizontalLineToRelative(2f) + curveTo(16.55f, 4f, 17f, 4.45f, 17f, 5f) + close() + moveTo(15f, 6f) + horizontalLineTo(9f) + verticalLineToRelative(2f) + horizontalLineToRelative(6f) + verticalLineTo(6f) + close() + } + } + +val Icons.Rounded.BatteryCharging0Bar + get() = materialIcon("Icons.Rounded.BatteryCharging0Bar") { + group( + scaleX = 0.26458333f, + scaleY = 0.26458333f, + ) { + materialPath { + moveTo(41.574219f, 7.5585938f) + curveTo(39.495479f, 7.5585937f, 37.794922f, 9.2591505f, 37.794922f, 11.337891f) + lineTo(37.794922f, 15.117188f) + lineTo(30.236328f, 15.117188f) + curveTo(28.157588f, 15.117187f, 26.457031f, 16.819697f, 26.457031f, 18.898438f) + lineTo(26.457031f, 79.369141f) + curveTo(26.457031f, 81.447881f, 28.157588f, 83.150391f, 30.236328f, 83.150391f) + lineTo(60.472656f, 83.150391f) + curveTo(62.551396f, 83.150391f, 64.251953f, 81.447881f, 64.251953f, 79.369141f) + lineTo(64.251953f, 18.898438f) + curveTo(64.251953f, 16.819697f, 62.551396f, 15.117188f, 60.472656f, 15.117188f) + lineTo(52.914062f, 15.117188f) + lineTo(52.914062f, 11.337891f) + curveTo(52.914063f, 9.2591505f, 51.213506f, 7.5585938f, 49.134766f, 7.5585938f) + lineTo(41.574219f, 7.5585938f) + close() + moveTo(34.015625f, 22.677734f) + lineTo(56.693359f, 22.677734f) + lineTo(56.693359f, 75.589844f) + lineTo(34.015625f, 75.589844f) + lineTo(34.015625f, 22.677734f) + close() + moveTo(47.253906f, 32.126953f) + curveTo(46.605486f, 32.112843f, 45.950535f, 32.41843f, 45.582031f, 33.109375f) + lineTo(35.490234f, 52.005859f) + curveTo(34.809919f, 53.290899f, 35.716123f, 54.802734f, 37.152344f, 54.802734f) + lineTo(41.574219f, 54.802734f) + lineTo(41.574219f, 68.03125f) + curveTo(41.574219f, 69.996604f, 44.219867f, 70.640241f, 45.126953f, 68.939453f) + lineTo(55.21875f, 50.041016f) + curveTo(55.899065f, 48.755976f, 54.955066f, 47.244141f, 53.556641f, 47.244141f) + lineTo(49.134766f, 47.244141f) + lineTo(49.134766f, 34.015625f) + curveTo(49.134766f, 32.848696f, 48.201598f, 32.147575f, 47.253906f, 32.126953f) + close() + } + } + } + +val Icons.Rounded.BatteryCharging1Bar + get() = materialIcon("Icons.Rounded.BatteryCharging1Bar") { + group( + scaleX = 0.26458333f, + scaleY = 0.26458333f, + ) { + materialPath { + moveTo(41.574219f, 7.5585938f) + curveTo(39.495479f, 7.5585937f, 37.794922f, 9.2591505f, 37.794922f, 11.337891f) + lineTo(37.794922f, 15.117188f) + lineTo(30.236328f, 15.117188f) + curveTo(28.157588f, 15.117187f, 26.457031f, 16.819697f, 26.457031f, 18.898438f) + lineTo(26.457031f, 79.369141f) + curveTo(26.457031f, 81.447881f, 28.157588f, 83.150391f, 30.236328f, 83.150391f) + lineTo(60.472656f, 83.150391f) + curveTo(62.551396f, 83.150391f, 64.251953f, 81.447881f, 64.251953f, 79.369141f) + lineTo(64.251953f, 18.898438f) + curveTo(64.251953f, 16.819697f, 62.551396f, 15.117188f, 60.472656f, 15.117188f) + lineTo(52.914062f, 15.117188f) + lineTo(52.914062f, 11.337891f) + curveTo(52.914063f, 9.2591505f, 51.213506f, 7.5585938f, 49.134766f, 7.5585938f) + lineTo(41.574219f, 7.5585938f) + close() + moveTo(34.015625f, 22.677734f) + lineTo(56.693359f, 22.677734f) + lineTo(56.693359f, 68.03125f) + lineTo(45.611328f, 68.03125f) + lineTo(45.126953f, 68.939453f) + curveTo(44.219867f, 70.640241f, 41.574219f, 69.996604f, 41.574219f, 68.03125f) + lineTo(34.015625f, 68.03125f) + lineTo(34.015625f, 22.677734f) + close() + moveTo(41.574219f, 68.03125f) + lineTo(45.611328f, 68.03125f) + lineTo(55.21875f, 50.041016f) + curveTo(55.899065f, 48.755976f, 54.955066f, 47.244141f, 53.556641f, 47.244141f) + lineTo(49.134766f, 47.244141f) + lineTo(49.134766f, 34.015625f) + curveTo(49.134766f, 32.050271f, 46.489118f, 31.408588f, 45.582031f, 33.109375f) + lineTo(35.490234f, 52.005859f) + curveTo(34.809919f, 53.290899f, 35.716123f, 54.802734f, 37.152344f, 54.802734f) + lineTo(41.574219f, 54.802734f) + lineTo(41.574219f, 68.03125f) + close() + } + } + } + +val Icons.Rounded.BatteryCharging2Bar + get() = materialIcon("Icons.Rounded.BatteryCharging2Bar") { + group( + scaleX = 0.26458333f, + scaleY = 0.26458333f, + ) { + materialPath { + moveTo(41.574219f, 7.5585938f) + curveTo(39.495479f, 7.5585937f, 37.794922f, 9.2591505f, 37.794922f, 11.337891f) + lineTo(37.794922f, 15.117188f) + lineTo(30.236328f, 15.117188f) + curveTo(28.157588f, 15.117187f, 26.457031f, 16.819697f, 26.457031f, 18.898438f) + lineTo(26.457031f, 79.369141f) + curveTo(26.457031f, 81.447881f, 28.157588f, 83.150391f, 30.236328f, 83.150391f) + lineTo(60.472656f, 83.150391f) + curveTo(62.551396f, 83.150391f, 64.251953f, 81.447881f, 64.251953f, 79.369141f) + lineTo(64.251953f, 18.898438f) + curveTo(64.251953f, 16.819697f, 62.551396f, 15.117188f, 60.472656f, 15.117188f) + lineTo(52.914062f, 15.117188f) + lineTo(52.914062f, 11.337891f) + curveTo(52.914063f, 9.2591505f, 51.213506f, 7.5585938f, 49.134766f, 7.5585938f) + lineTo(41.574219f, 7.5585938f) + close() + moveTo(34.015625f, 22.677734f) + lineTo(56.693359f, 22.677734f) + lineTo(56.693359f, 60.472656f) + lineTo(49.648438f, 60.472656f) + lineTo(45.126953f, 68.939453f) + curveTo(44.219867f, 70.640241f, 41.574219f, 69.996604f, 41.574219f, 68.03125f) + lineTo(41.574219f, 60.472656f) + lineTo(34.015625f, 60.472656f) + lineTo(34.015625f, 22.677734f) + close() + moveTo(41.574219f, 60.472656f) + lineTo(49.648438f, 60.472656f) + lineTo(55.21875f, 50.041016f) + curveTo(55.899065f, 48.755976f, 54.955066f, 47.244141f, 53.556641f, 47.244141f) + lineTo(49.134766f, 47.244141f) + lineTo(49.134766f, 34.015625f) + curveTo(49.134766f, 32.050271f, 46.489118f, 31.408588f, 45.582031f, 33.109375f) + lineTo(35.490234f, 52.005859f) + curveTo(34.809919f, 53.290899f, 35.716123f, 54.802734f, 37.152344f, 54.802734f) + lineTo(41.574219f, 54.802734f) + lineTo(41.574219f, 60.472656f) + close() + } + } + } + +val Icons.Rounded.BatteryCharging3Bar + get() = materialIcon("Icons.Rounded.BatteryCharging3Bar") { + group( + scaleX = 0.26458333f, + scaleY = 0.26458333f, + ) { + materialPath { + moveTo(41.574219f, 7.5585938f) + curveTo(39.495479f, 7.5585937f, 37.794922f, 9.2591505f, 37.794922f, 11.337891f) + lineTo(37.794922f, 15.117188f) + lineTo(30.236328f, 15.117188f) + curveTo(28.157588f, 15.117187f, 26.457031f, 16.819697f, 26.457031f, 18.898438f) + lineTo(26.457031f, 79.369141f) + curveTo(26.457031f, 81.447881f, 28.157588f, 83.150391f, 30.236328f, 83.150391f) + lineTo(60.472656f, 83.150391f) + curveTo(62.551396f, 83.150391f, 64.251953f, 81.447881f, 64.251953f, 79.369141f) + lineTo(64.251953f, 18.898438f) + curveTo(64.251953f, 16.819697f, 62.551396f, 15.117188f, 60.472656f, 15.117188f) + lineTo(52.914062f, 15.117188f) + lineTo(52.914062f, 11.337891f) + curveTo(52.914063f, 9.2591505f, 51.213506f, 7.5585938f, 49.134766f, 7.5585938f) + lineTo(41.574219f, 7.5585938f) + close() + moveTo(34.015625f, 22.677734f) + lineTo(56.693359f, 22.677734f) + lineTo(56.693359f, 52.914062f) + lineTo(53.683594f, 52.914062f) + lineTo(45.126953f, 68.939453f) + curveTo(44.219867f, 70.640241f, 41.574219f, 69.996604f, 41.574219f, 68.03125f) + lineTo(41.574219f, 54.802734f) + lineTo(37.152344f, 54.802734f) + curveTo(36.048819f, 54.802734f, 35.258483f, 53.910469f, 35.259766f, 52.914062f) + lineTo(34.015625f, 52.914062f) + lineTo(34.015625f, 22.677734f) + close() + moveTo(35.259766f, 52.914062f) + lineTo(53.683594f, 52.914062f) + lineTo(55.21875f, 50.041016f) + curveTo(55.899065f, 48.755976f, 54.955066f, 47.244141f, 53.556641f, 47.244141f) + lineTo(49.134766f, 47.244141f) + lineTo(49.134766f, 34.015625f) + curveTo(49.134766f, 32.050271f, 46.489118f, 31.408588f, 45.582031f, 33.109375f) + lineTo(35.490234f, 52.005859f) + curveTo(35.332642f, 52.303535f, 35.260152f, 52.613661f, 35.259766f, 52.914062f) + close() + } + } + } + +val Icons.Rounded.BatteryCharging4Bar + get() = materialIcon("Icons.Rounded.BatteryCharging4Bar") { + group( + scaleX = 0.26458333f, + scaleY = 0.26458333f, + ) { + materialPath { + moveTo(41.574219f, 7.5585938f) + curveTo(39.495479f, 7.5585937f, 37.794922f, 9.2591505f, 37.794922f, 11.337891f) + lineTo(37.794922f, 15.117188f) + lineTo(30.236328f, 15.117188f) + curveTo(28.157588f, 15.117187f, 26.457031f, 16.819697f, 26.457031f, 18.898438f) + lineTo(26.457031f, 79.369141f) + curveTo(26.457031f, 81.447881f, 28.157588f, 83.150391f, 30.236328f, 83.150391f) + lineTo(60.472656f, 83.150391f) + curveTo(62.551396f, 83.150391f, 64.251953f, 81.447881f, 64.251953f, 79.369141f) + lineTo(64.251953f, 18.898438f) + curveTo(64.251953f, 16.819697f, 62.551396f, 15.117188f, 60.472656f, 15.117188f) + lineTo(52.914062f, 15.117188f) + lineTo(52.914062f, 11.337891f) + curveTo(52.914063f, 9.2591505f, 51.213506f, 7.5585938f, 49.134766f, 7.5585938f) + lineTo(41.574219f, 7.5585938f) + close() + moveTo(34.015625f, 22.677734f) + lineTo(56.693359f, 22.677734f) + lineTo(56.693359f, 45.353516f) + lineTo(49.134766f, 45.353516f) + lineTo(49.134766f, 47.244141f) + lineTo(53.556641f, 47.244141f) + curveTo(54.955066f, 47.244141f, 55.899065f, 48.755976f, 55.21875f, 50.041016f) + lineTo(45.126953f, 68.939453f) + curveTo(44.219867f, 70.640241f, 41.574219f, 69.996604f, 41.574219f, 68.03125f) + lineTo(41.574219f, 54.802734f) + lineTo(37.152344f, 54.802734f) + curveTo(35.716123f, 54.802734f, 34.809919f, 53.290899f, 35.490234f, 52.005859f) + lineTo(39.042969f, 45.353516f) + lineTo(34.015625f, 45.353516f) + lineTo(34.015625f, 22.677734f) + close() + moveTo(39.042969f, 45.353516f) + lineTo(49.134766f, 45.353516f) + lineTo(49.134766f, 34.015625f) + curveTo(49.134766f, 32.050271f, 46.489118f, 31.408588f, 45.582031f, 33.109375f) + lineTo(39.042969f, 45.353516f) + close() + } + } + } + +val Icons.Rounded.BatteryCharging5Bar + get() = materialIcon("Icons.Rounded.BatteryCharging5Bar") { + group( + scaleX = 0.26458333f, + scaleY = 0.26458333f, + ) { + materialPath { + moveTo(41.574219f, 7.5585938f) + curveTo(39.495479f, 7.5585937f, 37.794922f, 9.2591505f, 37.794922f, 11.337891f) + lineTo(37.794922f, 15.117188f) + lineTo(30.236328f, 15.117188f) + curveTo(28.157588f, 15.117187f, 26.457031f, 16.819697f, 26.457031f, 18.898438f) + lineTo(26.457031f, 79.369141f) + curveTo(26.457031f, 81.447881f, 28.157588f, 83.150391f, 30.236328f, 83.150391f) + lineTo(60.472656f, 83.150391f) + curveTo(62.551396f, 83.150391f, 64.251953f, 81.447881f, 64.251953f, 79.369141f) + lineTo(64.251953f, 18.898438f) + curveTo(64.251953f, 16.819697f, 62.551396f, 15.117188f, 60.472656f, 15.117188f) + lineTo(52.914062f, 15.117188f) + lineTo(52.914062f, 11.337891f) + curveTo(52.914063f, 9.2591505f, 51.213506f, 7.5585938f, 49.134766f, 7.5585938f) + lineTo(41.574219f, 7.5585938f) + close() + moveTo(34.015625f, 22.677734f) + lineTo(56.693359f, 22.677734f) + lineTo(56.693359f, 37.794922f) + lineTo(49.134766f, 37.794922f) + lineTo(49.134766f, 47.244141f) + lineTo(53.556641f, 47.244141f) + curveTo(54.955066f, 47.244141f, 55.899065f, 48.755976f, 55.21875f, 50.041016f) + lineTo(45.126953f, 68.939453f) + curveTo(44.219867f, 70.640241f, 41.574219f, 69.996604f, 41.574219f, 68.03125f) + lineTo(41.574219f, 54.802734f) + lineTo(37.152344f, 54.802734f) + curveTo(35.716123f, 54.802734f, 34.809919f, 53.290899f, 35.490234f, 52.005859f) + lineTo(43.080078f, 37.794922f) + lineTo(34.015625f, 37.794922f) + lineTo(34.015625f, 22.677734f) + close() + moveTo(43.080078f, 37.794922f) + lineTo(49.134766f, 37.794922f) + lineTo(49.134766f, 34.015625f) + curveTo(49.134766f, 32.050271f, 46.489118f, 31.408588f, 45.582031f, 33.109375f) + lineTo(43.080078f, 37.794922f) + close() + } + } + } + +val Icons.Rounded.BatteryCharging6Bar + get() = materialIcon("Icons.Rounded.BatteryCharging6Bar") { + group( + scaleX = 0.26458333f, + scaleY = 0.26458333f, + ) { + materialPath { + moveTo(41.574219f, 7.5585938f) + curveTo(39.495479f, 7.5585937f, 37.794922f, 9.2591505f, 37.794922f, 11.337891f) + lineTo(37.794922f, 15.117188f) + lineTo(30.236328f, 15.117188f) + curveTo(28.157588f, 15.117187f, 26.457031f, 16.819697f, 26.457031f, 18.898438f) + lineTo(26.457031f, 79.369141f) + curveTo(26.457031f, 81.447881f, 28.157588f, 83.150391f, 30.236328f, 83.150391f) + lineTo(60.472656f, 83.150391f) + curveTo(62.551396f, 83.150391f, 64.251953f, 81.447881f, 64.251953f, 79.369141f) + lineTo(64.251953f, 18.898438f) + curveTo(64.251953f, 16.819697f, 62.551396f, 15.117188f, 60.472656f, 15.117188f) + lineTo(52.914062f, 15.117188f) + lineTo(52.914062f, 11.337891f) + curveTo(52.914063f, 9.2591505f, 51.213506f, 7.5585938f, 49.134766f, 7.5585938f) + lineTo(41.574219f, 7.5585938f) + close() + moveTo(34.015625f, 22.677734f) + lineTo(56.693359f, 22.677734f) + lineTo(56.693359f, 30.236328f) + lineTo(34.015625f, 30.236328f) + lineTo(34.015625f, 22.677734f) + close() + moveTo(47.253906f, 32.126953f) + curveTo(48.201598f, 32.147575f, 49.134766f, 32.848696f, 49.134766f, 34.015625f) + lineTo(49.134766f, 47.244141f) + lineTo(53.556641f, 47.244141f) + curveTo(54.955066f, 47.244141f, 55.899065f, 48.755976f, 55.21875f, 50.041016f) + lineTo(45.126953f, 68.939453f) + curveTo(44.219867f, 70.640241f, 41.574219f, 69.996604f, 41.574219f, 68.03125f) + lineTo(41.574219f, 54.802734f) + lineTo(37.152344f, 54.802734f) + curveTo(35.716123f, 54.802734f, 34.809919f, 53.290899f, 35.490234f, 52.005859f) + lineTo(45.582031f, 33.109375f) + curveTo(45.950535f, 32.41843f, 46.605486f, 32.112843f, 47.253906f, 32.126953f) + close() + } + } + } \ No newline at end of file diff --git a/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/clock/ClockWidgetVM.kt b/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/clock/ClockWidgetVM.kt index 5e37970a..620fc994 100644 --- a/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/clock/ClockWidgetVM.kt +++ b/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/clock/ClockWidgetVM.kt @@ -10,10 +10,7 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.asLiveData import de.mm20.launcher2.ktx.tryStartActivity import de.mm20.launcher2.preferences.LauncherDataStore -import de.mm20.launcher2.ui.launcher.widgets.clock.parts.AlarmPartProvider -import de.mm20.launcher2.ui.launcher.widgets.clock.parts.DatePartProvider -import de.mm20.launcher2.ui.launcher.widgets.clock.parts.MusicPartProvider -import de.mm20.launcher2.ui.launcher.widgets.clock.parts.PartProvider +import de.mm20.launcher2.ui.launcher.widgets.clock.parts.* import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.channels.trySendBlocking import kotlinx.coroutines.flow.* @@ -29,7 +26,8 @@ class ClockWidgetVM : ViewModel(), KoinComponent { partProviders.value = listOf( DatePartProvider(), MusicPartProvider(), - AlarmPartProvider() + AlarmPartProvider(), + BatteryPartProvider(), ) } diff --git a/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/clock/parts/BatteryPartProvider.kt b/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/clock/parts/BatteryPartProvider.kt new file mode 100644 index 00000000..49f8c4cf --- /dev/null +++ b/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/clock/parts/BatteryPartProvider.kt @@ -0,0 +1,193 @@ +package de.mm20.launcher2.ui.launcher.widgets.clock.parts + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.content.IntentFilter +import android.os.BatteryManager +import android.os.Build +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.rounded.BatteryChargingFull +import androidx.compose.material.icons.rounded.BatteryFull +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import androidx.core.content.getSystemService +import de.mm20.launcher2.preferences.Settings +import de.mm20.launcher2.ui.R +import de.mm20.launcher2.ui.icons.* +import de.mm20.launcher2.ui.pluralResource +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.channels.trySendBlocking +import kotlinx.coroutines.flow.* + +class BatteryPartProvider : PartProvider { + + private val batteryInfo = MutableStateFlow(null) + + override fun getRanking(context: Context): Flow = channelFlow { + val chargingInfo = getChargingInfo(context) + + chargingInfo.collectLatest { + batteryInfo.value = it + if (it.charging) { + send(10) + } else if (it.level <= 15) { + send(55) + } else { + send(0) + } + } + } + + private val time = MutableStateFlow(System.currentTimeMillis()) + + override fun setTime(time: Long) { + super.setTime(time) + this.time.value = time + } + + @Composable + override fun Component(layout: Settings.ClockWidgetSettings.ClockWidgetLayout) { + + val batteryInfo by this.batteryInfo.collectAsState(null) + + batteryInfo?.let { + + if (layout == Settings.ClockWidgetSettings.ClockWidgetLayout.Vertical) { + Row( + Modifier.padding(8.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + imageVector = getBatteryIcon(it), + contentDescription = null + ) + Text( + modifier = Modifier.padding(start = 8.dp), + text = "${it.level} %", + style = MaterialTheme.typography.titleMedium, + ) + if (it.charging) { + Text( + modifier = Modifier.padding(start = 8.dp), + text = it.fullIn?.let { + val m = (it / 60000).toInt() + pluralResource(R.plurals.battery_part_remaining_charge_time, m, m) + } ?: stringResource(R.string.battery_part_charging), + style = MaterialTheme.typography.bodySmall + ) + } + } + } + if (layout == Settings.ClockWidgetSettings.ClockWidgetLayout.Horizontal) { + Row( + Modifier.padding(8.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + modifier = Modifier.padding(end = 12.dp).size(36.dp), + imageVector = getBatteryIcon(it), + contentDescription = null + ) + Column { + Text( + text = "${it.level} %", + style = MaterialTheme.typography.titleLarge, + ) + if (it.charging) { + Text( + text = it.fullIn?.let { + val m = (it / 60000).toInt() + pluralResource(R.plurals.battery_part_remaining_charge_time, m, m) + } ?: stringResource(R.string.battery_part_charging), + style = MaterialTheme.typography.bodyMedium + ) + } + } + } + } + } + } + + private fun getBatteryIcon(batteryInfo: BatteryInfo): ImageVector { + return if (batteryInfo.charging) { + when (batteryInfo.level) { + in 0..12 -> Icons.Rounded.BatteryCharging0Bar + in 13..25 -> Icons.Rounded.BatteryCharging1Bar + in 26..37 -> Icons.Rounded.BatteryCharging2Bar + in 38..50 -> Icons.Rounded.BatteryCharging3Bar + in 51..63 -> Icons.Rounded.BatteryCharging4Bar + in 64..75 -> Icons.Rounded.BatteryCharging5Bar + in 76..88 -> Icons.Rounded.BatteryCharging6Bar + else -> Icons.Rounded.BatteryChargingFull + } + } else { + when (batteryInfo.level) { + in 0..12 -> Icons.Rounded.Battery0Bar + in 13..25 -> Icons.Rounded.Battery1Bar + in 26..37 -> Icons.Rounded.Battery2Bar + in 38..50 -> Icons.Rounded.Battery3Bar + in 51..63 -> Icons.Rounded.Battery4Bar + in 64..75 -> Icons.Rounded.Battery5Bar + in 76..88 -> Icons.Rounded.Battery6Bar + else -> Icons.Rounded.BatteryFull + } + } + } + + private fun getChargingInfo(context: Context): Flow = callbackFlow { + val batteryManager: BatteryManager = context.getSystemService() ?: return@callbackFlow + + trySendBlocking( + BatteryInfo( + level = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY), + charging = batteryManager.isCharging, + fullIn = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + batteryManager.computeChargeTimeRemaining().takeIf { it >= 0 } + } else null, + ) + ) + + val receiver = object : BroadcastReceiver() { + override fun onReceive(context: Context?, intent: Intent?) { + trySendBlocking( + BatteryInfo( + level = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY), + charging = intent?.getIntExtra( + BatteryManager.EXTRA_STATUS, + BatteryManager.BATTERY_STATUS_UNKNOWN + ) == BatteryManager.BATTERY_STATUS_CHARGING, + fullIn = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + batteryManager.computeChargeTimeRemaining().takeIf { it >= 0 } + } else null, + ) + ) + } + } + context.registerReceiver(receiver, IntentFilter().apply { + addAction(Intent.ACTION_BATTERY_CHANGED) + }) + awaitClose { + context.unregisterReceiver(receiver) + } + } +} + +private data class BatteryInfo( + val level: Int, + val charging: Boolean, + val fullIn: Long?, +) \ No newline at end of file