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
14 changes: 14 additions & 0 deletions .github/codeql/codeql-kotlin-compat.init.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// CodeQL 2.26.x can analyze Kotlin 2.4.0 through 2.4.19, while the production
// build must use 2.4.20-Beta1 or newer to address GHSA-r937-wjx7-w2jp.
// This init script is used only by the isolated, cache-disabled CodeQL compile.
gradle.beforeProject { project ->
project.buildscript.configurations.configureEach { configuration ->
configuration.resolutionStrategy.eachDependency { details ->
if (details.requested.group == 'org.jetbrains.kotlin' &&
details.requested.name == 'kotlin-gradle-plugin') {
details.useVersion('2.4.10')
details.because('CodeQL 2.26.x supports Kotlin versions below 2.4.20')
}
}
}
}
9 changes: 9 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,19 @@ jobs:
queries: security-extended

- name: Compile Kotlin sources
env:
# Keep the scanner-only compatibility compiler isolated from every
# persistent Gradle cache. Production builds continue to use the
# patched 2.4.20-Beta1 plugin declared in build.gradle.
GRADLE_USER_HOME: ${{ runner.temp }}/codeql-gradle-home
run: >
./gradlew
:app:compileDebugKotlin
:protocol:compileDebugKotlin
--init-script .github/codeql/codeql-kotlin-compat.init.gradle
--rerun-tasks
--no-build-cache
--no-configuration-cache
--no-daemon
--stacktrace

Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ local.properties
*.pcapng
*.csv
*.json
!/.impeccable/design.json
*.log
*.jks
*.keystore
Expand All @@ -21,6 +22,7 @@ keystore.properties
keystore.properties.*
.tmp-*/
.tmp-*
/.impeccable/review/

