Skip to content

Releases: kdroidFilter/ComposeNativeTray

1.0.4

08 Oct 19:41

Choose a tag to compare

TrayApp : Adjust outside click detection for DPI scaling onj Windows

Full Changelog: v1.0.3...v1.0.4

1.0.3

08 Oct 18:45

Choose a tag to compare

Improve tray position detection on Windows Hdpi
Full Changelog: v1.0.2...v1.0.3

1.0.2

05 Oct 20:10
de7ffc4

Choose a tag to compare

What's Changed

Full Changelog: v1.0.1...v1.0.2

1.0.1

05 Oct 05:26
596a8dc

Choose a tag to compare

What's Changed

  • Refactor and enhance tray window dismissal behavior in TrayApp by @kdroidFilter in #319
  • Refactor and improve TrayApp implementation and dialog management by @kdroidFilter in #320
  • Update TrayApp with 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

03 Oct 14:28
379204b

Choose a tag to compare

🎉 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

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 call trayAppState.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

30 Sep 11:55
9c71e50

Choose a tag to compare

What's Changed

Full Changelog: v0.9.7...v0.9.8

0.9.7

30 Sep 08:38
f877070

Choose a tag to compare

What's Changed

Full Changelog: v0.9.6...v0.9.7

0.9.6

30 Sep 03:57
df54fe5

Choose a tag to compare

What's Changed

Full Changelog: v0.9.5...v0.9.6

0.9.5

30 Sep 03:26
e523ee3

Choose a tag to compare

📦 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

29 Sep 08:09
f810e5e

Choose a tag to compare

📦 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 code
    • setWindowSize(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-time
    • windowSize: StateFlow<DpSize> - Monitor window size changes
    • onVisibilityChanged(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:

  1. Replace windowSize parameter → Use state.setWindowSize()
  2. Replace visibleOnStart parameter → Use initiallyVisible in rememberTrayAppState()
  3. Add state parameter → Pass the TrayAppState instance
  4. 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 Tray API
  • State persistence across recompositions is handled automatically
  • Compatible with all existing TrayApp features (animations, menus, etc.)

Full Changelog: v0.9.3...v0.9.4