Releases: kdroidFilter/ComposeNativeTray
1.0.4
TrayApp : Adjust outside click detection for DPI scaling onj Windows
Full Changelog: v1.0.3...v1.0.4
1.0.3
Improve tray position detection on Windows Hdpi
Full Changelog: v1.0.2...v1.0.3
1.0.2
What's Changed
- Update init time of macos trayApp by @kdroidFilter in #323
Full Changelog: v1.0.1...v1.0.2
1.0.1
What's Changed
- Refactor and enhance tray window dismissal behavior in TrayApp by @kdroidFilter in #319
- Refactor and improve
TrayAppimplementation and dialog management by @kdroidFilter in #320 - Update
TrayAppwith new parameters and enhanced documentation by @kdroidFilter in #321 - Refactor dialog positioning and transition animations in TrayApp by @kdroidFilter in #322
Full Changelog: v1.0.0...v1.0.1
1.0.0
🎉 ComposeNativeTray 1.0.0
ComposeNativeTray has reached its first stable release!
The library is now considered production-ready across Windows, macOS, and Linux.
👉 Note: TrayApp remains marked as experimental, but continues to evolve rapidly.
🏆 Stability Milestone
- Core APIs are now stable and production-safe
- Public API surface is frozen (non-experimental parts)
- Numerous fixes contributed by production users
✨ New: TrayWindowDismissMode
- Introduce
TrayWindowDismissModefor dismiss behavior control by @kdroidFilter in #316 - Bump jna from 5.18.0 to 5.18.1 by @dependabot[bot] in #312
The TrayApp popup window can now be configured with different dismiss behaviors:
-
AUTO (default)
The popup automatically hides when focus is lost or the user clicks outside (previous behavior). -
MANUAL
The popup stays visible until you explicitly calltrayAppState.hide().
Perfect for dashboards, overlays, or scenarios where the user should decide when to close.
val trayAppState = rememberTrayAppState(
initialDismissMode = TrayWindowDismissMode.MANUAL
)Switch at runtime:
trayAppState.setDismissMode(TrayWindowDismissMode.AUTO)Full Changelog: v0.9.8...v1.0.0
0.9.8
What's Changed
- Refactor TrayApp visibility and dialog positioning logic by @kdroidFilter in #311
Full Changelog: v0.9.7...v0.9.8
0.9.7
What's Changed
- Improve TrayApp window positioning and state management by @kdroidFilter in #310
Full Changelog: v0.9.6...v0.9.7
0.9.6
What's Changed
- Preserve component states and update TrayApp management by @kdroidFilter in #309
Full Changelog: v0.9.5...v0.9.6
0.9.5
📦 ComposeNativeTray 0.9.5
This release fixes a critical state preservation issue in TrayApp - component states are now properly maintained when toggling the popup window visibility.
🐛 Critical Fix: State Preservation
Problem: Hiding the popup window destroyed all internal states (text inputs, selections, scroll positions)
Solution: The window now remains in the composition tree with controlled visibility
// Before: States were lost
if (shouldShowWindow) {
DialogWindow(...) { content() }
}
// After: States are preserved
DialogWindow(
visible = shouldShowWindow, // Control visibility without unmounting
...
) { content() }✨ What's Fixed
- Text fields, checkboxes, and forms retain their values
- Scroll positions are maintained
- Running animations continue smoothly
- No more content resets when reopening the popup
📝 Notes
- Fully backwards compatible - no code changes required
- Performance improvement - no component recreation overhead
- Works across all platforms (Windows, macOS, Linux)
Full Changelog: v0.9.4...v0.9.5
0.9.4
📦 ComposeNativeTray 0.9.4
This release introduces TrayAppState, a powerful state management API for the experimental TrayApp feature, providing programmatic control over popup windows and reactive state observation.
🎯 Major Enhancement: TrayAppState API
The experimental TrayApp now includes comprehensive state management through TrayAppState, enabling:
-
Programmatic Control
show()/hide()/toggle()- Control popup visibility from anywhere in your codesetWindowSize(DpSize)- Dynamically resize the popup window- No more relying solely on user clicks - full API control
-
Reactive State Observation
isVisible: StateFlow<Boolean>- Track popup visibility in real-timewindowSize: StateFlow<DpSize>- Monitor window size changesonVisibilityChanged(callback)- Get notified when visibility changes- Seamless integration with Compose's
collectAsState()
-
Simplified API
rememberTrayAppState()- Convenient state creation and persistence- Initial configuration via constructor parameters
- Bidirectional updates (user actions and programmatic changes)
🔄 Migration Guide
Before (0.9.0 - 0.9.3):
TrayApp(
icon = Icons.Default.Window,
tooltip = "My App",
windowSize = DpSize(300.dp, 500.dp),
visibleOnStart = true,
menu = { /* ... */ }
) {
// Popup content
}After (0.9.4+):
val trayAppState = rememberTrayAppState(
initialWindowSize = DpSize(300.dp, 500.dp),
initiallyVisible = true
)
// Observe state changes
val isVisible by trayAppState.isVisible.collectAsState()
TrayApp(
state = trayAppState, // Pass the state
icon = Icons.Default.Window,
tooltip = "My App",
menu = { /* ... */ }
) {
// Popup content
}
// Control from anywhere
Button(onClick = { trayAppState.toggle() }) {
Text("Toggle Popup")
}Key Changes:
- Replace
windowSizeparameter → Usestate.setWindowSize() - Replace
visibleOnStartparameter → UseinitiallyVisibleinrememberTrayAppState() - Add
stateparameter → Pass theTrayAppStateinstance - New control capabilities → Call state methods from any composable or coroutine
✨ New Capabilities
-
Control from Main Window
// In your main window Button(onClick = { trayAppState.show() }) { Text("Show Tray Popup") }
-
Dynamic Resizing
// Change size based on content or user preference trayAppState.setWindowSize(400.dp, 600.dp)
-
State Synchronization
// React to visibility changes LaunchedEffect(trayAppState) { trayAppState.onVisibilityChanged { visible -> println("Popup is now ${if (visible) "visible" else "hidden"}") } }
📝 Notes
- This is a breaking change for TrayApp users (experimental API)
- No changes to the stable
TrayAPI - State persistence across recompositions is handled automatically
- Compatible with all existing TrayApp features (animations, menus, etc.)
Full Changelog: v0.9.3...v0.9.4