# Operating-system metadata
desktop.ini
Expand Down
116 changes: 116 additions & 0 deletions .impeccable/design.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
{
"schemaVersion": 2,
"generatedAt": "2026-08-16T23:16:52+09:00",
"title": "Design System: GF2logger",
"extensions": {
"colorMeta": {
"brand-orange": {
"role": "primary",
"displayName": "Muted Signal Orange",
"canonical": "#D7824B",
"tonalRamp": ["#3C2113", "#65351D", "#914D29", "#BC6838", "#D7824B", "#E8A477", "#F2C9AD", "#FBEDE2"]
},
"warm-paper": {
"role": "neutral",
"displayName": "Warm Paper",
"canonical": "#F7F4EF",
"tonalRamp": ["#272521", "#4A4741", "#6F6A62", "#969087", "#BBB5AC", "#D9D4CC", "#ECE8E1", "#F7F4EF"]
},
"soft-charcoal": {
"role": "neutral",
"displayName": "Soft Charcoal",
"canonical": "#20211F",
"tonalRamp": ["#111210", "#20211F", "#353632", "#555650", "#777871", "#9D9E96", "#C7C7C0", "#F0F0EA"]
},
"capture-green": {
"role": "tertiary",
"displayName": "Capture Green",
"canonical": "#4B7955",
"tonalRamp": ["#17261A", "#294330", "#3C6245", "#4B7955", "#6B966F", "#91B496", "#BDD2BF", "#E9F1E8"]
},
"stop-red": {
"role": "tertiary",
"displayName": "Stop Red",
"canonical": "#A85258",
"tonalRamp": ["#351619", "#5A292E", "#823E44", "#A85258", "#C5777C", "#D99DA0", "#EBC5C7", "#F9ECEC"]
}
},
"typographyMeta": {
"headline": { "displayName": "Headline", "purpose": "Screen and onboarding titles." },
"title": { "displayName": "Title", "purpose": "Sections, destinations, and prominent states." },
"body": { "displayName": "Body", "purpose": "Actions and operational explanations." },
"label": { "displayName": "Label", "purpose": "Navigation, metadata, and supporting text." }
},
"shadows": [],
"motion": [],
"breakpoints": []
},
"components": [
{
"name": "Primary Button",
"kind": "button",
"refersTo": "button-primary",
"description": "Commitment action such as Next or One-time Capture.",
"html": "<button class=\"ds-btn-primary\">NEXT</button>",
"css": ".ds-btn-primary { min-height: 48px; padding: 0 16px; border: 0; border-radius: 14px; background: #D7824B; color: #25231F; font: 600 14px sans-serif; } .ds-btn-primary:hover { background: #C8733D; } .ds-btn-primary:focus-visible { outline: 2px solid #7D3F1E; outline-offset: 2px; } .ds-btn-primary:active { background: #C8733D; }"
},
{
"name": "Quiet List Row",
"kind": "custom",
"refersTo": "list-row",
"description": "Compact utility or settings action with optional supporting copy.",
"html": "<div class=\"ds-list-row\"><span><strong>Packet viewer</strong><small>Open saved packet data</small></span><b aria-hidden=\"true\">›</b></div>",
"css": ".ds-list-row { min-height: 60px; padding: 6px 8px; display: flex; align-items: center; justify-content: space-between; border-bottom: 1px solid #DED8CF; background: #FFFCF8; color: #25231F; font: 14px sans-serif; } .ds-list-row span { display: grid; gap: 2px; } .ds-list-row small { color: #6C665F; font-size: 12px; } .ds-list-row:focus-within { outline: 2px solid #D7824B; outline-offset: -2px; }"
},
{
"name": "Segmented Choice",
"kind": "chip",
"description": "Native semantic choice group for language and theme.",
"html": "<div class=\"ds-segment\" role=\"radiogroup\"><button class=\"ds-segment-active\" role=\"radio\" aria-checked=\"true\">한국어</button><button role=\"radio\" aria-checked=\"false\">English</button></div>",
"css": ".ds-segment { min-height: 54px; padding: 3px; display: flex; border-radius: 14px; background: #EEEAE3; } .ds-segment button { flex: 1; min-height: 48px; border: 0; border-radius: 11px; background: transparent; color: #25231F; font: 600 14px sans-serif; } .ds-segment .ds-segment-active { background: #F6E4D7; color: #7D3F1E; } .ds-segment button:focus-visible { outline: 2px solid #D7824B; outline-offset: -2px; }"
},
{
"name": "Capture Status Panel",
"kind": "card",
"description": "The primary operational group for state, target, and capture actions.",
"html": "<section class=\"ds-capture\"><small>● Capture status</small><h2>Ready</h2><p>Capture is stopped</p><div><button>Prepare</button><button class=\"ds-capture-primary\">One-time Capture</button><button disabled>Stop</button></div></section>",
"css": ".ds-capture { padding: 16px; border: 1px solid #44453F; border-radius: 16px; background: #292A27; color: #F5F0E8; font-family: sans-serif; } .ds-capture small { color: #E49B68; } .ds-capture h2 { margin: 12px 0 4px; color: #A9C9A8; } .ds-capture p { color: #BDB6AC; } .ds-capture div { display: flex; gap: 8px; } .ds-capture button { flex: 1; min-height: 48px; border: 1px solid #858077; border-radius: 14px; background: #33342F; color: #F5F0E8; } .ds-capture .ds-capture-primary { border: 0; background: #E49B68; color: #2B1D14; } .ds-capture button:focus-visible { outline: 2px solid #E49B68; outline-offset: 2px; } .ds-capture button:disabled { opacity: .55; }"
},
{
"name": "Primary Bottom Navigation",
"kind": "nav",
"refersTo": "bottom-navigation",
"description": "The only persistent navigation, limited to Home, Platoon, and Weekly.",
"html": "<nav class=\"ds-bottom-nav\"><button class=\"ds-nav-active\">⌂<span>Home</span></button><button>♟<span>Platoon</span></button><button>▣<span>Weekly</span></button></nav>",
"css": ".ds-bottom-nav { height: 64px; display: flex; border-top: 1px solid #DED8CF; background: #FFFCF8; } .ds-bottom-nav button { flex: 1; border: 0; background: transparent; color: #6C665F; display: grid; place-content: center; gap: 2px; font: 500 11px sans-serif; } .ds-bottom-nav .ds-nav-active { color: #D7824B; } .ds-bottom-nav button:focus-visible { outline: 2px solid #D7824B; outline-offset: -2px; }"
}
],
"narrative": {
"northStar": "The Evidence Field Instrument",
"overview": "GF2logger should feel like a quiet, dependable instrument used during and after a game session. Its hierarchy is operational rather than decorative: capture state comes first, Platoon and Weekly are unmistakable destinations, and data utilities stay compact and calm. Warm paper and soft charcoal replace sterile white and absolute black. Muted orange is rare enough to remain meaningful, while green and red communicate capture and destructive states only when paired with text or an icon.",
"keyCharacteristics": [
"Compact, status-led Android layouts.",
"Warm neutral fields with one restrained brand accent.",
"Flat tonal grouping, hairlines, and minimal shadow.",
"Equal care for English, Korean, and enlarged system text."
],
"rules": [
{ "name": "The One Accent Rule", "body": "Orange marks brand, selection, or commitment; it does not fill ordinary utility rows.", "section": "colors" },
{ "name": "The State Is a Sentence Rule", "body": "Green, red, and warning tones never carry meaning alone.", "section": "colors" },
{ "name": "The System Scale Rule", "body": "Never replace scalable text with text baked into an image.", "section": "typography" },
{ "name": "The Flat Instrument Rule", "body": "A surface must earn separation through function before receiving a container.", "section": "elevation" }
],
"dos": [
"Do keep capture state and next actions visible without scrolling on the primary screen.",
"Do preserve 48dp targets, native checked semantics, and Android Back behavior.",
"Do verify English, Korean, light/dark themes, system bars, and enlarged text on a physical device.",
"Do use orange sparingly for primary action and selection."
],
"donts": [
"Don't use absolute black, stark white, gradients, glass effects, decorative blur, or deep shadows.",
"Don't turn every row into a large card or invent mockup-only settings.",
"Don't use color as the only status signal.",
"Don't move parser, capture, repository, or report policy into Activities while changing presentation."
]
}
}
69 changes: 69 additions & 0 deletions .interface-design/system.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# GF2logger interface system

