david-swift / SettingsKit-macOS

Add a settings window to a SwiftUI macOS app
https://david-swift.github.io/SettingsKit-macOS/
MIT License
87 stars 2 forks source link

Disable the "No Selection" behavior #5

Open longseespace opened 1 year ago

longseespace commented 1 year ago

Is your feature request related to a problem? Please describe.

This feature doesn't make sense when the user always need to edit something on the sidebar. A misclick might render the "No selection" screen which is just a text "No row selected" etc. Which is kinda annoying.

Describe the solution you'd like

Allow developers to specify the behavior. Maybe show "No selection" screen only if there is no rows in the sidebar. Otherwise, always select one row.

Describe alternatives you've considered

Not sure.

Additional context

This is for SettingsSubtab

david-swift commented 1 year ago

You are right, @longseespace! I've changed the behavior in SettingsKit 0.1.10.

If the user clicks in the space under the last item in the sidebar list, the last item is selected (instead of switching to "No Selection").

If the subtabs change...

The "No Selection" subtab is only displayed if no other subtabs are available (e.g. if a user removes every item from a list or if a "static" tab does not contain multiple subtabs).

longseespace commented 1 year ago

@david-swift I think when user click the space under the list, we should not change the selection at all. They usually do it because of a misclick and not because they wanted to select the last item 🤔

Here is what I propose:

When the Main tab first appear, we automatically select the first item.

Clicking on the space under the list won't change selection. Treat it as a misclick

Adding a new item would select it automatically

david-swift commented 1 year ago

@longseespace Currently, when the tab first appears, the first item is selected. When the tab is opened again later, the item that has been selected before closing the settings the last time is selected. That is the behavior you describe, right?

Yes, I don't think people would click in the space under the list to select the last item - I'll change that.

Adding a new item does select it automatically in version 0.1.10:

https://github.com/david-swift/SettingsKit-macOS/assets/106754840/1317aef3-0393-4ded-aac9-cb417fc57738

david-swift commented 1 year ago

Oh I see, I should not assume that the new item is always the last one. I'll change that.

david-swift commented 1 year ago

Clicking on the space under the list won't change selection. Treat it as a misclick

Solving that problem is quite difficult as the space under the list actually is part of the SwiftUI list, and SwiftUI handles a click in that region as deselecting any selection. For macOS 13 or later, there is an initializer for a non-optional selection type (that one) without that behavior, but for macOS 12, there is only this initializer. A click in this area sets the selection value to nil which results in losing the information about the item that has been selected before deselecting the item.

Prohibiting any change if the newly selected value is nil does not seem to be working for some reason:

List(
    contentWithoutNoSelectionSubtabs,
    selection: model.selectedSubtabs[id].binding { newValue in
        if newValue != nil {
            model.selectedSubtabs[id] = newValue
        }
    }
) { subtab in
    // ...
}

Maybe you have some (not too hacky) solution, @longseespace? Otherwise, I could solve the problem for macOS 13 or later, but it would remain a problem in macOS 12.

longseespace commented 1 year ago

@david-swift Ahhh, that makes sense. I didn't know the API was only available on macOS 13 or later. Sounds good, we should fix for the macOS 13 first and I will find a solution for macOS 12.

Edit: actually I changed my mind. I think the behavior should be consistent. I checked and looks like this behavior (show No Selection when clicking the empty space) is common in many other native apps. So you decide what it's gonna be 🤔

david-swift commented 1 year ago

I really like the behavior with the initializer with the non-optional selection value (treating it as a misclick).

  1. If a new subtab has been added, select that one (#4).
  2. If a subtab has been removed:
    1. Select the subtab that has now the same index, if there is one.
    2. Otherwise, select the subtab that has an index one lower than the current, if there is one.
    3. Otherwise, try to select the last subtab in the list. Normally, that should fail, so show the "No Selection" view (there aren't any items available).
  3. If the number of items has not changed, but the selection is invalid, select the last item. This gets called in macOS 12 when deselecting the value, or in macOS 12 and 13+ when the view appears for the first time. If there are no items available, show the "No Selection" view.

Is that behavior ok for you, @longseespace? It isn't consistent between macOS 12 and 13+, but I really like the idea that no selection is only possible if there are no subtabs available, and that a click below the list is handled as a misclick wherever possible.

longseespace commented 1 year ago

Yes, sounds great. Let's do it.

david-swift commented 1 year ago

I've implemented this behavior with release 0.1.11. I'll keep that issue open as there is still no elegant solution for misclicks for macOS 12, but close issue #4.

Thanks for opening those issues, @longseespace!