Skip to content

Commit 27c5b6d

Browse files
Keril3claude
andcommitted
Larger independent status bar sizes, minute mode pauses background sync, About the author
- Status bar icon: the number is measured by its digits (a decimal comma hangs below them), the arrow gives way before the number ever shrinks, sizes are multipliers ×0.8–×1.25, the arrow beside the number is the default. - Arrow position as themed tiles drawn with the real icon. - Turning minute mode on switches background sync off and shows a notice that stays until its link or ✕; it comes back when minute mode stops. - Progress bars add whole blocks one by one as in Windows XP; reading a file shows a running group of blocks. - A chain on the GitHub button and an "About the author" window with keril.art and its contacts. - Fixed: "Clear" in the developer log left Samsung Health's lines. - Tests, translations in 12 languages, READMEs, changelog, screenshots, 1.8.0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 3ae920c commit 27c5b6d

60 files changed

Lines changed: 1009 additions & 151 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎CHANGELOG.md‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,25 @@
22

33
Newest version first. A version's section becomes the release notes on GitHub.
44

5+
## 1.8.0 — 2026-10-12
6+
7+
- The glucose in the status bar is larger and its sizes are independent. The number is measured by its digits:
8+
a decimal comma hangs below them instead of making them about a fifth smaller. The arrow's size never changes
9+
the number any more: when the square runs short, the digits get narrower and then the arrow gives way. Beside
10+
the number (now the default) the number is as tall as the clock's digits. The sizes are multipliers, two
11+
smaller and two larger: ×0.8, ×0.9, ×1.1, ×1.25 instead of S, M, L, XL.
12+
- "Arrow position" shows both choices as tiles in the app's style, each drawn on a status bar with the real
13+
icon; the preview's status bar follows the light or dark theme.
14+
- Turning minute mode on switches background sync off: it would only fetch the same, less often. A pink notice
15+
at the bottom of the screen says so and stays until its link to the setting or its ✕ is tapped. When minute
16+
mode is turned off, background sync comes back with its interval.
17+
- Progress bars behave as in Windows XP: whole blocks appear one after another. Reading a file shows a group of
18+
blocks running through the bar.
19+
- "About SugarBridge": the GitHub button has a chain to show it is a link. A new "About the author" window below
20+
it has the website keril.art and the contacts from it: email, Discord and Telegram.
21+
- Fixed: "Clear" in the developer tools' log left Samsung Health's lines, which are read from Android's usage
22+
statistics each time. Lines older than the moment of clearing aren't shown again.
23+
524
## 1.7.1 — 2026-10-12
625

726
- Fixed: with the notification pinned, every new value moved SugarBridge's icon in the status bar ahead of other

‎README.md‎

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,10 @@ from the LibreLinkUp cloud and writes them to Health Connect, where Samsung Heal
2424