## Direction

Use the approved three-screen composition recorded in `PRODUCT.md` as the
visual ground truth. The product should feel like a compact field instrument:
quiet, legible, evidence-led, and unmistakably Android rather than a generic
card stack.

## Layout grammar

- Use a 4dp base grid. Default screen inset is 16dp; related copy is separated
by 4dp or 8dp; sections are separated by 16dp or 24dp.
- Keep every touch target at least 48dp high, while using inset fills and
hairlines so the visible control can remain compact.
- Home is status-led: app bar, capture status, two key destinations, quiet
utilities, recent evidence, then the persistent Home/Platoon/Weekly bar.
- Settings uses a compact back app bar followed by grouped list rows. Do not
turn every setting into a card.
- Onboarding uses a dark editorial field: top actions, emblem, title and short
explanation, progress, feature list, bottom Previous/Next actions, step label.
- Preserve ordinary Android Back behavior. Bottom navigation is reserved for
Home, Platoon, and Weekly.

## Color roles

- Background: warm off-white in light mode; soft near-black charcoal in dark.
- Surface: a subtle one-step tonal lift from the background.
- Primary text: warm ink/ivory. Secondary text is lower-contrast but AA legible.
- Brand/primary: muted orange, used sparingly for the selected destination,
commitment actions, and the emblem's star.
- Success/capture: desaturated green with explicit status text or an icon.
- Stop/destructive/failure: softened red with explicit text or an icon.
- Avoid absolute black/white, gradients, glass effects, decorative blur, and
deep shadows.

## Type

- Use the Android system sans family so English and Korean share consistent
metrics and device font scaling.
- Screen title: 22-24sp medium/bold.
- Section title: 15-17sp medium.
- Body/action label: 14-16sp regular/medium.
- Supporting text and metadata: 12-13sp regular.
- Keep centered copy to onboarding headlines and short descriptions; operational
and settings copy is start-aligned.

## Component rules

- Header icon actions: 48dp hit area with a quiet tonal or transparent surface.
- Capture status: a bounded outlined/tonal panel with a small label, prominent
state, concise detail, and distinct Start/One-time/Stop actions.
- Feature destinations: paired compact rows/cards with icon, title, supporting
text, and chevron. Orange marks their importance without filling the screen.
- Utility/settings rows: 52-60dp, title plus optional supporting line, trailing
chevron or native checkbox/switch. Use dividers or common-region spacing.
- Bottom navigation: three equal 56-64dp destinations; selected state uses
orange icon/label and unselected destinations remain neutral.
- Onboarding: a compact language action remains available because locale is a
required first-use decision; Skip is always visible.

## Accessibility and state

- Controls expose native semantics and readable content descriptions.
- Color never carries state alone. Pair capture, selection, warning, and error
colors with text and/or icons.
- Pressed, disabled, selected, and busy states must remain visually distinct.
- Review English and Korean on the physical phone, including onboarding pages,
light Settings, dark Home, system bars, and enlarged font behavior.
31 changes: 31 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,37 @@

All notable changes to mobileGF2logger are documented here.

## 2.3.0 - 2026-08-17

### Added

- Add a five-page first-launch guide for Main, Settings, Platoon management,
weekly-table controls, and parsed-packet pages. The bilingual segmented
selector persists its language choice immediately, while Skip and Get
started permanently complete onboarding for that installation.
- Add System, Light, and Dark appearance choices to Settings and preserve the
selected theme in complete backups.

### Changed

- Refresh every Activity with a compact, black-and-white-first interface,
restrained accent color, flatter geometry, accessible touch targets, and
theme-aware packet and weekly-table cells.
- Refine the bilingual onboarding copy around the actual capture, evidence,
backup, Discord, and weekly-table workflows, enlarge its page icons, and use
compact `1/5` progress labels in both languages.
- Preserve existing unified settings while migrating upgraded v2.2.0 installs
past the first-use guide; fresh installs still receive onboarding once.
- Extend complete-backup settings to schema v2 while restoring v1 backups with
safe theme and onboarding defaults.

### Fixed

- Explicitly resolve the build-only Kotlin Gradle Plugin to patched
`2.4.20-Beta1`, replacing the vulnerable `2.2.10` version pulled transitively
by Android Gradle Plugin 9.3.1 and giving Dependabot a direct manifest entry
it can update in the future.

## 2.2.0 - 2026-08-11

### Added
Expand Down
Loading
Loading