Commit graph

258 commits

Author SHA1 Message Date
Adam Brown
b4e4a08702
Story Ideas: account-level idea capture with sync (#720)
Quick-capture story ideas as tagged markdown blobs in a new Project
Selection tab, stored one file per idea in .ideas/ and promotable into
a project. Offline-first; syncs as a phase inside the account sync
session (shape-agnostic server storage, hash-baseline conflicts,
tombstone/outbox deletion, ideasStateHash skip for unchanged sets).
Unifies idea + project tag suggestions behind AccountTagService.
2026-07-05 01:49:04 -07:00
Wavesonics
8bcd696761
Add startup logging: build/environment banner and startup breadcrumbs
Log a single identifying line as the first line on every platform:
version plus OS/runtime, and on desktop the display server (Wayland/X11
+ DE) and Skia renderApi. Makes user-submitted logs self-describing.

Banner is expect/actual in :common, wired into the desktop, Android, and
iOS startup entry points. Also adds INFO breadcrumbs across desktop
startup so a stall localizes to a stage.
2026-07-01 22:04:11 -07:00
Adam Brown
092652edfa Add RTF import for new projects
Adds RTF as an import format alongside Markdown. RTF has no headings, so
the importer collects each paragraph with its formatting and splits into
scenes by one of three user-chosen strategies: formatting (outline level
/ font size / bold), a chapter-heading regex, or a single scene.

Shared scene/group folding is extracted into ImportStructure so both
importers reuse it, and a StoryImporterRegistry routes by file extension.
Importers now take ByteArray so RTF bytes aren't decoded prematurely.

Markdown gains an Auto detection mode (the new default) that reads a lone
leading heading as the project title and picks the chapter level by
frequency. The create-dialog help affordance becomes an icon button.
2026-06-25 00:15:37 -07:00
Adam Brown
4e0cee48c8 Move story import into the project creation flow
Relocate "Import Story" from the Project Home screen to the Create
Project dialog. An "Import" action in the create dialog opens the file
picker and import dialog; confirming creates the project (name derived
from the file name, editable and validated) and splits the file into
scenes by running the existing ImportStoryUseCase in a temporary
project scope.

- Move import state/handlers from ProjectHome(Component) to
  ProjectsList(Component)
- Move ImportStoryDialog + ImportFilePicker (expect/3 actuals) to the
  projectselection package; picker is now callback-based
- Add an optional mastheadAction slot to FormDialog for the Import button
- Add an editable, validated project-name field to the import dialog
- Add ProjectsListComponent tests for the import handlers and the
  create-failure path
2026-06-24 17:29:18 -07:00
Adam Brown
3e9ad32109 Unexport AddNoteActivity and filter obscured touches (F-8)
AddNoteActivity was exported with no permission, so any installed app could pop the Add Note dialog over the user pre-locked to a chosen project; a tapjacking overlay tricking a Save tap would write a note and push it to the sync server. It is only ever launched in-process (ProjectSelectActivity) or via the home-screen widgets' PendingIntents, neither of which needs export. Set android:exported=false in both manifests and filter touches delivered while the window is obscured.
2026-06-24 16:09:47 -07:00
Adam Brown
5b377eaf83 Stop ProjectRootActivity from opening caller-supplied project paths
ProjectRootActivity was exported and resolveProjectDef deserialized a caller-supplied ProjectDef whose free-form path was used verbatim for all project file I/O, letting any installed app root the editor at an attacker-controlled directory (confused deputy, CWE-926/CWE-22). Resolve the target project by name against on-disk projects only, drop the serialized EXTRA_PROJECT path extra, and mark the activity exported=false; it is only launched in-process via explicit intents and PendingIntents from widgets and shortcuts.
2026-06-24 14:14:52 -07:00
Adam Brown
47e5f9bf95
Fix flaky editor instrumented tests by re-injecting until the edit lands (#632)
The markdown/scene editor consumes hardware key events and reports edits
through an async flow. sendStringSync could fire before the field had focus
(or before the editor's editOperations collector started), silently dropping
the keystrokes so the observed change never happened and waitUntil timed out.
A longer timeout can't recover dropped input.

typeIntoEditor now re-focuses and re-injects until a caller-supplied
propagated() lambda confirms the change, or a deadline throws a clear error.
NotesWorkflowTest and SceneEditorWorkflowTest pass their existing change
signal and drop their redundant waitUntil blocks.
2026-06-22 11:43:00 -07:00
Adam Brown
85c7913eba Strip dep info blob from fdroid builds 2026-06-22 02:08:29 -07:00
Adam Brown
b44c315431
Target Android API 37 (Android 17)
Bump compileSdk/targetSdk to 37 and AGP to 9.1.1 (9.0.x maxes out at
API 36.1 and can't resolve the minor-versioned android-37.0 platform).

Handle the two breaking behavior changes for API 37 targets:

- Cleartext traffic: usesCleartextTraffic is now ignored without a
  network security config. Self-hosted servers can be plain HTTP
  (ServerSettings.ssl = false), so add network_security_config.xml
  permitting cleartext and reference it from both manifests.

- Local network access: declare ACCESS_LOCAL_NETWORK and request it at
  runtime via a new expect/actual RequestLocalNetworkPermission,
  triggered when the server-setup dialog opens so the grant resolves
  before any LAN connection. No-op on desktop/iOS.
2026-06-07 23:57:01 -07:00
Adam Brown
a2998adcba
Re-enable public-storage projects on F-Droid builds (#568)
Restores the "store projects in public storage" feature, gated to F-Droid builds (the required MANAGE_EXTERNAL_STORAGE permission is disallowed on Google Play).

- Expose the build channel at runtime via BuildConfig.FDROID in the common module.
- Declare the storage permissions only in src/fdroid/AndroidManifest.xml, swapped in for F-Droid builds.
- Restore the storage-location toggle + file-access UI, gated on BuildConfig.FDROID; reconcile the toggle with the real location on open.
- Build the GitHub release APK as the F-Droid flavor.
- Extract the directory move into a tested FileSystem.moveDirectory() helper (fixes the same-path data-loss crash; runs off the UI thread).
- Read the fdroid flag consistently across settings.gradle.kts and module scripts.
- Document the F-Droid build flag in DEVELOPMENT.md.
2026-06-07 19:16:42 -07:00
Adam Brown
eca76803fa
Fix flaky NotesWorkflowTest create-note race (#562)
* Fix flaky NotesWorkflowTest create-note race

createNoteThenOpenIt clicked the create confirm button immediately after
typeIntoEditor. The markdown editor reports text changes through an async
editOperations flow that waitForIdle() doesn't await, so noteText could
still be empty at confirm time -> createNote("") returns NoteError.EMPTY,
the create screen never dismisses, and the browse grid's note-card- nodes
never reappear -> 10s timeout.

Wait for the word/char counter to reflect the typed body before confirming.
Tag the counter (NOTES_CREATE_META_TAG) and add a textOf() harness helper to
read it. Verified on emulator (4/4 runs green).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Guard project list load against a concurrently-deleted project

loadProjectList lists project dirs then reads each one's metadata in a
parallelMap. If a project is deleted between the listing and the read
(another window, or a refresh racing a delete), loadMetadata's recovery
path tries to recreate project.toml in a directory that no longer exists
and throws FileNotFoundException from inside its own catch block, failing
the entire list load (and crashing the instrumented test that exposed it).

Catch the per-project load failure and skip the vanished project - this
also makes the previously-dead `if (metadata != null)` branch live, which
was the original intent.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 16:50:47 -07:00
Adam Brown
d1e265a44c
Add Foundation primitives tier; rename Id/Sync/Settings repos (#558)
* Rename IdRepository to IdAllocator
It is a special foundational primative

* Rename SyncDataRepository to SyncJournal
It is a special foundational primative

* Rename GlobalSettingsRepository to GlobalSettingsStore
It is a special foundational primitive

* docs: add Foundation primitives tier to the architecture doc

Document IdAllocator, SyncJournal, and GlobalSettingsStore as a fixed set of
stateful, cross-cutting primitives that the whole data layer may depend on —
acyclic leaves (GlobalSettingsStore <- SyncJournal <- IdAllocator) that named
the dependency reality instead of treating it as a no-sibling violation.
2026-06-06 01:17:13 -07:00
Adam Brown
04a9772d03
Expand Android instrumented UI test coverage across editor screens (#553)
Add a reusable EditorTestHarness (seed a project via Koin, launch straight
into ProjectRootActivity, navigate, tear down without racing the scope flush)
and one happy-path instrumented test per feature area: navigation smoke,
scene list/editor, notes, encyclopedia, timeline, project home, and global
search.

To make the UI addressable, add optional testTag params to shared design-system
components (FormField, MarkdownEditField, HdHairlineField/TagField/SearchField/
TypePicker, HdBottomBar/HdNavRail) and colocated testTag consts on the relevant
screens. The custom text editor consumes key events rather than Compose SetText
semantics, so the harness types into it via injected keystrokes.

All 9 new tests pass on an api-34 emulator.
2026-06-04 00:20:52 -07:00
Adam Brown
da516e1772
Android e2e UI test harness (on-device project lifecycle) (#516)
ProjectLifecycleTest launches the real ProjectSelectActivity, creates a project,
waits for it to appear in the list, and confirms opening it launches
ProjectRootActivity (via ActivityMonitor). Cleans up in @After.

- Wire jetbrains-compose ui-test-junit4 into the androidTest source set.
- Tag the create-project affordance (CreateProjectButtonTestTag); "Create
  Project" otherwise appears as three separate on-screen texts.
- Run the instrumented suite on an emulator in CI (android-emulator-runner) with
  AVD snapshot caching.
- Convert HashTest from JUnit Jupiter to JUnit4 so the AndroidJUnit4 runner can
  execute it on-device (it had "no runnable methods" otherwise); use assertEquals
  since assert() is a no-op when assertions are disabled on a device. It now
  verifies EntityHasher's golden vector on Android ART.
- Fix a scope-close crash: getSceneBufferDirectory used a non-recursive
  createDirectory, so closing a project whose scenes/ dir is absent threw on the
  teardown path and crashed the process. Use createDirectories (matching its
  siblings) and order the test teardown so it doesn't delete the project mid-close.
2026-06-03 22:11:14 -07:00
Adam Brown
73185ee7b2
Compile the Android instrumented tests in CI (#518)
buildDebug never touched the androidTest source set, so a stale instrumented
test could - and did - rot unnoticed: HashTest stopped compiling after `tags`
was added to EntityHasher.hashNote.

- Add a :android:assembleDebugAndroidTest step: a fast, emulator-free gate that
  compiles + packages the androidTest source set on every PR.
- Fix the stale HashTest to match the current hashNote signature.
- Exclude the duplicate META-INF/LICENSE files the test deps ship so the
  androidTest APK packages.
2026-05-28 23:07:18 -07:00
Adam Brown
ea17b263d5
Fix IllegalStateException: closed race in FileLogger (#524)
The log-consumer coroutine could write to appendBuffer after another
thread (the logging framework / shutdown) had already closed it, e.g.
during CoroutineScope cancellation, throwing IllegalStateException: closed.

Make the single consumer coroutine the sole owner of the sink: it writes,
flushes, and closes appendBuffer (the latter in a finally block so it runs
on normal channel close and on cancellation alike). close() now just closes
the message channel, which ends the consumer; flush()/close() no longer
touch the sink from foreign threads. As a bonus, queued messages are
drained before the sink closes. Applies to both desktop and android.
2026-05-28 23:06:21 -07:00
Adam Brown
2365b33c87
Fix IllegalStateException: closed race in FileLogger (#519)
The log-consumer coroutine could write to appendBuffer after close()
closed it from another thread (e.g. during scope cancellation on
shutdown), throwing IllegalStateException: closed.

Guard all sink access with a lock and a closed flag, and close the
message channel on close() so the consumer terminates cleanly. Applies
to both the desktop and android FileLogger.
2026-05-28 23:00:23 -07:00
Adam Brown
d9cc7d1b76
New Crowdin updates (#497)
* New translations strings_account_settings.xml (French)

[ci skip]

* New translations strings_account_settings.xml (Spanish)

[ci skip]

* New translations strings_account_settings.xml (German)

[ci skip]

* New translations strings_account_settings.xml (Italian)

[ci skip]

* New translations strings_account_settings.xml (Ukrainian)

[ci skip]

* New translations strings_account_settings.xml (Chinese Simplified)

[ci skip]

* New translations strings_account_settings.xml (Portuguese, Brazilian)

[ci skip]

* New translations strings_project_select_navigation.xml (French)

[ci skip]

* New translations strings_project_select_navigation.xml (Spanish)

[ci skip]

* New translations strings_project_select_navigation.xml (German)

[ci skip]

* New translations strings_project_select_navigation.xml (Italian)

[ci skip]

* New translations strings_project_select_navigation.xml (Ukrainian)

[ci skip]

* New translations strings_project_select_navigation.xml (Chinese Simplified)

[ci skip]

* New translations strings_project_select_navigation.xml (Portuguese, Brazilian)

[ci skip]

* New translations strings_desktop.xml (French)

[ci skip]

* New translations strings_desktop.xml (Spanish)

[ci skip]

* New translations strings_desktop.xml (German)

[ci skip]

* New translations strings_desktop.xml (Italian)

[ci skip]

* New translations strings_desktop.xml (Ukrainian)

[ci skip]

* New translations strings_desktop.xml (Chinese Simplified)

[ci skip]

* New translations strings_desktop.xml (Portuguese, Brazilian)

[ci skip]

* New translations strings_project_home.xml (French)

[ci skip]

* New translations strings_project_home.xml (Spanish)

[ci skip]

* New translations strings_project_home.xml (German)

[ci skip]

* New translations strings_project_home.xml (Italian)

[ci skip]

* New translations strings_project_home.xml (Ukrainian)

[ci skip]

* New translations strings_project_home.xml (Chinese Simplified)

[ci skip]

* New translations strings_project_home.xml (Portuguese, Brazilian)

[ci skip]

* New translations strings_scene_editor.xml (French)

[ci skip]

* New translations strings_scene_editor.xml (Spanish)

[ci skip]

* New translations strings_scene_editor.xml (German)

[ci skip]

* New translations strings_scene_editor.xml (Italian)

[ci skip]

* New translations strings_scene_editor.xml (Ukrainian)

[ci skip]

* New translations strings_scene_editor.xml (Chinese Simplified)

[ci skip]

* New translations strings_scene_editor.xml (Portuguese, Brazilian)

[ci skip]

* New translations strings.xml (French)

[ci skip]

* New translations strings.xml (Spanish)

[ci skip]

* New translations strings.xml (German)

[ci skip]

* New translations strings.xml (Italian)

[ci skip]

* New translations strings.xml (Ukrainian)

[ci skip]

* New translations strings.xml (Chinese Simplified)

[ci skip]

* New translations strings.xml (Portuguese, Brazilian)

[ci skip]

* New translations strings_about_app.xml (French)

[ci skip]

* New translations strings_about_app.xml (Spanish)

[ci skip]

* New translations strings_about_app.xml (German)

[ci skip]

* New translations strings_about_app.xml (Italian)

[ci skip]

* New translations strings_about_app.xml (Ukrainian)

[ci skip]

* New translations strings_about_app.xml (Chinese Simplified)

[ci skip]

* New translations strings_about_app.xml (Portuguese, Brazilian)

[ci skip]

* New translations strings_notes.xml (French)

[ci skip]

* New translations strings_notes.xml (Spanish)

[ci skip]

* New translations strings_notes.xml (German)

[ci skip]

* New translations strings_notes.xml (Italian)

[ci skip]

* New translations strings_notes.xml (Ukrainian)

[ci skip]

* New translations strings_notes.xml (Chinese Simplified)

[ci skip]

* New translations strings_notes.xml (Portuguese, Brazilian)

[ci skip]

* New translations strings_project_home.xml (French)

[ci skip]

* New translations strings_project_home.xml (Spanish)

[ci skip]

* New translations strings_project_home.xml (German)

[ci skip]

* New translations strings_project_home.xml (Italian)

[ci skip]

* New translations strings_project_home.xml (Ukrainian)

[ci skip]

* New translations strings_project_home.xml (Chinese Simplified)

[ci skip]

* New translations strings_project_home.xml (Portuguese, Brazilian)

[ci skip]

* New translations strings_timeline.xml (French)

[ci skip]

* New translations strings_timeline.xml (Spanish)

[ci skip]

* New translations strings_timeline.xml (German)

[ci skip]

* New translations strings_timeline.xml (Italian)

[ci skip]

* New translations strings_timeline.xml (Ukrainian)

[ci skip]

* New translations strings_timeline.xml (Chinese Simplified)

[ci skip]

* New translations strings_timeline.xml (Portuguese, Brazilian)

[ci skip]

* New translations messages_en.properties (French)

[ci skip]

* New translations messages_en.properties (Spanish)

[ci skip]

* New translations messages_en.properties (German)

[ci skip]

* New translations messages_en.properties (Italian)

[ci skip]

* New translations messages_en.properties (Ukrainian)

[ci skip]

* New translations messages_en.properties (Chinese Simplified)

[ci skip]

* New translations messages_en.properties (Portuguese, Brazilian)

[ci skip]
2026-05-27 00:41:14 -07:00
Wavesonics
a3b077824a Add iOS support via Compose Multiplatform
iOS now runs the same shared Compose UI as Android and Desktop. The
existing Decompose component graph (IosRoot, ProjectSelection,
ProjectRoot) is reused; the Swift app shrinks to an AppDelegate, a
Koin bootstrap, and a UIViewControllerRepresentable that hands off to
a Kotlin ComposeUIViewController. The SwiftUI starter under
/ios/ios/ui and /ios/ios/DecomposeHelpers is deleted.

Hammer.framework moves from :common to :composeUi so the framework
ships the Compose entry point; Xcode's Run Script invokes
:composeUi:embedAndSignAppleFrameworkForXcode. iosArm64 and
iosSimulatorArm64 targets are declared with libbacktrace source-info
so K/N crashes report file:line. 17 expects across composeUi get iOS
actuals (file pickers via filekit, image loading via Coil3,
LanguageUtil via NSLocale.preferredLanguages, etc).

The adaptive nav scaffolds — bottom bar at compact width, side nav
rail otherwise — are extracted from the Android activities into
shared ProjectSelectScaffold and ProjectRootScaffold in
composeUi/commonMain, along with their Modifier helpers and the
close-confirm dialogs. Android activities are now thin shells that
delegate to these; iOS calls the same scaffolds, so phone/tablet
layout is unified across all three platforms.

App icon and CFBundleDisplayName set so the home screen reads
"Hammer" with the brand logo instead of the blueprint placeholder.
2026-05-20 00:36:29 -07:00
Adam Brown
42f230694f
Add launch-time update notification with release-notes dialog
Lifts version check into VersionCheckRepository + GithubVersionCheckDataSource.
On launch, shows an update dialog when a newer release is available and the
tag hasn't been dismissed (tracked in GlobalSettings). Falls back to the
annotated tag message when the release body is empty. AboutApp's VersionCard
gains a button to open the same dialog on demand.
2026-05-19 23:29:39 -07:00
Wavesonics
7664c1fe8d Upgrade to Gradle and AGP 9 2026-05-18 18:48:39 -07:00
Adam Brown
bbfc27efa2
Track last-edited scene per project and surface in stats
Adds `created` and `lastEdited` timestamps to SceneMetadata, stamped
on every autosave tick in SceneEditorRepository.recordSceneActivity.
StatisticsService rolls them up into a new "Last Edited" tile on the
project home dashboard, and the Android widget reads the same field
from the stats cache.

The timestamps ride the sync wire on ApiProjectEntity.SceneEntity and
participate in EntityHasher.hashScene. On download, local values are
preserved when the server didn't ship them. No conflict resolution —
last write wins.

EntityHasher hash functions had their defaults removed so call sites
can't silently miss a newly added field; this caught a latent bug in
the second markForSynchronization hash call that was relying on
defaults for archived/confirmedReferences/dismissedReferences.
2026-05-17 22:57:10 -07:00
Adam Brown
3f9c497657
Add recent-projects launcher menus for Linux (D-Bus quicklist) and macOS (Dock menu), reaching parity with the Windows jump list. All three platforms are now unified behind a QuickShortcuts interface so callers don't care which OS they're on. Pulled the shared "top N projects by lastAccessed" pipeline up onto ProjectsRepository.getRecentProjects() (used by the desktop and Android shortcut managers), and replaced scattered os.name string-matching with a typed HostOs enum. 2026-05-17 14:40:56 -07:00
Adam Brown
95361e7761
Fix android build 2026-05-17 13:45:19 -07:00
Adam Brown
4b3f657084
Add monochrome icon 2026-05-16 21:31:03 -07:00
Adam Brown
aaaaa6f79f
Update libraries metadata 2026-05-14 21:47:43 -07:00
Adam Brown
2701c77523
New Crowdin updates (#475)
* New translations messages_en.properties (German)

* New translations strings_about_app.xml (German)

* New translations strings_account_settings.xml (German)

* New translations strings_drafts.xml (German)

* New translations strings_encyclopedia.xml (German)

* New translations strings_notes.xml (German)

* New translations strings_project_home.xml (German)

* New translations strings_projects_list.xml (German)

* New translations strings_timeline.xml (German)

* New translations strings.xml (German)

* New translations messages_en.properties (German)

* New translations strings_about_app.xml (French)

* New translations strings_about_app.xml (Spanish)

* New translations strings_about_app.xml (German)

* New translations strings_about_app.xml (Italian)

* New translations strings_about_app.xml (Ukrainian)

* New translations strings_about_app.xml (Chinese Simplified)

* New translations strings_about_app.xml (Portuguese, Brazilian)

* New translations strings_drafts.xml (German)

* New translations messages_en.properties (German)

* New translations strings_about_app.xml (French)

* New translations strings_about_app.xml (Spanish)

* New translations strings_about_app.xml (German)

* New translations strings_about_app.xml (Italian)

* New translations strings_about_app.xml (Ukrainian)

* New translations strings_about_app.xml (Chinese Simplified)

* New translations strings_about_app.xml (Portuguese, Brazilian)

* New translations strings_globalsearch.xml (French)

* New translations strings_globalsearch.xml (Spanish)

* New translations strings_globalsearch.xml (German)

* New translations strings_globalsearch.xml (Italian)

* New translations strings_globalsearch.xml (Ukrainian)

* New translations strings_globalsearch.xml (Chinese Simplified)

* New translations strings_globalsearch.xml (Portuguese, Brazilian)

* New translations strings_globalsearch.xml (French)

* New translations strings_globalsearch.xml (Spanish)

* New translations strings_globalsearch.xml (German)

* New translations strings_globalsearch.xml (Italian)

* New translations strings_globalsearch.xml (Ukrainian)

* New translations strings_globalsearch.xml (Chinese Simplified)

* New translations strings_globalsearch.xml (Portuguese, Brazilian)

* New translations strings_project_home.xml (French)

* New translations strings_project_home.xml (Spanish)

* New translations strings_project_home.xml (German)

* New translations strings_project_home.xml (Italian)

* New translations strings_project_home.xml (Ukrainian)

* New translations strings_project_home.xml (Chinese Simplified)

* New translations strings_project_home.xml (Portuguese, Brazilian)

* New translations strings_project_home.xml (French)

* New translations strings_project_home.xml (Spanish)

* New translations strings_project_home.xml (German)

* New translations strings_project_home.xml (Italian)

* New translations strings_project_home.xml (Ukrainian)

* New translations strings_project_home.xml (Chinese Simplified)

* New translations strings_project_home.xml (Portuguese, Brazilian)

* New translations strings_encyclopedia.xml (French)

* New translations strings_scene_editor.xml (French)

* New translations strings_sync.xml (French)

* New translations strings_encyclopedia.xml (Spanish)

* New translations strings_scene_editor.xml (Spanish)

* New translations strings_sync.xml (Spanish)

* New translations strings_encyclopedia.xml (German)

* New translations strings_scene_editor.xml (German)

* New translations strings_sync.xml (German)

* New translations strings_encyclopedia.xml (Italian)

* New translations strings_scene_editor.xml (Italian)

* New translations strings_sync.xml (Italian)

* New translations strings_encyclopedia.xml (Ukrainian)

* New translations strings_scene_editor.xml (Ukrainian)

* New translations strings_sync.xml (Ukrainian)

* New translations strings_encyclopedia.xml (Chinese Simplified)

* New translations strings_scene_editor.xml (Chinese Simplified)

* New translations strings_sync.xml (Chinese Simplified)

* New translations strings_encyclopedia.xml (Portuguese, Brazilian)

* New translations strings_scene_editor.xml (Portuguese, Brazilian)

* New translations strings_sync.xml (Portuguese, Brazilian)

* New translations strings_project_home.xml (French)

[ci skip]

* New translations strings_project_home.xml (Spanish)

[ci skip]

* New translations strings_project_home.xml (German)

[ci skip]

* New translations strings_project_home.xml (Italian)

[ci skip]

* New translations strings_project_home.xml (Ukrainian)

[ci skip]

* New translations strings_project_home.xml (Chinese Simplified)

[ci skip]

* New translations strings_project_home.xml (Portuguese, Brazilian)

[ci skip]

* New translations strings_sync.xml (French)

[ci skip]

* New translations strings_sync.xml (Spanish)

[ci skip]

* New translations strings_sync.xml (German)

[ci skip]

* New translations strings_sync.xml (Italian)

[ci skip]

* New translations strings_sync.xml (Ukrainian)

[ci skip]

* New translations strings_sync.xml (Chinese Simplified)

[ci skip]

* New translations strings_sync.xml (Portuguese, Brazilian)

[ci skip]

* New translations strings_encyclopedia.xml (French)

[ci skip]

* New translations strings_scene_editor.xml (French)

[ci skip]

* New translations strings_encyclopedia.xml (Spanish)

[ci skip]

* New translations strings_scene_editor.xml (Spanish)

[ci skip]

* New translations strings_encyclopedia.xml (German)

[ci skip]

* New translations strings_scene_editor.xml (German)

[ci skip]

* New translations strings_encyclopedia.xml (Italian)

[ci skip]

* New translations strings_scene_editor.xml (Italian)

[ci skip]

* New translations strings_encyclopedia.xml (Ukrainian)

[ci skip]

* New translations strings_scene_editor.xml (Ukrainian)

[ci skip]

* New translations strings_encyclopedia.xml (Chinese Simplified)

[ci skip]

* New translations strings_scene_editor.xml (Chinese Simplified)

[ci skip]

* New translations strings_encyclopedia.xml (Portuguese, Brazilian)

[ci skip]

* New translations strings_scene_editor.xml (Portuguese, Brazilian)

[ci skip]

* New translations strings_notes.xml (French)

[ci skip]

* New translations strings_project_navigation.xml (French)

[ci skip]

* New translations strings_scene_list.xml (French)

[ci skip]

* New translations strings_notes.xml (Spanish)

[ci skip]

* New translations strings_project_navigation.xml (Spanish)

[ci skip]

* New translations strings_scene_list.xml (Spanish)

[ci skip]

* New translations strings_notes.xml (German)

[ci skip]

* New translations strings_project_navigation.xml (German)

[ci skip]

* New translations strings_scene_list.xml (German)

[ci skip]

* New translations strings_notes.xml (Italian)

[ci skip]

* New translations strings_project_navigation.xml (Italian)

[ci skip]

* New translations strings_scene_list.xml (Italian)

[ci skip]

* New translations strings_notes.xml (Ukrainian)

[ci skip]

* New translations strings_project_navigation.xml (Ukrainian)

[ci skip]

* New translations strings_scene_list.xml (Ukrainian)

[ci skip]

* New translations strings_notes.xml (Chinese Simplified)

[ci skip]

* New translations strings_project_navigation.xml (Chinese Simplified)

[ci skip]

* New translations strings_scene_list.xml (Chinese Simplified)

[ci skip]

* New translations strings_notes.xml (Portuguese, Brazilian)

[ci skip]

* New translations strings_project_navigation.xml (Portuguese, Brazilian)

[ci skip]

* New translations strings_scene_list.xml (Portuguese, Brazilian)

[ci skip]

* New translations strings_globalsearch.xml (French)

[ci skip]

* New translations strings_globalsearch.xml (Spanish)

[ci skip]

* New translations strings_globalsearch.xml (German)

[ci skip]

* New translations strings_globalsearch.xml (Italian)

[ci skip]

* New translations strings_globalsearch.xml (Ukrainian)

[ci skip]

* New translations strings_globalsearch.xml (Chinese Simplified)

[ci skip]

* New translations strings_globalsearch.xml (Portuguese, Brazilian)

[ci skip]

* New translations strings_sync.xml (French)

[ci skip]

* New translations strings_sync.xml (Spanish)

[ci skip]

* New translations strings_sync.xml (German)

[ci skip]

* New translations strings_sync.xml (Italian)

[ci skip]

* New translations strings_sync.xml (Ukrainian)

[ci skip]

* New translations strings_sync.xml (Chinese Simplified)

[ci skip]

* New translations strings_sync.xml (Portuguese, Brazilian)

[ci skip]

* New translations strings_notes.xml (French)

[ci skip]

* New translations strings_scene_list.xml (French)

[ci skip]

* New translations strings_notes.xml (Spanish)

[ci skip]

* New translations strings_scene_list.xml (Spanish)

[ci skip]

* New translations strings_notes.xml (German)

[ci skip]

* New translations strings_scene_list.xml (German)

[ci skip]

* New translations strings_notes.xml (Italian)

[ci skip]

* New translations strings_scene_list.xml (Italian)

[ci skip]

* New translations strings_notes.xml (Ukrainian)

[ci skip]

* New translations strings_scene_list.xml (Ukrainian)

[ci skip]

* New translations strings_notes.xml (Chinese Simplified)

[ci skip]

* New translations strings_scene_list.xml (Chinese Simplified)

[ci skip]

* New translations strings_notes.xml (Portuguese, Brazilian)

[ci skip]

* New translations strings_scene_list.xml (Portuguese, Brazilian)

[ci skip]

* New translations strings_account_settings.xml (French)

[ci skip]

* New translations strings_timeline.xml (French)

[ci skip]

* New translations strings_account_settings.xml (Spanish)

[ci skip]

* New translations strings_timeline.xml (Spanish)

[ci skip]

* New translations strings_account_settings.xml (German)

[ci skip]

* New translations strings_timeline.xml (German)

[ci skip]

* New translations strings_account_settings.xml (Italian)

[ci skip]

* New translations strings_timeline.xml (Italian)

[ci skip]

* New translations strings_account_settings.xml (Ukrainian)

[ci skip]

* New translations strings_timeline.xml (Ukrainian)

[ci skip]

* New translations strings_account_settings.xml (Chinese Simplified)

[ci skip]

* New translations strings_timeline.xml (Chinese Simplified)

[ci skip]

* New translations strings_account_settings.xml (Portuguese, Brazilian)

[ci skip]

* New translations strings_timeline.xml (Portuguese, Brazilian)

[ci skip]

* New translations strings_account_settings.xml (German)

[ci skip]

* New translations strings_account_settings.xml (Portuguese, Brazilian)

[ci skip]

* New translations strings_sync.xml (French)

[ci skip]

* New translations strings_sync.xml (Spanish)

[ci skip]

* New translations strings_sync.xml (German)

[ci skip]

* New translations strings_sync.xml (Italian)

[ci skip]

* New translations strings_sync.xml (Ukrainian)

[ci skip]

* New translations strings_sync.xml (Chinese Simplified)

[ci skip]

* New translations strings_sync.xml (Portuguese, Brazilian)

[ci skip]

* New translations strings_projects_list.xml (French)

[ci skip]

* New translations strings_projects_list.xml (Spanish)

[ci skip]

* New translations strings_projects_list.xml (German)

[ci skip]

* New translations strings_projects_list.xml (Italian)

[ci skip]

* New translations strings_projects_list.xml (Ukrainian)

[ci skip]

* New translations strings_projects_list.xml (Chinese Simplified)

[ci skip]

* New translations strings_projects_list.xml (Portuguese, Brazilian)

[ci skip]

* New translations strings_globalsearch.xml (French)

[ci skip]

* New translations strings_globalsearch.xml (Spanish)

[ci skip]

* New translations strings_globalsearch.xml (German)

[ci skip]

* New translations strings_project_home.xml (French)

[ci skip]

* New translations strings_project_home.xml (Spanish)

[ci skip]

* New translations strings_project_home.xml (German)

[ci skip]

* New translations strings_project_home.xml (Italian)

[ci skip]

* New translations strings_scene_editor.xml (French)

[ci skip]

* New translations strings_scene_editor.xml (Spanish)

[ci skip]

* New translations strings_scene_editor.xml (German)

[ci skip]

* New translations strings_scene_editor.xml (Italian)

[ci skip]

* New translations strings_project_navigation.xml (French)

[ci skip]

* New translations strings_project_navigation.xml (Spanish)

[ci skip]

* New translations strings_project_navigation.xml (German)

[ci skip]

* New translations strings_project_navigation.xml (Italian)

[ci skip]

* New translations strings.xml (French)

[ci skip]

* New translations strings_project_select_navigation.xml (French)

[ci skip]

* New translations strings.xml (French)

[ci skip]

* New translations strings.xml (Spanish)

[ci skip]

* New translations strings_project_select_navigation.xml (Spanish)

[ci skip]

* New translations strings.xml (Spanish)

[ci skip]

* New translations strings.xml (German)

[ci skip]

* New translations strings_project_select_navigation.xml (German)

[ci skip]

* New translations strings.xml (German)

[ci skip]

* New translations strings.xml (Italian)

[ci skip]

* New translations strings_project_select_navigation.xml (Italian)

[ci skip]

* New translations strings.xml (Italian)

[ci skip]

* New translations strings_globalsearch.xml (Italian)

[ci skip]

* New translations strings_globalsearch.xml (Ukrainian)

[ci skip]

* New translations strings_globalsearch.xml (Chinese Simplified)

[ci skip]

* New translations strings_globalsearch.xml (Portuguese, Brazilian)

[ci skip]

* New translations strings_project_home.xml (Ukrainian)

[ci skip]

* New translations strings_project_home.xml (Chinese Simplified)

[ci skip]

* New translations strings_project_home.xml (Portuguese, Brazilian)

[ci skip]

* New translations strings_scene_editor.xml (Ukrainian)

[ci skip]

* New translations strings_scene_editor.xml (Chinese Simplified)

[ci skip]

* New translations strings_scene_editor.xml (Portuguese, Brazilian)

[ci skip]

* New translations strings_project_navigation.xml (Ukrainian)

[ci skip]

* New translations strings_project_navigation.xml (Chinese Simplified)

[ci skip]

* New translations strings_project_navigation.xml (Portuguese, Brazilian)

[ci skip]

* New translations strings.xml (Ukrainian)

[ci skip]

* New translations strings_project_select_navigation.xml (Ukrainian)

[ci skip]

* New translations strings.xml (Ukrainian)

[ci skip]

* New translations strings.xml (Chinese Simplified)

[ci skip]

* New translations strings_project_select_navigation.xml (Chinese Simplified)

[ci skip]

* New translations strings.xml (Chinese Simplified)

[ci skip]

* New translations strings.xml (Portuguese, Brazilian)

[ci skip]

* New translations strings_project_select_navigation.xml (Portuguese, Brazilian)

[ci skip]

* New translations strings.xml (Portuguese, Brazilian)

[ci skip]
2026-05-14 21:28:32 -07:00
Adam Brown
ff7fb7cce3
Fix android build 2026-05-14 21:11:23 -07:00
Wavesonics
e76be9c8a4 Updating logo and icons 2026-05-13 21:53:57 -07:00
Adam Brown
1963c09632
Apply new navigation design to android 2026-05-13 00:08:14 -07:00
Adam Brown
b1eff6a632
Expandable nav rail with sliding indicator 2026-05-12 14:00:55 -07:00
Adam Brown
76883d7c25
Add Story Info home-screen widget
Resizable single-project stats widget (4x1 / 2x2 / 3x2 / 3x3+) showing
total word count, cadence-goal progress, today/streak, a 7-day sparkline,
and Open/Note actions. Adds a config activity for project selection.

Bumps Glance to 1.2.0-rc01 and wires up providePreview + setWidgetPreviews
so all three widgets render previews on Android 15+ pickers. Adds the
project name to the Add Note widget header. Extracts parseDailyWordTotals
and formatWidgetWords as shared helpers.
2026-05-12 12:03:44 -07:00
Adam Brown
03e5643bb4
Add dynamic launcher shortcuts for recent projects 2026-05-12 01:08:31 -07:00
Adam Brown
6ea8c5eeb5
Add Stories List home-screen widget
Lists projects with cached word counts; row tap opens the project, header opens the project picker. Lifts shared mono text styles into WidgetDesignSystem and extracts ProjectRootActivity.createIntent to dedupe the deep-link builder.
2026-05-12 00:34:12 -07:00
Adam Brown
456c38fb59
Restyle Add Note widget with editorial design 2026-05-12 00:11:00 -07:00
Adam Brown
18221fcd42
Redesign project selection 2026-05-09 12:57:34 -07:00
Adam Brown
af2965a9f8
Add nav-rail/bottom-bar primitives and tighten the design system
Adds HdNavRail/HdNavRailItem (icon + hover-tooltip, secondaryContainer
selected pill) and HdBottomBar/HdBottomBarItem (slim 56dp icon-only bar
with the same pill treatment, navigation-bar inset handled). Swaps the
desktop ProjectEditorWindow rail and Android CompactNavigation
NavigationBar to the new components — the phone bar reclaims about 24dp
of vertical space versus the M3 default.

Drops the redundant HdFormat.formatThousands in favour of the existing
Int.formatDecimalSeparator across all callers. Merges HdMetadataRow
into HdInlineStat with a valueStyle parameter. Removes the unused
HammerTheme object and the dead HdSwatch overload, hoists Theme.kt
Shapes and the 2dp/16dp RoundedCornerShape allocations to top-level
constants, and trims signature-restating KDoc throughout.

Tightens ProjectStatsUi recompositions: remembers the chapter bar-chart
items + min/max in a single ChapterStats holder, the encyclopedia
totalEntries and Inhabitants header summary, the top-appearances
HdAttributionItem list, and the per-device bar-chart items. Pulls
Random.nextInt out of the EncyclopediaDonut animation tween and into
remember, replaces the in-body hasAnimated flip with LaunchedEffect,
and accepts the encyclopedia counts as parameters so the same sum
isn't computed twice. ProjectHomeMenu now takes hasServer from its
caller instead of subscribing to the same Decompose Value a second
time.
2026-04-29 17:46:00 -07:00
Adam Brown
585c9919c5
Apply project theme to project window UI
Renames ProjectTheme.color1/color2 to primary/secondary and pipes them
into a Material 3 ColorScheme via material-kolor's dynamicColorScheme.
The user's secondary seeds both the Material 3 secondary and tertiary
palettes, the Rainbow palette style keeps them in distinct hue lanes
instead of collapsing toward the primary, and surfaceTint is redirected
to secondary so elevated surfaces (cards, dialogs, top bars) pick up
the accent.

The override is hoisted to the platform entry points
(ProjectEditorWindow.AppContent on desktop, ProjectRootActivity.Content
on Android) so a single ProjectThemeOverride wraps the NavigationRail,
ProjectRootUi, FAB stack, and confirm-close dialogs. ProjectRootUi and
ProjectRootFab no longer self-wrap.

All five project FABs (notes, encyclopedia, timeline, scene group,
scene) explicitly draw containerColor/contentColor from
secondaryContainer so the second color is the obvious accent on the
heaviest visible chrome.
2026-04-28 20:59:15 -07:00
Adam Brown
9708ad1566
Consolidate installId into GlobalSettings with one-shot migration
The install id used to live on ServerSettings, regenerating on every
server reconfig and absent for solo users. It now lives on GlobalSettings
as a stable identity used both for server auth and for the
writing-activity device id. ServerSettings keeps its final clean shape;
the legacy server.json is read once via a private ServerSettingsOld
mirror in MigrateInstallIdToGlobal to copy the value forward.

Adds a GlobalMigration interface alongside the existing per-project
Migration so DataMigrator can run global one-shots before iterating
projects. handleDataMigration() becomes suspend; app entry points wrap
it in runBlocking.
2026-04-28 16:42:53 -07:00
Adam Brown
c18524d130
Wire up shortcut on android 2026-04-26 10:57:29 -07:00
Adam Brown
91af310636
Android now has logs written to disk!
They can be shared as a zip file too
2026-03-30 21:49:12 -07:00
Adam Brown
b2e2500f81
New Crowdin updates (#457)
* New translations messages_en.properties (French)

* New translations messages_en.properties (Spanish)

* New translations messages_en.properties (German)

* New translations messages_en.properties (Italian)

* New translations messages_en.properties (Ukrainian)

* New translations messages_en.properties (Chinese Simplified)

* New translations messages_en.properties (Portuguese, Brazilian)

* New translations messages_en.properties (French)

* New translations messages_en.properties (Spanish)

* New translations messages_en.properties (German)

* New translations messages_en.properties (Italian)

* New translations messages_en.properties (Ukrainian)

* New translations messages_en.properties (Chinese Simplified)

* New translations messages_en.properties (Portuguese, Brazilian)

* New translations strings_timeline.xml (Portuguese, Brazilian)

* New translations strings_drafts.xml (Portuguese, Brazilian)

* New translations strings_encyclopedia.xml (Portuguese, Brazilian)

* New translations strings_timeline.xml (Portuguese, Brazilian)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings_about_app.xml (Portuguese, Brazilian)

* New translations strings_scene_editor.xml (Portuguese, Brazilian)

* New translations messages_en.properties (French)

* New translations messages_en.properties (Spanish)

* New translations messages_en.properties (German)

* New translations messages_en.properties (Italian)

* New translations messages_en.properties (Ukrainian)

* New translations messages_en.properties (Chinese Simplified)

* New translations messages_en.properties (Portuguese, Brazilian)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings_account_settings.xml (Portuguese, Brazilian)

* New translations strings_drafts.xml (Portuguese, Brazilian)

* New translations strings_encyclopedia.xml (Portuguese, Brazilian)

* New translations strings_project_home.xml (Portuguese, Brazilian)

* New translations strings_projects_list.xml (Portuguese, Brazilian)

* New translations strings_scene_list.xml (Portuguese, Brazilian)

* New translations strings.xml (Portuguese, Brazilian)

* New translations messages_en.properties (French)

* New translations messages_en.properties (Spanish)

* New translations messages_en.properties (German)

* New translations messages_en.properties (Italian)

* New translations messages_en.properties (Ukrainian)

* New translations messages_en.properties (Chinese Simplified)

* New translations messages_en.properties (Portuguese, Brazilian)

* New translations strings_account_settings.xml (Portuguese, Brazilian)

* New translations strings_encyclopedia.xml (Portuguese, Brazilian)

* New translations strings_notes.xml (Portuguese, Brazilian)

* New translations strings_project_home.xml (Portuguese, Brazilian)

* New translations strings_projects_list.xml (Portuguese, Brazilian)

* New translations strings_scene_editor.xml (Portuguese, Brazilian)

* New translations strings.xml (Portuguese, Brazilian)

* New translations full_description.txt (French)

* New translations full_description.txt (Spanish)

* New translations full_description.txt (German)

* New translations full_description.txt (Italian)

* New translations full_description.txt (Ukrainian)

* New translations full_description.txt (Chinese Simplified)

* New translations full_description.txt (Portuguese, Brazilian)

* New translations strings_account_settings.xml (French)

* New translations strings_account_settings.xml (Spanish)

* New translations strings_account_settings.xml (German)

* New translations strings_account_settings.xml (Italian)

* New translations strings_account_settings.xml (Ukrainian)

* New translations strings_account_settings.xml (Chinese Simplified)

* New translations strings_account_settings.xml (Portuguese, Brazilian)

* New translations strings_scene_editor.xml (French)

* New translations strings_scene_editor.xml (Spanish)

* New translations strings_scene_editor.xml (German)

* New translations strings_scene_editor.xml (Italian)

* New translations strings_scene_editor.xml (Ukrainian)

* New translations strings_scene_editor.xml (Chinese Simplified)

* New translations strings_scene_editor.xml (Portuguese, Brazilian)

* New translations strings_scene_list.xml (French)

* New translations strings_scene_list.xml (Spanish)

* New translations strings_scene_list.xml (German)

* New translations strings_scene_list.xml (Italian)

* New translations strings_scene_list.xml (Ukrainian)

* New translations strings_scene_list.xml (Chinese Simplified)

* New translations strings_scene_list.xml (Portuguese, Brazilian)

* New translations strings_notes.xml (Portuguese, Brazilian)

* New translations strings_scene_editor.xml (Portuguese, Brazilian)

* New translations strings_scene_list.xml (Portuguese, Brazilian)

* New translations strings_sync.xml (French)

* New translations strings_sync.xml (Spanish)

* New translations strings_sync.xml (German)

* New translations strings_sync.xml (Italian)

* New translations strings_sync.xml (Ukrainian)

* New translations strings_sync.xml (Chinese Simplified)

* New translations strings_sync.xml (Portuguese, Brazilian)

* New translations messages_en.properties (French)

* New translations messages_en.properties (Spanish)

* New translations messages_en.properties (German)

* New translations messages_en.properties (Italian)

* New translations messages_en.properties (Ukrainian)

* New translations messages_en.properties (Chinese Simplified)

* New translations messages_en.properties (Portuguese, Brazilian)

* New translations strings_scene_editor.xml (French)

* New translations strings_scene_editor.xml (Spanish)

* New translations strings_scene_editor.xml (German)

* New translations strings_scene_editor.xml (Italian)

* New translations strings_scene_editor.xml (Ukrainian)

* New translations strings_scene_editor.xml (Chinese Simplified)

* New translations strings_scene_editor.xml (Portuguese, Brazilian)
2026-01-13 23:53:15 -08:00
Adam Brown
cd1c491c0b Improved Server setup error messaging
Add client-side validation for email, password, and URL, along with shared validation utilities

Server error messages can now properly bubble up to the UI
2026-01-13 23:50:47 -08:00
Adam Brown
eb571bfaa1
New Crowdin updates (#455)
* New translations messages_en.properties (Spanish)

* New translations strings.xml (Spanish)

* New translations messages_en.properties (Spanish)
2026-01-09 14:15:30 -08:00
Adam Brown
ee38a2112e
New Crowdin updates (#439)
* New translations messages_en.properties (French)

* New translations messages_en.properties (Spanish)

* New translations messages_en.properties (German)

* New translations messages_en.properties (Italian)

* New translations messages_en.properties (Ukrainian)

* New translations messages_en.properties (Chinese Simplified)

* New translations strings.xml (French)

* New translations strings.xml (Spanish)

* New translations strings.xml (German)

* New translations strings.xml (Italian)

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Chinese Simplified)

* New translations messages_en.properties (French)

* New translations messages_en.properties (Spanish)

* New translations messages_en.properties (German)

* New translations messages_en.properties (Italian)

* New translations messages_en.properties (Ukrainian)

* New translations messages_en.properties (Chinese Simplified)

* New translations strings.xml (French)

* New translations strings.xml (Spanish)

* New translations strings.xml (German)

* New translations strings.xml (Italian)

* New translations strings.xml (Ukrainian)

* New translations messages_en.properties (Portuguese, Brazilian)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings_about_app.xml (French)

* New translations strings_about_app.xml (Spanish)

* New translations strings_about_app.xml (German)

* New translations strings_about_app.xml (Italian)

* New translations strings_about_app.xml (Ukrainian)

* New translations strings_about_app.xml (Chinese Simplified)

* New translations strings_about_app.xml (Portuguese, Brazilian)

* New translations strings_account_settings.xml (French)

* New translations strings_account_settings.xml (Spanish)

* New translations strings_account_settings.xml (German)

* New translations strings_account_settings.xml (Italian)

* New translations strings_account_settings.xml (Ukrainian)

* New translations strings_account_settings.xml (Chinese Simplified)

* New translations strings_account_settings.xml (Portuguese, Brazilian)

* New translations strings_desktop.xml (French)

* New translations strings_desktop.xml (Spanish)

* New translations strings_desktop.xml (German)

* New translations strings_desktop.xml (Italian)

* New translations strings_desktop.xml (Ukrainian)

* New translations strings_desktop.xml (Chinese Simplified)

* New translations strings_desktop.xml (Portuguese, Brazilian)

* New translations strings_drafts.xml (French)

* New translations strings_drafts.xml (Spanish)

* New translations strings_drafts.xml (German)

* New translations strings_drafts.xml (Italian)

* New translations strings_drafts.xml (Ukrainian)

* New translations strings_drafts.xml (Chinese Simplified)

* New translations strings_drafts.xml (Portuguese, Brazilian)

* New translations strings_encyclopedia.xml (French)

* New translations strings_encyclopedia.xml (Spanish)

* New translations strings_encyclopedia.xml (German)

* New translations strings_encyclopedia.xml (Italian)

* New translations strings_encyclopedia.xml (Ukrainian)

* New translations strings_encyclopedia.xml (Chinese Simplified)

* New translations strings_encyclopedia.xml (Portuguese, Brazilian)

* New translations strings_notes.xml (French)

* New translations strings_notes.xml (Spanish)

* New translations strings_notes.xml (German)

* New translations strings_notes.xml (Italian)

* New translations strings_notes.xml (Ukrainian)

* New translations strings_notes.xml (Chinese Simplified)

* New translations strings_notes.xml (Portuguese, Brazilian)

* New translations strings_project_home.xml (French)

* New translations strings_project_home.xml (Spanish)

* New translations strings_project_home.xml (German)

* New translations strings_project_home.xml (Italian)

* New translations strings_project_home.xml (Ukrainian)

* New translations strings_project_home.xml (Chinese Simplified)

* New translations strings_project_home.xml (Portuguese, Brazilian)

* New translations strings_project_navigation.xml (French)

* New translations strings_project_navigation.xml (Spanish)

* New translations strings_project_navigation.xml (German)

* New translations strings_project_navigation.xml (Italian)

* New translations strings_project_navigation.xml (Ukrainian)

* New translations strings_project_navigation.xml (Chinese Simplified)

* New translations strings_project_navigation.xml (Portuguese, Brazilian)

* New translations strings_project_select_navigation.xml (French)

* New translations strings_project_select_navigation.xml (Spanish)

* New translations strings_project_select_navigation.xml (German)

* New translations strings_project_select_navigation.xml (Italian)

* New translations strings_project_select_navigation.xml (Ukrainian)

* New translations strings_project_select_navigation.xml (Chinese Simplified)

* New translations strings_project_select_navigation.xml (Portuguese, Brazilian)

* New translations strings_projects_list.xml (French)

* New translations strings_projects_list.xml (Spanish)

* New translations strings_projects_list.xml (German)

* New translations strings_projects_list.xml (Italian)

* New translations strings_projects_list.xml (Ukrainian)

* New translations strings_projects_list.xml (Chinese Simplified)

* New translations strings_projects_list.xml (Portuguese, Brazilian)

* New translations strings_scene_editor.xml (French)

* New translations strings_scene_editor.xml (Spanish)

* New translations strings_scene_editor.xml (German)

* New translations strings_scene_editor.xml (Italian)

* New translations strings_scene_editor.xml (Ukrainian)

* New translations strings_scene_editor.xml (Chinese Simplified)

* New translations strings_scene_editor.xml (Portuguese, Brazilian)

* New translations strings_scene_list.xml (French)

* New translations strings_scene_list.xml (Spanish)

* New translations strings_scene_list.xml (German)

* New translations strings_scene_list.xml (Italian)

* New translations strings_scene_list.xml (Ukrainian)

* New translations strings_scene_list.xml (Chinese Simplified)

* New translations strings_scene_list.xml (Portuguese, Brazilian)

* New translations strings_sync.xml (French)

* New translations strings_sync.xml (Spanish)

* New translations strings_sync.xml (German)

* New translations strings_sync.xml (Italian)

* New translations strings_sync.xml (Ukrainian)

* New translations strings_sync.xml (Chinese Simplified)

* New translations strings_sync.xml (Portuguese, Brazilian)

* New translations strings_timeline.xml (French)

* New translations strings_timeline.xml (Spanish)

* New translations strings_timeline.xml (German)

* New translations strings_timeline.xml (Italian)

* New translations strings_timeline.xml (Ukrainian)

* New translations strings_timeline.xml (Chinese Simplified)

* New translations strings_timeline.xml (Portuguese, Brazilian)

* New translations strings.xml (French)

* New translations strings.xml (Spanish)

* New translations strings.xml (German)

* New translations strings.xml (Italian)

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Chinese Simplified)

* New translations strings.xml (Portuguese, Brazilian)

* New translations full_description.txt (French)

* New translations full_description.txt (Spanish)

* New translations full_description.txt (German)

* New translations full_description.txt (Italian)

* New translations full_description.txt (Ukrainian)

* New translations full_description.txt (Chinese Simplified)

* New translations full_description.txt (Portuguese, Brazilian)

* New translations short_description.txt (French)

* New translations short_description.txt (Spanish)

* New translations short_description.txt (German)

* New translations short_description.txt (Italian)

* New translations short_description.txt (Ukrainian)

* New translations short_description.txt (Chinese Simplified)

* New translations short_description.txt (Portuguese, Brazilian)

* New translations title.txt (French)

* New translations title.txt (Spanish)

* New translations title.txt (German)

* New translations title.txt (Italian)

* New translations title.txt (Ukrainian)

* New translations title.txt (Chinese Simplified)

* New translations title.txt (Portuguese, Brazilian)

* New translations strings.xml (German)

* New translations strings_about_app.xml (German)

* New translations strings_account_settings.xml (German)

* New translations strings.xml (German)

* New translations messages_en.properties (German)

* New translations strings_account_settings.xml (German)

* New translations full_description.txt (German)

* New translations short_description.txt (German)

* New translations strings_about_app.xml (Portuguese, Brazilian)

* New translations short_description.txt (Portuguese, Brazilian)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings_desktop.xml (Portuguese, Brazilian)

* New translations strings_project_navigation.xml (Portuguese, Brazilian)

* New translations strings_project_select_navigation.xml (Portuguese, Brazilian)

* New translations full_description.txt (Portuguese, Brazilian)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings_project_home.xml (Portuguese, Brazilian)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings_notes.xml (Portuguese, Brazilian)

* New translations strings_project_home.xml (Portuguese, Brazilian)

* New translations strings_scene_editor.xml (Portuguese, Brazilian)

* New translations strings_account_settings.xml (French)

* New translations strings_account_settings.xml (Spanish)

* New translations strings_account_settings.xml (German)

* New translations strings_account_settings.xml (Italian)

* New translations strings_account_settings.xml (Ukrainian)

* New translations strings_account_settings.xml (Chinese Simplified)

* New translations strings_account_settings.xml (Portuguese, Brazilian)

* New translations strings_encyclopedia.xml (French)

* New translations strings_encyclopedia.xml (Spanish)

* New translations strings_encyclopedia.xml (German)

* New translations strings_encyclopedia.xml (Italian)

* New translations strings_encyclopedia.xml (Ukrainian)

* New translations strings_encyclopedia.xml (Chinese Simplified)

* New translations strings_encyclopedia.xml (Portuguese, Brazilian)

* New translations strings_notes.xml (French)

* New translations strings_notes.xml (Spanish)

* New translations strings_notes.xml (German)

* New translations strings_notes.xml (Italian)

* New translations strings_notes.xml (Ukrainian)

* New translations strings_notes.xml (Chinese Simplified)

* New translations strings_notes.xml (Portuguese, Brazilian)

* New translations strings_projects_list.xml (French)

* New translations strings_projects_list.xml (Spanish)

* New translations strings_projects_list.xml (German)

* New translations strings_projects_list.xml (Italian)

* New translations strings_projects_list.xml (Ukrainian)

* New translations strings_projects_list.xml (Chinese Simplified)

* New translations strings_projects_list.xml (Portuguese, Brazilian)

* Clean up

* New translations messages_en.properties (Chinese Simplified)

* New translations messages_en.properties (Portuguese, Brazilian)

* New translations strings_account_settings.xml (French)

* New translations strings_account_settings.xml (Spanish)

* New translations strings_account_settings.xml (German)

* New translations strings_account_settings.xml (Italian)

* New translations strings_account_settings.xml (Ukrainian)

* New translations strings_account_settings.xml (Chinese Simplified)

* New translations strings_account_settings.xml (Portuguese, Brazilian)

* New translations strings_notes.xml (French)

* New translations strings_notes.xml (Spanish)

* New translations strings_notes.xml (German)

* New translations strings_notes.xml (Italian)

* New translations strings_notes.xml (Ukrainian)

* New translations strings_notes.xml (Chinese Simplified)

* New translations strings_notes.xml (Portuguese, Brazilian)

* New translations full_description.txt (French)

* New translations full_description.txt (Spanish)

* New translations full_description.txt (German)

* New translations full_description.txt (Italian)

* New translations full_description.txt (Ukrainian)

* New translations short_description.txt (French)

* New translations short_description.txt (Spanish)

* New translations short_description.txt (German)

* New translations short_description.txt (Italian)

* New translations short_description.txt (Ukrainian)

* New translations title.txt (French)

* New translations title.txt (Spanish)

* New translations title.txt (German)

* New translations title.txt (Italian)

* New translations title.txt (Ukrainian)

* New translations full_description.txt (Chinese Simplified)

* New translations full_description.txt (Portuguese, Brazilian)

* New translations short_description.txt (Chinese Simplified)

* New translations short_description.txt (Portuguese, Brazilian)

* New translations title.txt (Chinese Simplified)

* New translations title.txt (Portuguese, Brazilian)

* Clean up
2026-01-06 00:35:32 -08:00
Adam Brown
5c2c815c2e Implemented backup sharing 2026-01-05 23:37:05 -08:00
Adam Brown
074696df48 Fix Snackbars being behind bottom nav on phones 2025-12-29 15:54:42 -08:00
Adam Brown
34e55f5e89 Focus mode now enabled do-no-disturb on Android 2025-12-27 23:33:09 -08:00
Adam Brown
c94bb97a76 Save exception info from proguard 2025-12-25 11:32:53 -08:00
Adam Brown
ae9112508c Improve confirm close dialog 2025-12-25 01:50:21 -08:00