The DB directory came from getApplicationSupportDirectory(), which on Windows
is derived from the executable's Company/Product version metadata. Two builds
with different metadata (or a future rebrand) resolved DIFFERENT %APPDATA%
folders and read DIFFERENT databases, so a user's history appeared to vanish
when they ran a different build.
Pin the desktop DB to a constant path (Windows: %APPDATA%\Offband MeshCore;
Linux pinned too, its support dir derives from the exe name). On first run at
the pinned location, migrate an existing DB in via SQLite VACUUM INTO (a
consistent snapshot that is safe even under a concurrent writer), choosing the
DB from the known canonical locations first and falling back to a bounded
scan of the app-data roots (no name blocklist) so a DB under an unknown
folder is still found. On any snapshot failure it aborts cleanly, leaving the
source intact and opening a fresh DB - never a raw file copy of a live WAL DB.
Adds sqlite3 as a direct dependency (pinned to drift 2.34.2's resolved 3.5.0).
Tests cover source selection, the folder-agnostic scan, and the snapshot
happy + abort paths.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
drift_flutter's native default is getApplicationDocumentsDirectory(), which on
Windows resolves to the user's Documents folder - redirected into OneDrive on
most machines (verified: drift_flutter 0.3.1 connect.dart). A live SQLite file
syncing to OneDrive risks lock contention and corruption, and it is simply the
wrong place for app data.
The DB now opens in getApplicationSupportDirectory() (%APPDATA% on Windows),
the same place SharedPreferences already lives, so all app data sits together.
Existing installs already have a DB in the old location, so opening a fresh one
there would abandon their migrated history. _appSupportDatabaseDirectory()
relocates it once on first run: it moves offband_store.sqlite and its -wal/-shm
sidecars from the documents dir to the support dir before drift opens, and
never deletes a source without a successful copy. If relocation fails it is
logged loudly and a fresh DB is created, with the migration re-running from
SharedPreferences rather than silently losing anything.
Web is unaffected: path_provider has no web backend and drift ignores
databaseDirectory there, using OPFS/IndexedDB.
Adds `path` as a direct dependency (was transitive).
flutter analyze clean, tests pass.
Owner asked whether the web assets must be re-downloaded on every drift bump.
They do not - the version can be pinned - but doing that safely needed three
changes, because the failure mode is silent.
1. drift and drift_flutter are pinned EXACTLY (2.34.2 / 0.3.1), no caret. The
committed web assets are built for a specific drift release, so a caret
would let pub resolve a newer drift than the shipped binaries and break the
web build with no signal at compile time.
2. pubspec.lock is now committed (removed from .gitignore). It was ignored,
which for an application means resolution can differ between machines and
CI. That undermines the pin: the assets are matched against the RESOLVED
version, so resolution has to be reproducible. Owner-authorized, and it is
a repo-wide change rather than a storage-only one.
3. New test asserting the shipped assets match the resolved drift version,
plus that both files exist and the wasm really starts with the WebAssembly
magic bytes. Verified in both directions: it passes when matched and fails
loudly with re-download instructions when skewed.
Without (3) a stale asset compiles, deploys, and only fails in the user's
browser - the exact silent-failure class SAFELANE 6 forbids and that produced
#333 earlier.
Upgrading drift is now a deliberate step: bump the pin, re-download both
assets, update web/drift_assets.version. The test fails until you do.
flutter analyze clean, tests pass.
we were only deleting channels and messages on device and the in app db would persist
this caused weird messages to later show up in other channels as they were deleted and
added due to the fact we store messages by channel index(slot #)
- Reduce reaction payload from ~44 bytes to 9 bytes (5x smaller)
- Use 4-char hex hash (timestamp + sender + first 5 chars) for message ID
- Use 2-char hex emoji index instead of multi-byte UTF-8 emoji
- Format: r:HASH:INDEX (e.g., r:a1b2:00)
- For 1:1 chats, sender is implicit (null) for shorter hash
- Prevent users from reacting to their own messages
- Add room server reaction support with sender identification
- Make emoji lists public in EmojiPicker for shared indexing
- Add 💪 and 🚀 emojis to picker
- Add comprehensive unit tests for reaction helpers
- Update minor dependencies
- Added flutter_linkify package to auto-detect and linkify URLs in chat messages.
- Implemented LinkHandler class to manage link tap confirmations and URL launching.
- Updated chat_screen.dart to use Linkify for displaying message text with links.
- Registered url_launcher plugin for handling URL launches across platforms.
- Updated pubspec.yaml and pubspec.lock to include new dependencies.
- Cleaned up untranslated.json by removing unused translations.
- Implement Community model for managing community data, including secret handling and PSK derivation.
- Create CommunityQrScannerScreen for scanning and joining communities via QR codes.
- Develop CommunityStore for persisting community data using SharedPreferences.
- Introduce QrCodeDisplay widget for displaying QR codes with customizable options.
- Add QrScannerWidget for reusable QR code scanning functionality with validation and controls.
- Introduced a new extension for localization in Flutter with `LocalizationExtension` in `l10n.dart`.
- Added a Python script `translate.py` for translating ARB/JSON localization files using a local Ollama model, preserving keys and placeholders, and handling ICU format rules.
Open-source Flutter client for MeshCore LoRa mesh networking devices.
Features:
- BLE device scanning and connection
- Nordic UART Service (NUS) integration
- Material 3 design with system theme support
- Provider-based state management
- Placeholder screens for chat, contacts, and settings
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>