Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
cec7fb6
chore(deps): bump MapLibre to 6.28.0
Avi0n Jul 28, 2026
7232a01
feat(remote-nodes): size neighbor key hex by hash
Avi0n Aug 2, 2026
8fbc3ce
feat(contacts): debounced advert delta sync
Avi0n Aug 2, 2026
69c42d7
fix(contacts): prune only on complete snapshots
Avi0n Aug 3, 2026
570d27a
Bump version to 1.4.0
Avi0n Aug 3, 2026
9d46034
feat(contacts): stamp lastHeard on mesh liveness
Avi0n Aug 3, 2026
07d7dd3
feat(chats): show multi-match flood regions
Avi0n Aug 4, 2026
d311e93
fix(chats): attach repeats after a node rename
Avi0n Aug 14, 2026
edc11e7
fix(remote-nodes): rewrite clock sync to time
Avi0n Aug 14, 2026
a07e0ed
fix(remote-nodes): compare clocks in device info
Avi0n Aug 14, 2026
d96e419
fix(repeaters): add region as flood-allowed
Avi0n Aug 14, 2026
b64ec99
fix(settings): defer region add until the alert dismisses
Avi0n Aug 14, 2026
57397a3
ui(regions): label * as unscoped
Avi0n Aug 14, 2026
4b9b6c4
fix(chats): don't yank a scrolled-up thread
Avi0n Aug 14, 2026
dd948aa
fix(chats): keep timeline across reconnect
Avi0n Aug 18, 2026
fa91bdc
chore(sim): seed multi-match flood regions
Avi0n Aug 19, 2026
d706ed0
fix(ble): keep auto-reconnect while out of range
Avi0n Aug 20, 2026
80f410a
feat(contacts): crop profile picture before saving (#397)
hansimgamr Aug 20, 2026
d91b2c8
fix(contacts): crop clamp, iPad menu, list refresh
Avi0n Aug 20, 2026
69e6a2a
fix(contacts): refresh list after nickname edit
Avi0n Aug 20, 2026
a3dfe07
feat(chats): show avatars on incoming clusters
Avi0n Aug 21, 2026
ccad1ea
feat(chats): fly cluster-end avatar to new tail
Avi0n Aug 21, 2026
5977b50
feat(chats): plot channel sender on path map
Avi0n Aug 21, 2026
2cc95f5
fix(settings): show contact info while typing
Avi0n Aug 22, 2026
d5e44d2
feat(l10n): add Portuguese (Portugal)
Avi0n Aug 23, 2026
c3726ce
fix(backup): fetch leftover flood sentinels
Avi0n Aug 23, 2026
fee5d71
fix(contacts): fetch leftover flood sentinels
Avi0n Aug 23, 2026
6f15948
feat(chats): show fallback ? on repeat details
Avi0n Aug 23, 2026
1e0ced6
feat(wifi): accept hostnames when connecting
Avi0n Aug 23, 2026
5813a47
fix(make): show progress while tests run
Avi0n Aug 24, 2026
417690b
fix(chats): cap first-page size on huge unread
Avi0n Aug 24, 2026
337ebc0
fix(make): skip simctl diagnose after tests
Avi0n Aug 24, 2026
8501669
feat(chats): show failed-send badge on list rows
Avi0n Aug 24, 2026
ea7b58d
test(contacts): keep avatars on batch save and reseed
Avi0n Aug 24, 2026
90ec929
test(chats): pin failed-send mark-seen isolation
Avi0n Aug 24, 2026
371a834
fix(chats): hold compose lift during swipe-back
Avi0n Aug 24, 2026
d894e64
fix(settings): radio menu uses settings stack
Avi0n Aug 24, 2026
1a28e10
feat(chats): add on-device message translation
Avi0n Aug 25, 2026
63ee95a
fix(ci): close PRs after injecting checklist
Avi0n Aug 25, 2026
b52da3d
fix(chats): sibling overlay for sheet translate
Avi0n Aug 27, 2026
e1f61b8
feat(chats): overlay fallback when session fails
Avi0n Aug 28, 2026
12ee6c8
fix(chats): hide translate on outgoing messages
Avi0n Aug 28, 2026
0763e77
feat(repeaters): add default scope picker
Avi0n Aug 28, 2026
93b50ae
fix(l10n): revise pt-PT translation
zadoke Aug 28, 2026
a22d46a
Merge pull request #413 from zadoke/dev
Avi0n Aug 28, 2026
55a3192
fix(l10n): match pt-PT default scope to #413
Avi0n Aug 28, 2026
8a9d84f
fix(sim): keep contact avatars on reseed
Avi0n Aug 30, 2026
24b8da3
test(ble): poll watchdog natural exit
Avi0n Aug 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
13 changes: 6 additions & 7 deletions .github/workflows/pr-checklist.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ jobs:
const BODY_MARKER = '<!-- pr-checklist-template -->';

// PRs opened via the API/CLI (incl. AI agents) bypass the repository
// template, so the checklist never appears. When it is absent we inject
// this into the body once; editing the body re-fires this workflow,
// which then enforces the checkbox state.
// template, so the checklist never appears. Inject it so the
// contributor has boxes to check; GITHUB_TOKEN body edits do not
// re-fire this workflow, so the same run must also close below.
const TEMPLATE = [
BODY_MARKER,
'## Tested on',
Expand Down Expand Up @@ -78,17 +78,16 @@ jobs:
const common = { owner: context.repo.owner, repo: context.repo.repo, issue_number: pr.number };

// The checklist is partly or wholly absent (template was bypassed).
// Inject it once so the contributor actually sees the boxes; the
// resulting body edit re-fires this workflow to enforce them.
// Inject it so the contributor sees the boxes, then fall through and
// close. A later human checkbox edit still retriggers `edited`.
if (pr.state === 'open' && !allPresent && !body.includes(BODY_MARKER)) {
await github.rest.pulls.update({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pr.number,
body: body ? `${body}\n\n${TEMPLATE}` : TEMPLATE,
});
core.info(`Injected checklist template into PR #${pr.number}; awaiting completion.`);
return;
core.info(`Injected checklist template into PR #${pr.number}.`);
}

// Was this PR previously closed by the bot? Only those are eligible for auto-reopen.
Expand Down
14 changes: 4 additions & 10 deletions MC1/Intents/MessageTargetResolution.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,14 @@ import MC1Services

// MARK: - Scope resolution

/// The radio and persistence store an intent query reads from. Resolves the
/// store explicitly because pickers populate while disconnected and in a
/// cold/background context with no live `ServiceContainer`: when connected the
/// live `dataStore`, otherwise a standalone store over the same open container.
/// A `nil` current radio (no connection and nothing last-connected, or a
/// pre-launch bridge with no `AppState`) yields nil, which every caller maps to
/// an empty result rather than an error.
/// The radio and persistence store an intent query reads from. Uses the
/// process-lifetime store on `ConnectionManager` because pickers populate
/// while disconnected. A `nil` radio yields nil; callers map that to empty.
@MainActor
func currentRadioScope(_ bridge: IntentBridge) -> (radioID: UUID, store: PersistenceStore)? {
guard let appState = bridge.appState,
let radioID = appState.currentRadioID else { return nil }
let store = appState.services?.dataStore
?? appState.connectionManager.createStandalonePersistenceStore()
return (radioID, store)
return (radioID, appState.connectionManager.persistenceStore)
}

// MARK: - Channel resolution
Expand Down
42 changes: 42 additions & 0 deletions MC1/Resources/AppShortcuts.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@
"value" : "Wyślij ogłoszenie w ${applicationName}"
}
},
"pt" : {
"stringUnit" : {
"state" : "translated",
"value" : "Enviar um Advert em ${applicationName}"
}
},
"ru" : {
"stringUnit" : {
"state" : "translated",
Expand Down Expand Up @@ -101,6 +107,12 @@
"value" : "Wyślij ogłoszenie ${reach} w ${applicationName}"
}
},
"pt" : {
"stringUnit" : {
"state" : "translated",
"value" : "Enviar um Advert ${reach} em ${applicationName}"
}
},
"ru" : {
"stringUnit" : {
"state" : "translated",
Expand Down Expand Up @@ -161,6 +173,12 @@
"value" : "Sprawdź stan radia w ${applicationName}"
}
},
"pt" : {
"stringUnit" : {
"state" : "translated",
"value" : "Verificar o estado do rádio em ${applicationName}"
}
},
"ru" : {
"stringUnit" : {
"state" : "translated",
Expand Down Expand Up @@ -221,6 +239,12 @@
"value" : "Czy moje radio jest połączone w ${applicationName}"
}
},
"pt" : {
"stringUnit" : {
"state" : "translated",
"value" : "O meu rádio está ligado em ${applicationName}?"
}
},
"ru" : {
"stringUnit" : {
"state" : "translated",
Expand Down Expand Up @@ -281,6 +305,12 @@
"value" : "Wyślij wiadomość do ${target} w ${applicationName}"
}
},
"pt" : {
"stringUnit" : {
"state" : "translated",
"value" : "Enviar uma mensagem a ${target} em ${applicationName}"
}
},
"ru" : {
"stringUnit" : {
"state" : "translated",
Expand Down Expand Up @@ -341,6 +371,12 @@
"value" : "Wyślij wiadomość w ${applicationName}"
}
},
"pt" : {
"stringUnit" : {
"state" : "translated",
"value" : "Enviar uma mensagem em ${applicationName}"
}
},
"ru" : {
"stringUnit" : {
"state" : "translated",
Expand Down Expand Up @@ -401,6 +437,12 @@
"value" : "Jaki jest poziom baterii radia w ${applicationName}"
}
},
"pt" : {
"stringUnit" : {
"state" : "translated",
"value" : "Qual é a bateria do meu rádio em ${applicationName}?"
}
},
"ru" : {
"stringUnit" : {
"state" : "translated",
Expand Down
Loading
Loading