2525
- **Glucose in Samsung Health**: in the background every 15 minutes (or less often), without a notification.
2626
- **Minute mode**: every new reading goes to Samsung Health, and the glucose value with its trend arrow is
27-
shown as a number in the status bar: by default the number fills the icon and the arrow stands above it.
28-
In Settings → Status bar you set the size of the number and of the arrow and where the arrow stands, with a
29-
preview; each can also be turned off. The notification can be made quiet or hidden completely.
27+
shown as a number in the status bar, as tall as the clock's digits. In Settings → Status bar you make the
28+
number and the arrow smaller or larger (×0.8, ×0.9, ×1.1, ×1.25, each on its own) and put the arrow beside
29+
the number or above it, with a preview; each can also be turned off. Background sync is switched off while
30+
minute mode runs and comes back when it stops. The notification can be made quiet or hidden completely.
3031
- **Full history from LibreView**: download the export right in the app, look through it on a chart (a day, a
3132
week, a month, all of it or any period from a calendar), then choose the days you want in Samsung Health.
3233
Nothing is written twice, and anything unwanted can be deleted. The history stays in the app until you delete
@@ -36,7 +37,8 @@ from the LibreLinkUp cloud and writes them to Health Connect, where Samsung Heal
3637
- **Its own chart and statistics** for 12 hours, mmol/L or mg/dL, your own target range. Tap the chart to open it
3738
full screen and move a finger along it to read every value and its time.
3839
- **Light and dark theme** in the style of [keril.art](https://keril.art/): a blue sky with a field of dots,
39-
Windows XP style windows and a pixel font. The phone's theme by default, or light or dark in Settings.
40+
windows and progress bars in the style of Windows XP (the bars fill block by block) and a pixel font. The
41+
phone's theme by default, or light or dark in Settings.
4042
- **Readable for everyone**: four text sizes and a low vision mode with the phone's own font, larger text,
4143
more contrast and a plain background.
4244
- **Developer tools** (Settings → About SugarBridge): an event log of every sync and of what Android did
@@ -110,6 +112,7 @@ You need:
110112
back for hours while the phone lies idle, and Samsung may put the app to sleep.
111113
7. Optional: **Settings → Minute mode** for a new value every minute; "Pin the notification" brings it back if it
112114
is swiped away by accident. **Settings → Status bar** sets how large the number and the arrow are there.
115+
Minute mode switches background sync off and says so in a notice; it comes back when minute mode stops.
113116

114117
### Full history from LibreView
115118

@@ -161,8 +164,17 @@ restricted settings", confirm, then turn usage access on. The developer tools ha
161164
than every 15 minutes. It can be made quiet (Settings → "Glucose in the notification") or turned off completely
162165
("Hide the notification completely"); the mode keeps working.
163166

164-
**Do I need background sync for minute mode?** No, they are separate. Background sync (every 15 minutes or
165-
less often, no notification) can stay on as a backup: each run fetches the last 12 hours, so nothing is missed.
167+
**Do I need background sync for minute mode?** No. Minute mode already fetches every minute what background
168+
sync (every 15 minutes or less often, no notification) would fetch, so turning minute mode on switches
169+
background sync off. A notice at the bottom of the screen says so and stays until you tap its link to the
170+
setting or its ✕. When minute mode is turned off, background sync comes back with the interval it had. You can
171+
also turn it back on yourself: it does no harm, each run fetches the last 12 hours.
172+
173+
**Why is the number in the status bar not larger?** Android draws every notification icon in a small square,
174+
the same for every app, and shrinks a wider picture to fit it. So the number and the arrow share one square.
175+
With the arrow beside the number, the number is as tall as the clock's digits; above the number the arrow takes
176+
height, so both are a little smaller there. The number's size never depends on the arrow's: when the square
177+
runs short, the arrow gives way. Long values (10.4, 250) are narrowed a little first.
166178

167179
**Can it work without Health Connect?** No, and it doesn't need to: on Android 14+ it is part of the system,
168180
not a separate app. Writing to Samsung Health directly requires a Samsung partner key. If Health Connect is
@@ -244,14 +256,19 @@ GitHub Actions builds and signs the APK in Releases when a `v*` tag arrives in t
244256
```
245257
3. **Every release:** add the version's section to [CHANGELOG.md](CHANGELOG.md), then
246258
```sh
247-
git tag v1.7.1
248-
git push origin v1.7.1
259+
git tag v1.8.0
260+
git push origin v1.8.0
249261
```
250262
A few minutes later `SugarBridge.apk` appears in Releases with the notes from the CHANGELOG.
251263

252264
A signed APK can be built locally too: put `sugarbridge.keystore`, `sugarbridge.keystorePassword`,
253265
`sugarbridge.keyAlias` and `sugarbridge.keyPassword` into `~/.gradle/gradle.properties` (outside the repository)
254-
and run `./gradlew assembleRelease -Psugarbridge.version=1.7.1`.
266+
and run `./gradlew assembleRelease -Psugarbridge.version=1.8.0`.
267+
268+
## Author
269+
270+
SugarBridge is made by Keril³: [keril.art](https://keril.art/). The contacts are on the website and in the app
271+
(Settings → About the author).
255272

256273
## Thanks
257274

‎README.ru.md‎

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,10 @@
2424

2525
- **Сахар в Samsung Health** — в фоне раз в 15 минут (можно реже) без уведомления в шторке.
2626
- **Минутный режим** — каждый новый замер попадает в Samsung Health, а сахар со стрелкой виден
27-
числом в строке состояния: по умолчанию число занимает весь значок, а стрелка стоит над ним. В Настройках →
28-
«Строка состояния» задаются размер числа и стрелки и где стоит стрелка, с предпросмотром; их можно и
29-
выключить. Уведомление можно сделать тихим или скрыть совсем.
27+
числом в строке состояния — высотой с цифры часов. В Настройках → «Строка состояния» число и стрелку можно
28+
уменьшить или увеличить (×0,8, ×0,9, ×1,1, ×1,25, каждое отдельно) и поставить стрелку справа от числа или
29+
над ним, с предпросмотром; их можно и выключить. Пока работает минутный режим, фоновая синхронизация
30+
выключена и включается снова, когда он остановлен. Уведомление можно сделать тихим или скрыть совсем.
3031
- **Вся история из LibreView** — скачайте выгрузку прямо в приложении, посмотрите её на графике (день, неделя,
3132
месяц, вся или любой период из календаря) и выберите дни, которые нужны в Samsung Health. Повторы не
3233
задваиваются, ненужное можно удалить. История остаётся в приложении, пока вы её не удалите; новую выгрузку
@@ -36,7 +37,8 @@
3637
- **Свой график и статистика** за 12 часов, ммоль/л или мг/дл, свой целевой диапазон. Нажмите на график —
3738
он откроется на весь экран, а пальцем по нему видно каждое значение и его время.
3839
- **Светлая и тёмная тема** в стиле [keril.art](https://keril.art/): голубое небо в точку, окна в духе
39-
Windows XP и пиксельный шрифт. По умолчанию — как на телефоне, в настройках можно выбрать светлую или тёмную.
40+
Windows XP, такие же полоски загрузки (заполняются по блоку) и пиксельный шрифт. По умолчанию — как на
41+
телефоне, в настройках можно выбрать светлую или тёмную.
4042
- **Удобно читать** — четыре размера текста и режим для слабовидящих: обычный шрифт телефона, крупнее,
4143
контрастнее, однотонный фон.
4244
- **Инструменты для разработчиков** (Настройки → О SugarBridge): журнал всех синхронизаций и того, что делал
@@ -113,6 +115,7 @@ SugarBridge сначала пробует сервер по стране тел
113115
синхронизацию, пока телефон лежит без дела, а Samsung может усыплять приложение.
114116
7. По желанию: **Настройки → Минутный режим** — новое значение каждую минуту; «Закрепить уведомление» вернёт
115117
его, если случайно смахнуть. **Настройки → Строка состояния** — насколько крупными там будут число и стрелка.
118+
Минутный режим выключает фоновую синхронизацию и сообщает об этом; когда он остановлен, она включается снова.
116119

117120
### Вся история из LibreView
118121

@@ -167,8 +170,17 @@ Connect, можно только через Samsung Health Data SDK с кодо
167170
только сервису с уведомлением. Его можно сделать тихим (Настройки → «Сахар в уведомлении») или
168171
выключить совсем (кнопка «Скрыть уведомление совсем») — режим продолжит работать.
169172

170-
**Нужна ли фоновая синхронизация для минутного режима?** Нет, они не связаны. Фоновую (раз в 15 минут или реже,
171-
без уведомления) можно оставить запасной: каждый раз она забирает историю за 12 часов, так что пропусков не будет.
173+
**Нужна ли фоновая синхронизация для минутного режима?** Нет. Минутный режим каждую минуту забирает то же, что
174+
фоновая (раз в 15 минут или реже, без уведомления), поэтому при его включении фоновая выключается. Внизу экрана
175+
появится уведомление об этом; оно не исчезнет, пока вы не нажмёте в нём ссылку на настройку или ✕. Когда
176+
минутный режим выключен, фоновая включается снова с тем же интервалом. Её можно включить и самому — вреда не
177+
будет: каждый раз она забирает историю за 12 часов.
178+
179+
**Почему число в строке состояния не крупнее?** Android рисует значок любого уведомления в маленьком квадрате,
180+
одинаковом для всех приложений, а более широкую картинку уменьшает, чтобы она влезла. Поэтому число и стрелка
181+
делят один квадрат. Со стрелкой справа число высотой с цифры часов; над числом стрелка занимает высоту, поэтому
182+
там оба чуть меньше. Размер числа никогда не зависит от размера стрелки: если места не хватает, уступает
183+
стрелка. Длинные значения (10,4, 250) сначала немного сужаются.
172184

173185
**Можно ли без Health Connect?** Нет, и не нужно: на Android 14+ это часть системы, а не отдельное
174186
приложение. Писать в Samsung Health напрямую можно только с ключом партнёра Samsung. Если
@@ -251,14 +263,19 @@ APK в Releases собирает и подписывает GitHub Actions, ко
251263
```
252264
3. **Каждый выпуск:** допишите раздел версии в [CHANGELOG.md](CHANGELOG.md) (на английском), затем
253265
```sh
254-
git tag v1.7.1
255-
git push origin v1.7.1
266+
git tag v1.8.0
267+
git push origin v1.8.0
256268
```
257269
Через несколько минут в Releases появится `SugarBridge.apk` с описанием из CHANGELOG.
258270

259271
Подписанный APK можно собрать и у себя: пропишите в `~/.gradle/gradle.properties` (вне репозитория)
260272
`sugarbridge.keystore`, `sugarbridge.keystorePassword`, `sugarbridge.keyAlias`, `sugarbridge.keyPassword`
261-
и запустите `./gradlew assembleRelease -Psugarbridge.version=1.7.1`.
273+
и запустите `./gradlew assembleRelease -Psugarbridge.version=1.8.0`.
274+
275+
## Автор
276+
277+
SugarBridge делает Keril³: [keril.art](https://keril.art/). Контакты — на сайте и в приложении
278+
(Настройки → Об авторе).
262279

263280
## Благодарности
264281

‎app/build.gradle.kts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ plugins {
33
alias(libs.plugins.kotlin.compose)
44
}
55

6-
// The version: a release takes it from the git tag (./gradlew -Psugarbridge.version=1.7.1), otherwise this one.
6+
// The version: a release takes it from the git tag (./gradlew -Psugarbridge.version=1.8.0), otherwise this one.
77
// versionCode grows with it: 1.2.3 → 10203.
8-
val appVersion = providers.gradleProperty("sugarbridge.version").getOrElse("1.7.1")
8+
val appVersion = providers.gradleProperty("sugarbridge.version").getOrElse("1.8.0")
99
val appVersionCode = (appVersion.substringBefore('-').split('.').map { it.toIntOrNull() ?: 0 } + listOf(0, 0, 0))
1010
.take(3)
1111
.let { (major, minor, patch) -> major * 10_000 + minor * 100 + patch }

‎app/src/androidTest/java/com/sugarbridge/app/sync/StatusIconTest.kt‎

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,70 @@ class StatusIconTest {
6161
assertTrue((0..2).all { arrowHeight(it) < arrowHeight(it + 1) })
6262
}
6363

64+
/** Rows with a visible pixel left of column [before]: beside the number, everything but the arrow. */
65+
private fun rowsLeftOf(b: Bitmap, before: Int): IntRange {
66+
val rows = (0 until SIZE).filter { y -> (0 until before).any { x -> visible(b, x, y) } }
67+
return rows.first()..rows.last()
68+
}
69+
70+
/** The height of the first digit alone, without a comma's tail. */
71+
private fun firstDigitHeight(icon: Bitmap) = height(rowsLeftOf(icon, runs(icon, rows = false).first().last + 1))
72+
73+
/** The number's drawn height: above it is everything under the arrow, beside it everything left of the arrow. */
74+
private fun numberHeight(icon: Bitmap, above: Boolean): Int =
75+
if (above) runs(icon, rows = true).drop(1).let { it.last().last - it.first().first + 1 }
76+
else height(rowsLeftOf(icon, runs(icon, rows = false).last().first))
77+
78+
/**
79+
* The arrow's step never changes the number, for short and long values, with a dot or a comma, beside and
80+
* above. When the square runs short, the arrow gives way instead.
81+
*/
82+
@Test
83+
fun theArrowsStepNeverChangesTheNumber() {
84+
for (value in listOf("6,2", "6.4", "10.4", "22,2", "115", "250")) {
85+
for (above in listOf(false, true)) {
86+
for (numberStep in 0..3) {
87+
val heights = (0..3).map { arrowStep -> numberHeight(StatusIcon.draw(value, 3, above, numberStep, arrowStep), above) }
88+
assertTrue("$value, above $above, number $numberStep: $heights", heights.max() - heights.min() <= 1)
89+
}
90+
}
91+
}
92+
}
93+
94+
/** Above the number every step of the number draws it larger, with a comma too. */
95+
@Test
96+
fun aboveTheNumberEveryStepCounts() {
97+
for (value in listOf("6,4", "6.4")) {
98+
val heights = (0..3).map { numberHeight(StatusIcon.draw(value, 3, true, it, 3), above = true) }
99+
assertTrue("$value: $heights", (0..2).all { heights[it] < heights[it + 1] })
100+
}
101+
}
102+
103+
/** Next to a number of usual size the arrow grows with its step, and the number's step doesn't change it. */
104+
@Test
105+
fun theArrowKeepsItsSizeWhileThereIsRoom() {
106+
fun arrowWidth(numberStep: Int, arrowStep: Int) = height(runs(StatusIcon.draw("6,2", 3, false, numberStep, arrowStep), rows = false).last())
107+
assertTrue((0..2).all { arrowWidth(1, it) < arrowWidth(1, it + 1) })
108+
assertTrue((0..2).all { abs(arrowWidth(0, it) - arrowWidth(2, it)) <= 1 })
109+
assertTrue(arrowWidth(3, 3) <= arrowWidth(0, 3)) // at the largest number the largest arrow gives way
110+
}
111+
112+
/** The comma's tail hangs below the digits: "6,4" has digits as tall as "6.4". */
113+
@Test
114+
fun aCommaDoesNotMakeTheDigitsSmaller() {
115+
fun firstDigit(value: String) = firstDigitHeight(StatusIcon.draw(value, 0, false, 2, 1))
116+
assertTrue("${firstDigit("6,4")} vs ${firstDigit("6.4")}", abs(firstDigit("6,4") - firstDigit("6.4")) <= 1)
117+
}
118+
119+
/** Alone, the largest number is about as tall as the icon: as tall as the clock's digits in the status bar. */
120+
@Test
121+
fun theLargestNumberFillsTheIcon() {
122+
for (value in listOf("6.4", "6,2")) {
123+
val digit = firstDigitHeight(StatusIcon.draw(value, 0, false, 3, 1))
124+
assertTrue("$value: $digit of $SIZE", digit >= SIZE * 0.74)
125+
}
126+
}
127+
64128
@Test
65129
fun withoutATrendTheNumberIsInTheMiddle() {
66130
val number = runs(StatusIcon.draw("6.4", 0, true, 3, 1), rows = true).single()

0 commit comments

Comments
 (0)