Commit Graph
100 Commits
Author SHA1 Message Date
M57andM57 bbe3b00ccb test(#293): add foundational Compose UI test for StateViews (TEST-15) (#301)
Co-authored-by: M57 <hy4ri@users.noreply.github.com>
2026-06-22 05:25: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
M57 4715c85185 fix(#204): dynamically reset and reload chat title when creating or switching sessions (#247)
* fix(#204): dynamically reset and reload chat title when creating or switching sessions

* fix(#204): refresh session list on message completion to catch auto-generated titles
2026-06-21 19:45:08 +03:00
M57 0c192eddad fix(#205): fix typing effect by checking actual streamed word counts and default it to enabled (#246)
* fix(#205): fix typing effect by checking actual streamed word counts and default it to enabled

* fix: correct import path of rememberSaveable to resolve build error

* fix: make typingDelayMs reactive using rememberUpdatedState in StreamingBubbleWithTypingEffect

* fix(#205): support message.delta event type to enable streaming text

* feat(#205): increase typing effect delay slider maximum to 1000ms

* fix(#205): continue animating completed streaming messages until all words are revealed

* fix(#205): revert slider delay maximum value back to 100ms
2026-06-21 19:38:51 +03:00
M57 2f5a31d3cb fix(#213): scroll-to-bottom FAB now targets absolute list bottom (#245) 2026-06-21 19:16:32 +03:00
M57 abe9e0e284 fix(#218): fallback to Untitled for empty or blank session titles (#244) 2026-06-21 19:13:09 +03:00
M57 57c3e468df feat(#238): update Model tab icon to Psychology (#243) 2026-06-21 19:09:16 +03:00
M57 bfef3613fa fix(#240): parse session_id from params root (#242)
* fix(#240): parse session_id from params root

Allows correct session mapping when opening app via notification.

* fix(#240): set MainActivity launchMode to singleTop

Prevents activity destruction and WebSocket reconnection when tapping notifications.

* fix(#240): save inline notification replies to Room database

* fix(#240): refresh current session when app comes to foreground

* fix(#240): use uppercase role string to match Mapper mapping expectations

* style: format NotificationReplyReceiver.kt to satisfy ktlint
2026-06-21 19:04:54 +03:00
M57andM57 d7ca7b084e fix(#240): notification tap race condition opens new chat instead of correct session (#241)
Two-pronged fix for the race between GatewayReady auto-creating a session
and ChatScreen LaunchedEffect calling switchSession:

1. ChatViewModel: added `initialSessionId` field. GatewayReady now checks
   this before auto-creating a session — if set, it calls switchSession
   instead. The field is set synchronously by ChatScreen via SideEffect
   during composition, before any WS event can be processed.

2. ChatScreen: LaunchedEffect now keys on state.connectionStatus and
   waits for CONNECTED before calling switchSession. This prevents the
   SESSION_RESUME message from being dropped (webSocket is null before
   onOpen, so send() is a silent no-op).

Fixes #240

Co-authored-by: M57 <hy4ri@users.noreply.github.com>
2026-06-21 18:32:29 +03:00
M57 adc23e3540 Merge pull request #239 from Hy4ri/fix/issue-214-notification-tap-navigation
fix(#214): notification tap now navigates to the correct session
2026-06-21 17:47:28 +03:00
M57 f68841c2a7 fix(#214): update test assertion to match full success message 2026-06-21 17:42:49 +03:00
M57 59f3af0a55 fix: add missing setValue import for mutableStateOf delegate 2026-06-21 17:25:54 +03:00
M57 0828fd8796 Merge pull request #237 from Hy4ri/fix/issue-201-platforms-response-shape
fix(#201): platforms endpoint response shape mismatch
2026-06-21 17:25:10 +03:00
M57 21744fd951 fix: replace .apply block with direct property/extra calls for ktlint 2026-06-21 17:22:35 +03:00
M57 fea7820740 fix: extract long toast string to val, fix indentation 2026-06-21 17:18:59 +03:00
M57 ab92b31d2e fix: ktlint wrapping violations on toast message and intent builder 2026-06-21 17:16:05 +03:00
M57 37fc9d9f17 fix: clarify toast - gateway restart required for platform toggle changes 2026-06-21 17:11:28 +03:00
M57 d2e59b2741 fix(#214): notification tap now navigates to correct session
Root cause: MainActivity had no onNewIntent override. When the app was
backgrounded and a notification was tapped, Android brought the existing
task to the foreground and delivered the intent via onNewIntent — but
since it wasn't overridden, the session ID from the notification was
silently dropped and the user saw the last-active session.

Fix:
1. Changed notificationSessionId from a local val to a Compose
   mutableStateOf so it's observable across recompositions.
2. Added onNewIntent override that reads the session ID from the
   incoming intent and updates the observable state.
3. Added FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP to the
   notification PendingIntent for reliable task management.
2026-06-21 16:40:30 +03:00
M57 262578528b fix: stabilize flaky testAutoReconnect with polling assertion 2026-06-21 16:26:07 +03:00
M57 d4eb36f032 fix: ktlint parameter-list-wrapping on getMessagingPlatforms 2026-06-21 16:12:35 +03:00
M57 35c608b2bf fix(#201): fix platforms endpoint response shape mismatch
GET /api/messaging/platforms returns a JSON object with a platforms
array inside, but the app expected a bare array. Wraps the response
in a new MessagingPlatformResponse model.

- Adds MessagingPlatformResponse.kt wrapper model
- Updates HermesApiService.kt return type + adds profile query param
- Updates ChannelsViewModel.kt to unwrap .platforms
- Updates E2eIntegrationTest.kt mock to match new response shape
2026-06-21 16:03:36 +03:00
M57 a89b932a0e Merge pull request #236 from Hy4ri/feat/issue-208-theme-presets
feat(#208): add Monochrome, Gruvbox, Catppuccin and AMOLED theme presets
2026-06-21 13:10:38 +03:00
M57 50e6ff5f7c fix(#236): resolve merge conflict markers in AuthManager.kt 2026-06-21 13:06:11 +03:00
M57 f738f33fc5 Merge pull request #235 from Hy4ri/feat/issue-207-chat-bubble-contrast
fix(#207): dynamic contrast adjustments for chat bubbles legibility
2026-06-21 12:46:50 +03:00
M57 7d8d2707c6 Merge pull request #234 from Hy4ri/feat/issue-232-dynamic-theme
feat(#232): dynamic theme switch on settings save
2026-06-21 12:39:21 +03:00
M57 7ce19cd52c Merge pull request #233 from Hy4ri/feat/issue-232-cron-icons
feat(#232): replace cron action text buttons with compact icons
2026-06-21 12:30:30 +03:00
M57 d1d5b0937c Merge pull request #231 from Hy4ri/refactor/issue-78-strings-extraction
refactor(#78): extract hardcoded strings to strings.xml
2026-06-21 12:23:10 +03:00
M57 4087ee0cac fix: switch issue templates to YAML forms, remove broken markdown templates
Markdown-based issue templates with frontmatter were silently ignored
by GitHub (likely an empty-string assignees field or frontmatter
format issue). Switched to the newer YAML-based issue forms which use
a structured schema format that GitHub explicitly supports.

- bug_report.yml: structured form with required fields for description,
  reproduction steps, environment, screenshots
- feature_request.yml: form with problem/motivation, proposed solution,
  alternatives, mockups
- config.yml: unchanged, keeps blank_issues_enabled: false
2026-06-21 10:39:27 +03:00
M57 20b8eae282 Merge pull request #229 from Hy4ri/fix/issue-template-frontmatter
fix: remove invalid assignees field from issue template frontmatter
2026-06-21 10:36:18 +03:00
M57 10a98128b5 fix: remove invalid assignees field from issue template frontmatter
The 'assignees: ''' value breaks GitHub's YAML parser, causing
templates to be silently ignored and falling back to blank issue +
discussions. Removed the field entirely since no auto-assignment
is needed.
2026-06-21 10:35:58 +03:00
M57 52bfadcae8 Merge pull request #228 from Hy4ri/feat/issue-templates
docs: add GitHub issue templates (bug report + feature request)
2026-06-21 10:33:39 +03:00
M57 6ebcb3930d docs: add GitHub issue templates (bug report + feature request)
Adds a config.yml chooser and two markdown templates:
- bug_report.md — structured bug report with reproduction steps,
  environment info, and screenshot slot
- feature_request.md — enhancement/UX/refactor request with
  problem statement, proposed solution, and alternatives

Both follow the project's bracket-prefix title convention.
2026-06-21 10:33:00 +03:00
M57andM57 bc3ddd626b docs: add GitHub PR template (#227)
Adds a .github/PULL_REQUEST_TEMPLATE.md with sections for summary,
type of change, screenshots, testing steps, and project-specific
checklist items (HermesScaffold, NavigationController, room schema,
screen dedup check).

Co-authored-by: M57 <hy4ri@users.noreply.github.com>
2026-06-21 10:29:03 +03:00
M57andM57 a5c070b353 ux: swap positions of new chat and search buttons in top bar (Issue #212) (#226)
Swapped the order of the Search toggle and New Chat icon buttons
in the ChatScreen top bar actions slot. Search is now on the left
(right-side outer position) which matches user expectations —
the new chat button was accidentally tapped when reaching for search.

Fixes #212

Co-authored-by: M57 <hy4ri@users.noreply.github.com>
2026-06-21 10:24:32 +03:00
M57 4e8da7b90c fix(security): allow cleartext traffic globally to support LAN IP connections (#200)
* feat(skills): add category and status filters (#111)

* fix(security): allow cleartext traffic globally to support LAN IP connections
2026-06-21 01:09:28 +03:00
M57 63575272c9 feat(skills): add category and status filters (#111) (#199) 2026-06-21 00:49:58 +03:00
M57 081996d376 refactor: extract entryProvider from MainNavigation (#197)
Extract the overly long `entryProvider` lambda out of `MainNavigation` into a separate `appEntryProvider` function to improve code readability and maintainability.
2026-06-21 00:31:59 +03:00
M57 f7a334ecfd Refactor CronExpressionFormatter to improve maintainability (#192)
Extract logic from a single long method `cronToHumanReadable` into distinct parser helpers for shortcuts, day of month, days of week, and general time handling. Move repetitive static properties and small format helpers to the object scope.
2026-06-21 00:30:02 +03:00
M57 5e90a4d1a7 fix(chat): conditional auto-scroll on new messages (#131) (#193) 2026-06-21 00:29:26 +03:00
M57 00c6e75f50 feat(connect): saved connection profiles support (#107) (#191)
* feat(#107): implement saved connection profiles support

* fix(connect): fallback profiles resolution and stubbing in tests
2026-06-21 00:18:35 +03:00
M57 0eed12d18e Refactor: Extract hardcoded "todo" to constant in KanbanScreen (#190)
- Extracted the hardcoded string "todo" to a `DEFAULT_COLUMN` constant in `KanbanScreen.kt` to improve code health and readability.
- Replaced the hardcoded string literal in the `viewModel.createTask` call with the new constant.
2026-06-21 00:17:37 +03:00
M57 63a927fae2 chore: Update softprops/action-gh-release to v3 to use Node 24 (#189)
Fixes the deprecation warning for Node 20 by bumping the action version.
2026-06-21 00:15:29 +03:00
M57 60c4096e9c Performance improvement for chat search filtering (#188) 2026-06-21 00:00:36 +03:00
M57 4547861c71 test: Add HermesWsClient test (#187) 2026-06-20 23:56:04 +03:00
M57 49fd12ac34 fix(#115): send enabled flag on config save and propagate configuration errors (#186) 2026-06-20 23:54:43 +03:00
M57 2b7facb7f4 Add NetworkResult Test for SafeApiCall and Mapping (#185)
* Add tests for NetworkResult and safeApiCall

* Fix ktlint errors formatting
2026-06-20 23:52:23 +03:00
M57 045932ca8b Optimize collection creation in Navigation.kt (#180)
* ⚡ Optimize collection creation in Navigation.kt

Replaced uses of `.map { ... }.toSet()` with `.mapTo(mutableSetOf()) { ... }` in Navigation.kt. This avoids the creation of intermediate ArrayList objects, saving unnecessary memory allocations.

* ⚡ Optimize collection creation in Navigation.kt

Replaced uses of `.map { ... }.toSet()` with `.mapTo(mutableSetOf()) { ... }` in Navigation.kt. This avoids the creation of intermediate ArrayList objects, saving unnecessary memory allocations. Fixed ktlint formatting issues causing CI failure.
2026-06-20 23:44:39 +03:00
M57 81b2ff3aa5 Add error path coverage for CronExpressionFormatter (#182)
* test: add error path coverage for CronExpressionFormatter

Added a new test case to cover the fallback code path when cron parsing throws an exception. This test ensures the formatting correctly defaults to returning "Raw: <schedule>" when an invalid string like '0 12 1 15 *' or '0 9 * * 8' is passed.

It also introduces mockk integration to mock android.util.Log which prevents RuntimeExceptions from being thrown during local JUnit tests when logging errors in the catch block.

* test: add error path coverage for CronExpressionFormatter and fix ktlint issues

Added a new test case to cover the fallback code path when cron parsing throws an exception. This test ensures the formatting correctly defaults to returning "Raw: <schedule>" when an invalid string like '0 12 1 15 *' or '0 9 * * 8' is passed.

It also introduces mockk integration to mock android.util.Log which prevents RuntimeExceptions from being thrown during local JUnit tests when logging errors in the catch block.

Also removed trailing whitespace and an empty line at the start of the class to fix ktlint checking in CI.
2026-06-20 23:43:46 +03:00
M57 34af34af6d perf: avoid intermediate allocation in bottomNavKeys (#184)
Replaces `.map { ... }.toSet()` with `.mapTo(mutableSetOf()) { ... }`
when resolving `bottomNavKeys` to avoid creating and discarding an
intermediate `ArrayList` during recomposition.
2026-06-20 23:42:40 +03:00
M57 3eb9e09f86 test: Add tests for malformed Base64 decoding in ConnectViewModel (#183) 2026-06-20 23:41:31 +03:00
M57 838b888f9b ⚡ Optimize Set creation in ChatViewModel (#181)
Refactored `chatMessages.map { it.id }.toSet()` to `chatMessages.mapTo(HashSet(chatMessages.size)) { it.id }` to avoid creating and discarding an unnecessary intermediate ArrayList.

Benchmark results show a ~31% performance improvement on 5000 iterations for typical sizes.
2026-06-20 23:38:36 +03:00
M57 d44df3f339 fix(#102): add EmptyState views for successful empty responses across data screens (#179) 2026-06-20 23:27:17 +03:00
M57 d1f4e9eb67 fix(#67): restrict cleartext traffic to local subnets and Tailscale range (#178) 2026-06-20 23:17:00 +03:00
M57 f2e11413cc fix(#66): enable room schema export and configure release migration safe-guards (#177) 2026-06-20 22:57:08 +03:00
M57 a315c9d3d4 fix(#63): require keystore env variables for release builds (#176)
* fix(#63): require keystore env variables for release builds

* fix(ci): conditionalize signing requirement to release tasks only
2026-06-20 22:47:46 +03:00
M57 64a047f095 feat: move session history to a dedicated history screen (#175)
* feat: move session history to a dedicated history screen

Closes #159.

* fix(ci): fix ktlint style issues and unresolved NavigationController reference
2026-06-20 22:27:54 +03:00
M57 d862172d78 fix(nav): keep NavKey implementation names in proguard (#174)
Avoid obfuscating screen classes/objects since their simpleNames are matched for bottom nav setup.
2026-06-20 17:54:58 +03:00
M57 82f2a5142f ci: update release workflow to Node.js 24 and setup-gradle validation (#173)
Closes #171.
2026-06-20 17:49:41 +03:00
M57 54a195bd94 fix(auth): initialize AuthManager in custom application class (#172)
Closes #68. Redundant initialization in MainActivity has been removed.
2026-06-20 17:43:40 +03:00
M57 a50628696f test(#100): add unit test to verify upsert for completion-only message (#170) 2026-06-20 17:38:07 +03:00
M57 8763271056 fix(#101): collect events once in init to prevent duplicate collectors on reconnect (#169) 2026-06-20 17:32:24 +03:00
M57 74714fc1df fix(#99): gate tool and clarify events by session id to prevent leaks (#168) 2026-06-20 17:27:34 +03:00
M57 6cb4e17882 fix(#127): serialize tool event data to JSON for pretty formatting (#167)
* fix(#127): serialize tool event data to JSON for pretty formatting

* fix(test): format tool start test case to satisfy ktlint
2026-06-20 17:22:28 +03:00
M57andM57 3c5fcf504c feat(#154): add word-by-word typing effect toggle and speed slider in settings (#165)
* feat(#154): add word-by-word typing effect toggle and speed slider in settings

* fix(settings): import Slider to fix build failure

---------

Co-authored-by: M57 <hy4ri@users.noreply.github.com>
2026-06-20 17:09:42 +03:00
M57 8c9c11df23 refactor(#103): centralize navigation mutations through NavigationController.resetTo() (#164)
* refactor(#103): centralize navigation mutations through NavigationController.resetTo()

* fix(chat): fix scroll-to-bottom FAB compilation errors
2026-06-20 17:01:37 +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
M57andM57 03cfcf8504 feat(#125): fix clarify input pre-filling and parse/route clarify_id (#156)
* feat(#125): fix clarification input pre-filling and parse/route clarify_id

* fix(#156): fix ktlint violations in ChatViewModelTest.kt

---------

Co-authored-by: M57 <hy4ri@users.noreply.github.com>
2026-06-20 16:35:58 +03:00
M57andM57 4544d88f8d feat(#130): add scroll-to-bottom FAB that appears when user scrolls up (#163)
Co-authored-by: M57 <hy4ri@users.noreply.github.com>
2026-06-20 14:12:25 +03:00
M57andM57 ca21e22147 ci(#71): change FGS type from dataSync to remoteMessaging for indefinite WebSocket listener (#162)
Co-authored-by: M57 <hy4ri@users.noreply.github.com>
2026-06-20 14:07:46 +03:00
M57andM57 87392f5e57 fix(#148): prevent chatTitle being overwritten by response handlers (#161)
Co-authored-by: M57 <hy4ri@users.noreply.github.com>
2026-06-20 14:04:59 +03:00
M57andM57 0ec70beb84 refactor(#104): prune unused ChatMessageDao APIs and stale test stubs (#160)
Co-authored-by: M57 <hy4ri@users.noreply.github.com>
2026-06-20 13:57:51 +03:00
M57andM57 3f19224228 feat(#123): add primary screens to drawer categorically (#158)
Co-authored-by: M57 <hy4ri@users.noreply.github.com>
2026-06-20 13:46:08 +03:00
M57andM57 c6d7a45905 fix(#135): guard goBack() against empty back stack (#157)
goBack() now uses ChatScreen as a fallback when the stack has
only one item, preventing the Settings back-button crash.

Co-authored-by: M57 <hy4ri@users.noreply.github.com>
2026-06-20 13:29:19 +03:00
M57 62b1115924 Merge pull request #155 from Hy4ri/feat/issue-125-clarification-respond-routing
feat(#125): pre-fill clarification input and route response via clarify.respond
2026-06-20 12:57:31 +03:00
M57 399691ed34 Merge pull request #153 from Hy4ri/feat/issue-125-clarification-input
feat(#125): add free-form text input and guidelines to ClarifyDialog
2026-06-20 12:33:16 +03:00
M57 42f8cfe509 Merge pull request #152 from Hy4ri/fix/issue-146-lost-replies
fix(#146): finalize active streaming message before tool execution or new message start
2026-06-20 12:20:55 +03:00
M57 196883b5c1 Merge pull request #151 from Hy4ri/refactor/chat-system-stability
refactor: stabilize chat system streaming, session loading, and connection state
2026-06-20 12:12:26 +03:00
M57andM57 a2d299e136 feat(#129): remove redundant source archive, add About version card in Settings (#149)
Co-authored-by: M57 <hy4ri@users.noreply.github.com>
2026-06-20 10:30:18 +03:00
M57andM57 f5edf1569c fix(#141): notification tap opens original session instead of new session (#147)
Co-authored-by: M57 <hy4ri@users.noreply.github.com>
2026-06-20 10:10:10 +03:00
M57andM57 ae62b05e6d fix(#144): add timestamp to tool/command message bubbles (#145)
Co-authored-by: M57 <hy4ri@users.noreply.github.com>
2026-06-20 10:01:44 +03:00
M57andM57 7248f66abf feat(#136): visible copy button overlay on long-press of message bubbles (#143)
Co-authored-by: M57 <hy4ri@users.noreply.github.com>
2026-06-20 09:46:10 +03:00
M57andronia 113467a99d fix(#140): fix skills content API endpoints — path params to query params (#142)
Co-authored-by: ronia <ronia@m57>
2026-06-20 02:43:26 +03:00
M57andronia 261ee6379a feat(#132): dynamic session title with ellipsis truncation (#139)
Co-authored-by: ronia <ronia@m57>
2026-06-20 02:37:55 +03:00
M57andronia 913c6fa878 fix(#134): remove settings button from chat top bar (#138)
Co-authored-by: ronia <ronia@m57>
2026-06-20 02:28:36 +03:00
M57andronia 27ac4d72a4 fix(#133): only show status dot red when offline, hide when connected (#137)
Co-authored-by: ronia <ronia@m57>
2026-06-20 02:25:29 +03:00
M57 61d49d2355 fix(chat): don't reload cached msgs on SESSION_RESUME ack 2026-06-20 00:54:16 +03:00
M57 0fabad820d fix(chat): fix old session resume losing server session ID
* fix(chat): reset agent typing status when resuming old sessions

* fix(chat): fix race condition in websocket request registration

* test(chat): update mocks for new send/sendMessage onSent callback

* style(chat): use named onSent param instead of trailing lambda

* style(chat): fix import ordering for ConcurrentHashMap

* test(chat): fix remaining 2-arg verify calls for send()
2026-06-20 00:40:16 +03:00
M57 46b24593f9 feat(#58): implement skill markdown/yaml editor UI (#121) 2026-06-19 23:58:34 +03:00
M57 022e9de195 Merge pull request #120 from Hy4ri/feat/issue-116-notification-reply
feat(#116): add direct reply action to background notifications
2026-06-19 23:48:55 +03:00
M57 ad508be0fa Merge pull request #119 from Hy4ri/feat/issue-114-chat-notification
fix(#114): separate notification channels and set service to low priority
2026-06-19 23:41:27 +03:00
M57 b1c628ee24 Merge pull request #118 from Hy4ri/feat/issue-60-tool-json-parsing
feat(#60): human-readable tool JSON parsing in chat
2026-06-19 23:32:27 +03:00
M57 85dc48fcd6 Merge pull request #117 from Hy4ri/revert-pr-42
Revert "Merge pull request #42 from Hy4ri/feat/sessions-screen"
2026-06-19 23:24:36 +03:00
M57 7d50b5acd7 Merge pull request #42 from Hy4ri/feat/sessions-screen
feat: dedicated Sessions browser screen (Issue #40)
2026-06-19 23:14:40 +03:00
M57 ee97be50cb Merge pull request #113 from Hy4ri/refactor/issue-79-retrofit-error-handling
fix(#79): centralize retrofit error handling with NetworkResult
2026-06-19 23:03:21 +03:00
M57andM57 43df3c6e73 fix(#64): call wsClient.disconnect() directly in onCleared() instead of launching on cancelled scope (#94)
Co-authored-by: M57 <hy4ri@users.noreply.github.com>
2026-06-19 22:18:04 +03:00
M57andM57 abcec14cb5 feat(#76): add testTag identifiers to composable elements for UI test targeting (#98)
Adds testTag modifiers to key interactive elements across the core
composables, enabling Espresso/Compose UI tests to locate them:

Navigation.kt  — 'nav_*' on bottom bar items, 'drawer_*' on drawer items
HermesScaffold — 'back_button', 'menu_button', 'refresh_button'
StateViews.kt  — 'loading_state', 'loading_spinner', 'error_retry_button',
                 'empty_state_action'
ChatScreen.kt  — 'chat_input', 'send_button', 'interrupt_button'

Co-authored-by: M57 <hy4ri@users.noreply.github.com>
2026-06-19 22:15:53 +03:00
M57andM57 cc52442be3 fix(#65): request POST_NOTIFICATIONS runtime permission on Android 13+ (#97)
* fix(#65): request POST_NOTIFICATIONS runtime permission on Android 13+

On API 33+ the manifest declaration alone is not enough — the app must
request POST_NOTIFICATIONS via ActivityResultContracts.RequestPermission
at runtime before it can show any notification, including the foreground
service notification from ChatNotificationService.

- Added rememberLauncherForActivityResult for POST_NOTIFICATIONS
- Added LaunchedEffect(Unit) that fires the permission request on first
  composition when running on API 33+ and permission is not yet granted
- The next lifecycle event (ON_STOP → NotificationHelper.start) picks
  up the permission if granted

* fix: add missing import android.os.Build for POST_NOTIFICATIONS permission check

* fix: add missing import for rememberLauncherForActivityResult (androidx.activity.compose)

---------

Co-authored-by: M57 <hy4ri@users.noreply.github.com>
2026-06-19 22:15:47 +03:00
M57andM57 27a896c634 docs(#70): sync project structure in README with actual codebase (#96)
- Removed references to HermesControlApp.kt, EmptyState.kt, LoadingState.kt
  (none of these files exist)
- Replaced with StateViews.kt, SharedComponents.kt
- Added data/ws/ (WebSocket TUI Gateway layer)
- Added notification/ (ChatNotificationService foreground service)
- Added util/ (CronExpressionFormatter)
- Added missing theme files: HermesStatusColors.kt, Spacing.kt, Shapes.kt
- Added settings/ and connect/ screen directories

Co-authored-by: M57 <hy4ri@users.noreply.github.com>
2026-06-19 22:15:41 +03:00
M57andM57 451412851f fix(#69): replace mipmap launcher icon with proper notification vector drawable (#95)
Notification smallIcon must use a simple mono vector drawable, not a
launcher mipmap. Launcher icons render broken in the status bar on
many devices.

- Added app/src/main/res/drawable/ic_notification.xml (simple info icon)
- Updated both showReplyNotification and buildForegroundNotification to
  reference R.drawable.ic_notification instead of R.mipmap.ic_launcher

Co-authored-by: M57 <hy4ri@users.noreply.github.com>
2026-06-19 22:15:36 +03:00