Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/workflows/build_loop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,14 @@ jobs:
# Several patches may be added per submodule.
# Adding comments (#) may be useful to easily tell the individual patches apart.

- name: Apply Glucose Guard branding
env:
GH_PAT: ${{ secrets.GH_PAT }}
GLUCOSE_GUARD_DESIGN_OWNER: iDustbin
GLUCOSE_GUARD_DESIGN_REPO: glucose-guard-design
GLUCOSE_GUARD_DESIGN_REF: main
run: ./Scripts/apply_glucose_guard_branding.sh

# Patch Fastlane Match to not print tables
- name: Patch Match Tables
run: |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,4 @@
"version" : 1,
"author" : "xcode"
}
}
}
Binary file modified OverrideAssetsLoop.xcassets/AppIcon.appiconset/Icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified OverrideAssetsLoop.xcassets/AppIcon.appiconset/icon_20pt.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified OverrideAssetsLoop.xcassets/AppIcon.appiconset/icon_20pt@2x-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified OverrideAssetsLoop.xcassets/AppIcon.appiconset/icon_20pt@2x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified OverrideAssetsLoop.xcassets/AppIcon.appiconset/icon_20pt@3x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified OverrideAssetsLoop.xcassets/AppIcon.appiconset/icon_29pt.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified OverrideAssetsLoop.xcassets/AppIcon.appiconset/icon_29pt@2x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified OverrideAssetsLoop.xcassets/AppIcon.appiconset/icon_29pt@3x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified OverrideAssetsLoop.xcassets/AppIcon.appiconset/icon_40pt.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified OverrideAssetsLoop.xcassets/AppIcon.appiconset/icon_40pt@2x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified OverrideAssetsLoop.xcassets/AppIcon.appiconset/icon_40pt@3x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified OverrideAssetsLoop.xcassets/AppIcon.appiconset/icon_60pt@2x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified OverrideAssetsLoop.xcassets/AppIcon.appiconset/icon_60pt@3x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified OverrideAssetsLoop.xcassets/AppIcon.appiconset/icon_76pt.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified OverrideAssetsLoop.xcassets/AppIcon.appiconset/icon_76pt@2x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified OverrideAssetsLoop.xcassets/AppIcon.appiconset/icon_83.5@2x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"size" : "29x29"
},
{
"filename" : "icon_33pt@2x.png",
"idiom" : "watch",
"role" : "notificationCenter",
"scale" : "2x",
Expand All @@ -54,6 +55,7 @@
"subtype" : "40mm"
},
{
"filename" : "icon_46pt@2x.png",
"idiom" : "watch",
"role" : "appLauncher",
"scale" : "2x",
Expand All @@ -69,13 +71,15 @@
"subtype" : "44mm"
},
{
"filename" : "icon_51pt@2x.png",
"idiom" : "watch",
"role" : "appLauncher",
"scale" : "2x",
"size" : "51x51",
"subtype" : "45mm"
},
{
"filename" : "icon_54pt@2x.png",
"idiom" : "watch",
"role" : "appLauncher",
"scale" : "2x",
Expand Down Expand Up @@ -107,13 +111,15 @@
"subtype" : "44mm"
},
{
"filename" : "icon_117pt@2x.png",
"idiom" : "watch",
"role" : "quickLook",
"scale" : "2x",
"size" : "117x117",
"subtype" : "45mm"
},
{
"filename" : "icon_129pt@2x.png",
"idiom" : "watch",
"role" : "quickLook",
"scale" : "2x",
Expand Down
Binary file modified OverrideAssetsWatchApp.xcassets/AppIcon.appiconset/Icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
22 changes: 21 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,24 @@
# LoopWorkspace
# LoopWorkspace (Glucose Guard)

This fork builds **Glucose Guard** on top of [LoopKit/LoopWorkspace](https://github.com/LoopKit/LoopWorkspace).

This step is **iOS only**: GitHub Actions sync from upstream Loop, apply Glucose
Guard icons and the display name, then publish to the existing TestFlight
account. Branding lives in `glucose-guard-design/` (and later in
[iDustbin/glucose-guard-design](https://github.com/iDustbin/glucose-guard-design)
when that repo exists). There is no web or Kubernetes app in this step.

For a local Xcode icon/name refresh after an upstream pull:

```
./Scripts/apply_glucose_guard_branding.sh
```

Or apply a local checkout of the design repo:

```
GLUCOSE_GUARD_DESIGN_PATH=/path/to/glucose-guard-design ./Scripts/apply_glucose_guard_branding.sh
```

The Loop app can be built using GitHub in a browser on any computer or using a Mac with Xcode.

Expand Down
118 changes: 118 additions & 0 deletions Scripts/apply_glucose_guard_branding.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
#!/usr/bin/env bash
# Pull Glucose Guard branding from iDustbin/glucose-guard-design and apply
# it to this LoopWorkspace checkout. Used after upstream LoopKit sync so
# icons and the display name survive a fork reset.
set -euo pipefail

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
DESIGN_OWNER="${GLUCOSE_GUARD_DESIGN_OWNER:-iDustbin}"
DESIGN_REPO="${GLUCOSE_GUARD_DESIGN_REPO:-glucose-guard-design}"
DESIGN_REF="${GLUCOSE_GUARD_DESIGN_REF:-main}"
LOCAL_DESIGN="${GLUCOSE_GUARD_DESIGN_PATH:-}"
CLONE_DIR=""

cleanup() {
if [[ -n "${CLONE_DIR}" && -d "${CLONE_DIR}" ]]; then
rm -rf "${CLONE_DIR}"
fi
}
trap cleanup EXIT

resolve_source() {
if [[ -n "${LOCAL_DESIGN}" ]]; then
if [[ ! -d "${LOCAL_DESIGN}/ios" ]]; then
echo "GLUCOSE_GUARD_DESIGN_PATH does not contain an ios/ directory: ${LOCAL_DESIGN}" >&2
exit 1
fi
printf '%s\n' "${LOCAL_DESIGN}"
return
fi

local bundled="${ROOT}/glucose-guard-design"
local url="https://github.com/${DESIGN_OWNER}/${DESIGN_REPO}.git"
CLONE_DIR="$(mktemp -d)"

echo "Cloning ${DESIGN_OWNER}/${DESIGN_REPO}@${DESIGN_REF}" >&2
set +e
if [[ -n "${GH_PAT:-}" ]]; then
git -c "http.extraHeader=Authorization: Bearer ${GH_PAT}" \
clone --depth 1 --branch "${DESIGN_REF}" "${url}" "${CLONE_DIR}"
else
git clone --depth 1 --branch "${DESIGN_REF}" "${url}" "${CLONE_DIR}"
fi
local clone_status=$?
set -e

if [[ "${clone_status}" -eq 0 && -d "${CLONE_DIR}/ios" ]]; then
printf '%s\n' "${CLONE_DIR}"
return
fi

echo "Remote ${DESIGN_OWNER}/${DESIGN_REPO} is not available; using bundled glucose-guard-design." >&2
rm -rf "${CLONE_DIR}"
CLONE_DIR=""
if [[ -d "${bundled}/ios" ]]; then
printf '%s\n' "${bundled}"
return
fi

echo "No Glucose Guard design source found. Create iDustbin/glucose-guard-design or set GLUCOSE_GUARD_DESIGN_PATH." >&2
exit 1
}

copy_catalog() {
local src="$1"
local dest="$2"
if [[ ! -d "${src}" ]]; then
echo "Missing asset catalog: ${src}" >&2
exit 1
fi
rm -rf "${dest}"
mkdir -p "$(dirname "${dest}")"
cp -R "${src}" "${dest}"
}

apply_display_name() {
local snippet="$1"
local xcconfig="${ROOT}/LoopConfigOverride.xcconfig"
python3 - "${snippet}" "${xcconfig}" <<'PY'
import re
import sys
from pathlib import Path

snippet = Path(sys.argv[1])
xcconfig = Path(sys.argv[2])
name = "GlucoseGuard"
if snippet.is_file():
for line in snippet.read_text(encoding="utf-8").splitlines():
stripped = line.strip()
if stripped.startswith("MAIN_APP_DISPLAY_NAME"):
_, _, value = stripped.partition("=")
candidate = value.strip()
if candidate:
name = candidate
break

text = xcconfig.read_text(encoding="utf-8") if xcconfig.exists() else ""
pattern = re.compile(r"^MAIN_APP_DISPLAY_NAME\s*=.*$", re.MULTILINE)
replacement = f"MAIN_APP_DISPLAY_NAME = {name}"
if pattern.search(text):
text = pattern.sub(replacement, text)
else:
if text and not text.endswith("\n"):
text += "\n"
text += replacement + "\n"
xcconfig.write_text(text, encoding="utf-8")
print(f"Set {replacement}")
PY
}

SRC="$(resolve_source)"
copy_catalog \
"${SRC}/ios/OverrideAssetsLoop.xcassets" \
"${ROOT}/OverrideAssetsLoop.xcassets"
copy_catalog \
"${SRC}/ios/OverrideAssetsWatchApp.xcassets" \
"${ROOT}/OverrideAssetsWatchApp.xcassets"
apply_display_name "${SRC}/ios/display_name.xcconfig"
echo "Glucose Guard branding applied from ${SRC}"
4 changes: 4 additions & 0 deletions glucose-guard-design/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.DS_Store
.idea/
.vscode/
*.log
33 changes: 33 additions & 0 deletions glucose-guard-design/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Glucose Guard Design

iOS branding for **Glucose Guard**: logo, color tokens, and Loop override app icons.

Step 1 is **iOS only**. The Loop fork
[iDustbin/LoopWorkspace](https://github.com/iDustbin/LoopWorkspace) syncs from
[LoopKit/LoopWorkspace](https://github.com/LoopKit/LoopWorkspace). GitHub Actions
then apply `ios/` (icons + display name) and publish to the existing TestFlight
account.

## Layout

- `branding/` — logo, SVG mark, color tokens
- `ios/` — `OverrideAssets*.xcassets` and `display_name.xcconfig`
- `docs/step-1.md` — what ships now vs later

## Apply to a local LoopWorkspace checkout

From the LoopWorkspace root:

```bash
./Scripts/apply_glucose_guard_branding.sh
```

Or point at this folder:

```bash
GLUCOSE_GUARD_DESIGN_PATH=/path/to/glucose-guard-design \
./Scripts/apply_glucose_guard_branding.sh
```

Until `iDustbin/glucose-guard-design` exists as its own GitHub repo, this tree
stays bundled inside the Loop fork so TestFlight still gets the Glucose Guard icon.
Binary file added glucose-guard-design/branding/app-icon-1024.png
Binary file added glucose-guard-design/branding/logo-512.png
Binary file added glucose-guard-design/branding/logo-source.png
Binary file added glucose-guard-design/branding/logo.png
11 changes: 11 additions & 0 deletions glucose-guard-design/branding/logo.svg
40 changes: 40 additions & 0 deletions glucose-guard-design/branding/tokens.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"name": "Glucose Guard",
"displayName": "GlucoseGuard",
"logo": {
"mark": "Medical cross fused with a guardian robot (head, eyes, shield torso)",
"statusRing": {
"connected": {
"color": "#22C55E",
"meaning": "CGM and insulin pump communication is working; closed loop is the goal"
},
"idle": {
"color": "#F4F4F5",
"meaning": "White ring — awaiting a live connection (placeholder in step 1)"
},
"disconnected": {
"color": "#F4333C",
"meaning": "Communication lost (shown only as a mock in the web shell)"
}
}
},
"brand": {
"red": "#F4333C",
"white": "#FFFFFF",
"black": "#0A0A0A"
},
"light": {
"background": "#FAFAFA",
"surface": "#FFFFFF",
"text": "#171717",
"muted": "#737373",
"border": "#E5E5E5"
},
"dark": {
"background": "#0A0A0A",
"surface": "#171717",
"text": "#FAFAFA",
"muted": "#A3A3A3",
"border": "#2A2A2A"
}
}
31 changes: 31 additions & 0 deletions glucose-guard-design/docs/step-1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Glucose Guard — Step 1 (iOS only)

Branding source of truth for the Loop iOS fork (`iDustbin/LoopWorkspace`).

## Implemented now

- App name: **GlucoseGuard**
- Robot-cross logo on brand red (`#F4333C`)
- iOS and watchOS override app icons
- GitHub Actions on the Loop fork pull this tree **after** syncing
`LoopKit/LoopWorkspace`, then Fastlane publishes to the existing TestFlight
account

## Not in this step

- Kubernetes / web dashboard
- Live CGM, pump, or Nightscout values
- Withings, Rex.fit, or other third-party health APIs
- Medical-person search and dataset access requests
- Food overview (owned by another company / designer)
- Custom Omnipod DASH communication patches

Omnipod DASH drops on newer InPlay/Atlas pods (especially iPhone 16 / 17e) are
handled upstream. Stay synced with LoopKit so Pod Keep Alive (Loop 3.14+)
arrives through the fork-sync workflow.

## Later

- Separate design repo on GitHub
- Web/Kubernetes shell
- CGM detail, A1C/GMI, averages
Loading