Commit Graph
17 Commits
Author SHA1 Message Date
M57andM57 eb71ae3a46 Fix WebSocket events being silently dropped on buffer overflow (#313)
* Fix WebSocket events being silently dropped on buffer overflow

Increases the MutableSharedFlow `extraBufferCapacity` from 64 to 256
and changes the `onBufferOverflow` policy to `BufferOverflow.DROP_OLDEST`
in `HermesWsClient.kt`. This fixes an issue where the slow collection
(e.g., due to DB writes) caused the buffer to fill up and silently drop
incoming real-time WebSocket events.

By setting `DROP_OLDEST`, `tryEmit()` remains functional without
suspending, allowing real-time events to be retained and prioritized.

Fixes #275

* Fix ktlint formatting issues in HermesWsClient.kt

The formatting changes adhere to ktlint rules required by the CI pipeline:
- Removed a trailing comma in MutableSharedFlow initialization to avoid multiline expression wrapping errors.
- Sorted imports to be in lexicographical order.

These formatting changes fix the failing CI check.

Fixes #275

* Fix WebSocket events being silently dropped on buffer overflow

Increases the MutableSharedFlow `extraBufferCapacity` from 64 to 256
and changes the `onBufferOverflow` policy to `BufferOverflow.DROP_OLDEST`
in `HermesWsClient.kt`. This fixes an issue where the slow collection
(e.g., due to DB writes) caused the buffer to fill up and silently drop
incoming real-time WebSocket events.

By setting `DROP_OLDEST`, `tryEmit()` remains functional without
suspending, allowing real-time events to be retained and prioritized.

Fixes #275

* Fix WebSocket events being silently dropped on buffer overflow

Increases the MutableSharedFlow extraBufferCapacity from 64 to 256
and changes the onBufferOverflow policy to BufferOverflow.DROP_OLDEST
in HermesWsClient.kt. This fixes an issue where the slow collection
(e.g., due to DB writes) caused the buffer to fill up and silently drop
incoming real-time WebSocket events.

By setting DROP_OLDEST, tryEmit() remains functional without
suspending, allowing real-time events to be retained and prioritized.

Fixes #275

* Fix WebSocket events being silently dropped on buffer overflow

Increases the MutableSharedFlow extraBufferCapacity from 64 to 256
and changes the onBufferOverflow policy to BufferOverflow.DROP_OLDEST
in HermesWsClient.kt. This fixes an issue where the slow collection
(e.g., due to DB writes) caused the buffer to fill up and silently drop
incoming real-time WebSocket events.

By setting DROP_OLDEST, tryEmit() remains functional without
suspending, allowing real-time events to be retained and prioritized.

Fixes #275

* Fix WebSocket events being silently dropped on buffer overflow

Increases the MutableSharedFlow extraBufferCapacity from 64 to 256
and changes the onBufferOverflow policy to BufferOverflow.DROP_OLDEST
in HermesWsClient.kt. This fixes an issue where the slow collection
(e.g., due to DB writes) caused the buffer to fill up and silently drop
incoming real-time WebSocket events.

By setting DROP_OLDEST, tryEmit() remains functional without
suspending, allowing real-time events to be retained and prioritized.

Fixes #275

---------

Co-authored-by: M57 <hy4ri@users.noreply.github.com>
2026-06-23 22:13:55 +03:00
M57andM57 2c6e437a5b Fix: Prevent AuthManager state pollution on connection verification (#348)
* Fix: Prevent AuthManager state pollution on connection verification

Modified `ConnectViewModel.connect()` to construct a temporary OkHttpClient and Retrofit builder, isolated from the global `ApiClient` state. The connection verification is executed using this temporary service. Only upon a successful HTTP response does the system persist the configured `host`, `port`, and `token` to the global `AuthManager` and triggers an `ApiClient.rebuild()`. This resolves the issue where a failed connection attempt would overwrite active and verified profiles. Extracted `createTempService` factory to `ApiClient` for robustness and clean tests.

Fixes #260

* Fix: Prevent AuthManager state pollution on connection verification

Modified `ConnectViewModel.connect()` to construct a temporary OkHttpClient and Retrofit builder, isolated from the global `ApiClient` state. The connection verification is executed using this temporary service. Only upon a successful HTTP response does the system persist the configured `host`, `port`, and `token` to the global `AuthManager` and triggers an `ApiClient.rebuild()`. This resolves the issue where a failed connection attempt would overwrite active and verified profiles. Extracted `createTempService` factory to `ApiClient` for robustness and clean tests.

Fixes #260

---------

Co-authored-by: M57 <hy4ri@users.noreply.github.com>
2026-06-23 20:49:58 +03:00
M57 c21e3e9ed0 fix(#259): validate host in pairing string to prevent SSRF (#344)
Add robust validation for hosts provided through URI or Base64 pairing
strings to prevent Server-Side Request Forgery (SSRF). The application
now rejects loopback addresses (like localhost, 127.0.0.1, 0.0.0.0),
link-local addresses, and any-local addresses, while continuing to allow
remote connections to site-local addresses, custom remote domains,
and VPN networks (like Tailscale). The DNS resolution operates securely
on the IO dispatcher to ensure main-thread safety. Included tests verify
both rejection of invalid hosts and seamless parsing of valid ones.
2026-06-23 12:47:50 +03:00
M57 6abfabdac0 fix(#287): fix empty-state subtitles and content description on Keys and Profiles screens (#311)
* fix(#287): fix empty-state subtitles and content description on Keys and Profiles screens

- Added `keys_empty_desc` and `profiles_empty_desc` string resources.
- Updated `KeysScreen.kt` and `ProfilesScreen.kt` to use correct empty-state subtitles instead of the copy-pasted `toolsets_empty_desc`.
- Added `content_desc_edit` string resource and applied it to the edit icon in `KeysScreen.kt` for accessibility.

* fix(#287): correct empty-state descriptions and accessibility content descriptions

- Replaced incorrect `toolsets_empty_desc` with newly added `keys_empty_desc` on the Keys screen.
- Replaced incorrect `toolsets_empty_desc` with newly added `profiles_empty_desc` on the Profiles screen.
- Updated the content description of the edit icon on the Keys screen to use newly added `content_desc_edit` instead of `nav_drawer_section_converse`.
2026-06-22 22:33:09 +03:00
M57andM57 e8025efcde fix(#298): internationalize ConnectViewModel strings, fix null-assert crash on profile selector (#307)
* fix(#298): internationalize ConnectViewModel strings, fix null-assert crash on profile selector

E1: Add all connect error resources to strings.xml for i18n readiness
E2: Migrate ConnectViewModel to AndroidViewModel, replace all hardcoded
    user-facing strings with getString(R.string.*) calls
F1: Replace state.selectedProfile!! with .?.let { } pattern in
    ConnectScreen.kt to eliminate NPE risk on mutable state copy

Closes #298

* fix(#298): update test files for AndroidViewModel constructor

Update ConnectViewModelTest.kt and E2eIntegrationTest.kt to pass
mock Application to the new ConnectViewModel(app) constructor.
Add getString() MockK stubs matching the string resource keys.

* fix(#298): add missing LocalContext import and restore connect_pairing_string

Two compilation errors:
- ConnectScreen.kt was missing import for LocalContext
- strings.xml was missing connect_pairing_string resource
  (accidentally removed in earlier patch)

* fix(#298): extract ViewModelFactory to avoid composable-in-non-composable error

LocalContext.current cannot be called inside a viewModel { } factory
lambda because the lambda is not @Composable. Fix by extracting a
ConnectViewModelFactory class and using run { } to capture the
Application value at the composable call site before passing to
the factory constructor.

* fix(#298): fix MockK varargs matching in test stubs

getString(int, Object...) takes varargs. MockK's any<Int>() and
any<String>() didn't match the vararg Object... slot. Changed to
any() (untyped) which matches correctly.

* fix(#298): fix MockK answers — arg indexing was wrong

In getString(int, Object...), firstArg is the resource ID,
secondArg is the format argument. Using firstArg<Int>() in
the answers block was returning the res ID, not 500/etc.
Changed to secondArg<Any>().

* fix(#298): replace getString(int,Object...) with String.format(getString(int),...)

Avoid MockK varargs matching issues by calling app.getString(int)
for the format template and String.format() to apply args.
Simplifies test stubs to pure getString(int) returns.

---------

Co-authored-by: M57 <hy4ri@users.noreply.github.com>
2026-06-22 21:38:28 +03:00
M57andM57 60bf6e8a33 feat: UI Changes
* fix(#220): implement edit soul and set model dialogs

* fix(#211): make UI more compact and information dense

* fix(#211): make navigation drawer sidebar more compact

* feat(#252): move settings item to end of navigation drawer

* feat(#250): add bottom navigation bar display mode settings

* feat(#225): add search bar filtering to remaining screens

* fix: make bottom navigation bar display modes more compact

* fix: resolve compilation error in KanbanScreen by referencing assignedTo

* feat: add search to achievements screen and top padding for icon-only navigation bar

* fix: adjust icon-only bottom bar height and remove padding

* fix(#249): remove unused PaddingValues imports in 6 screens

---------

Co-authored-by: M57 <hy4ri@users.noreply.github.com>
2026-06-21 20:42:23 +03:00
M57 32def80694 fix(#220): implement edit soul and set model dialogs (#248) 2026-06-21 20:03:31 +03:00
Hy4ri 8e8fca756a feat(#208): add Monochrome, Gruvbox, Catppuccin and AMOLED theme presets 2026-06-21 13:01:55 +03:00
Hy4ri 44e2006434 refactor(#78): extract UI strings for remaining batch 2.3 screens 2026-06-21 11:55:18 +03:00
Hy4ri b1950ece34 refactor(#78): extract UI strings for toolsets webhooks pairing and config screens 2026-06-21 11:48:33 +03:00
Hy4ri dcb23ba0a3 refactor(#78): extract UI strings for logs, system, model, and sessions/history screens 2026-06-21 11:41:41 +03:00
Hy4ri cdad31b555 refactor(#78): extract UI strings for chat, settings, connect, kanban, and skills screens 2026-06-21 11:38:33 +03:00
Hy4ri acd6cbf751 refactor(#78): extract notification strings to resources 2026-06-21 11:31:09 +03:00
Hy4ri c34f6f1e47 refactor(#78): extract navigation and drawer labels to string resources 2026-06-21 11:09:44 +03:00
Hy4ri 8efbe02c27 refactor(#78): extract shared components and common strings to resources 2026-06-21 11:00:20 +03:00
M57andM57 ff4649b601 fix(#130): fix compilation errors in scroll-to-bottom FAB (#166)
* fix(#130): fix compilation errors in scroll-to-bottom FAB

* fix(#130): add missing R import, context, and string resources

* fix(#130): use stringResource() instead of context.getString() for Compose lint

---------

Co-authored-by: M57 <hy4ri@users.noreply.github.com>
2026-06-20 16:45:05 +03:00
Hy4ri d6ff3de594 Initial commit of HermesControl Android app 2026-06-16 00:00:36 +03:00