sindresorhus / settings Goto Github PK
View Code? Open in Web Editor NEW⚙ Add a settings window to your macOS app in minutes
License: MIT License
⚙ Add a settings window to your macOS app in minutes
License: MIT License
I have been experimenting a bit with the SwiftUI additions to your framework and it would be nice if there was a documented way to attach an EnvironmentObject to a SwiftUI panel
Hi,
I want to manage the close event (click on red button on the top left).
in the app delegate I catch the function
func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool
in this event I want to call a function in the panels.
Is there a way to manage this?
Thanks
I make an app, just with statusbar and menu item. And I add preferences in the menu item.
But when the Preferences open, I can't use cmd+w close it. Only has to click red close button in the left up corner.
I used SwiftUI to build preference panels. However, when switching tabs, the view jumps with a weird animation. I feel this is because the SwiftUI view hasn't loaded when switching.
This only happens for the first time switching.
My current workaround is to disable the animation:
_ = PreferencesWindowController(
preferencePanes: [...],
style: .toolbarItems,
animated: false, // <---
hidesToolbarForSingleItem: true
)
Hi there,
So I was trying out this project because it looks great, but I'm having some trouble. First I tried the published version (0.2.1) in Cocoapods and it worked fine. However it doesn't include some of the recent changes such as using the segmented control. So I decided to use the version in master
instead.
Now with this I am having trouble. I simply created a new project and did what was explained in the README
(this project can be found here), and the preference window is not showing. It gets created and I can focus it, but it's not visible. I looked at the frame of the window, and it shows that the window has a height of 0 pixels... But I am not sure why that is happening...
I would really appreciate some help here 🙏
Thank you,
Kevin
Previously in Interface Builder I can achieve this by
using NSVisualEffectView in the main window
and set the panel material to "sidebar" (for better readability).
// This turns things non-transparent when window is not activated:
I don't know how to do this with this "Preference" package.
Could anyone please give me some instructions on where and how to modify?
Would be useful if we provide a default Preferences…
menu that opens the preferences window. Can be programmatically created or subclassed in Interface Builder. Should also include localization.
If the app is a menu bar app, we should also call NSApp.activate(ignoringOtherApps: true)
before showing the Preferences window.
There is a $80.00 open bounty on this issue. Add more on Issuehunt.
- Checkout the Issuehunt explorer to discover more funded issues.
- Need some help from other developers? Add your repositories on Issuehunt to raise funds.
Found this advice in the HIG today: https://developer.apple.com/design/human-interface-guidelines/macos/app-architecture/preferences/
So maybe after #6 is merged,
PreferencePane.toolbarTitle
to simply title
or preferencePaneTitle
This also makes #12 obsolete.
On High Sierra, I get this when I switch tabs:
*** Assertion failure in -[Preferences.PreferencesTabViewController transitionFromViewController:toViewController:options:completionHandler:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/AppKit/AppKit-1561.60.100/Controllers/NSViewController.m:925
Am investigating!
How do I use Preferences within SwiftUI app code? The only way I can see is to use Settings with a View.
WindowGroup
{
ContentView()
}
Settings
{
MyCustomSettingsView()
}
I personally don't really see the point of having a toolbar if there's only one preference pane and would like to hide it. I would still want to use this module though, so it's easy to add additional panes in the future.
So would be nice with a showToolbarForSinglePane
option.
@DivineDominion Thoughts?
divinedominion earned $60.00 by resolving this issue!
- Checkout the Issuehunt explorer to discover more funded issues.
- Need some help from other developers? Add your repositories on Issuehunt to raise funds.
Xcode 12.1
Just updated to version 2.1.0 and build now fails with following errors here:
(1) Cannot infer contextual base in reference to member 'preference'
(2) Value of type 'UserInteractionPausableWindow' has no member 'toolbarStyle'
PreferencesWindowController
(as a top-level member of the responder chain) doesnt forward any selectors to content, specifically the selected view controller. And since PWC is also final you can't subclass to do so. So there are 2 solutions:
open
so folks can subclass and handle responder chain actions at that layerI will make a PR that focus on option #2 as I prefer PWC to be pretty self contained and if all actions are forwarded properly, we can accomplish what we want at the VC level
Charts Environment
**Preference version Number:Master
**Xcode version:10.0
**Swift version:4.2
**macOS version running Xcode:10.14
i have a big problem
I do not know what to tell you
I'm just testing the program
2018-09-27 16:39:05.212472+0200 PreferencesExample[9389:1538460] [Layout] Unable to simultaneously satisfy constraints:
(
"<NSLayoutConstraint:0x600002121ae0 'NSStackView.Edge.Top' V:|-(>=0)-[_NSToolbarItemViewerLabelView:0x60000350c580] (active, names: '|':NSStackView:0x10120f2c0 )>",
"<NSLayoutConstraint:0x600002121b80 'NSStackView.Edge.Bottom' V:[_NSToolbarItemViewerLabelView:0x60000350c580]-(>=0)-| (active, names: '|':NSStackView:0x10120f2c0 )>",
"<NSLayoutConstraint:0x600002122260 NSToolbarButton:0x600003e08200.bottom <= NSStackView:0x10120f2c0.top - 2 (active)>",
"<NSLayoutConstraint:0x600002122210 V:|-(>=3)-[NSToolbarButton:0x600003e08200] (active, names: '|':NSToolbarItemViewer:0x10120eb50 )>",
"<NSLayoutConstraint:0x6000021222b0 NSStackView:0x10120f2c0.bottom == NSToolbarItemViewer:0x10120eb50.bottom - 4 (active)>",
"<NSLayoutConstraint:0x6000021223a0 'NSView-Encapsulated-Layout-Height' NSToolbarItemViewer:0x10120eb50.height == 1 (active)>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x600002121b80 'NSStackView.Edge.Bottom' V:[_NSToolbarItemViewerLabelView:0x60000350c580]-(>=0)-| (active, names: '|':NSStackView:0x10120f2c0 )>
Set the NSUserDefault NSConstraintBasedLayoutVisualizeMutuallyExclusiveConstraints to YES to have -[NSWindow visualizeConstraints:] automatically called when this happens. And/or, set a symbolic breakpoint on LAYOUT_CONSTRAINTS_NOT_SATISFIABLE to catch this in the debugger.
2018-09-27 16:39:05.213752+0200 PreferencesExample[9389:1538460] [Layout] Unable to simultaneously satisfy constraints:
(
"<NSLayoutConstraint:0x600002122260 NSToolbarButton:0x600003e08200.bottom <= NSStackView:0x10120f2c0.top - 2 (active)>",
"<NSLayoutConstraint:0x600002122210 V:|-(>=3)-[NSToolbarButton:0x600003e08200] (active, names: '|':NSToolbarItemViewer:0x10120eb50 )>",
"<NSLayoutConstraint:0x6000021222b0 NSStackView:0x10120f2c0.bottom == NSToolbarItemViewer:0x10120eb50.bottom - 4 (active)>",
"<NSLayoutConstraint:0x6000021223a0 'NSView-Encapsulated-Layout-Height' NSToolbarItemViewer:0x10120eb50.height == 1 (active)>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x600002122260 NSToolbarButton:0x600003e08200.bottom <= NSStackView:0x10120f2c0.top - 2 (active)>
Set the NSUserDefault NSConstraintBasedLayoutVisualizeMutuallyExclusiveConstraints to YES to have -[NSWindow visualizeConstraints:] automatically called when this happens. And/or, set a symbolic breakpoint on LAYOUT_CONSTRAINTS_NOT_SATISFIABLE to catch this in the debugger.
I don't always have time to do nice icons and would like to use this style:
Note how it's segmented controls in a narrow window toolbar.
NSTabView
actually has a style for this (which is also the default), but the segmented controls ends up in the window and not in the toolbar, like this:
Help appreciated 🙌
The only solution I can think of is to hide the NSTabView
tabs, put an NSSegmentedControl
centered in an NSToolbar
, listen to when the active segment changes, and then forward that to the NSTabView
. That is way more complicated than it should, so I'm hoping for someone to propose a better solution.
Instead of our custom solution: https://github.com/sindresorhus/Preferences/blob/main/Sources/Preferences/Localization.swift
See the initial attempt and feedback in #82
Would be nice if you could specify an array of SwiftUI Views
's instead of NSViewController
's.
Could probably use https://developer.apple.com/documentation/swiftui/nshostingcontroller for this.
Is there an option to force view size recalculation every time another tab is selected?
There is a $60.00 open bounty on this issue. Add more on Issuehunt.
- Checkout the Issuehunt explorer to discover more funded issues.
- Need some help from other developers? Add your repositories on Issuehunt to raise funds.
Thanks for the great project! Just wanted to mention that AFAICT if you are not using interface builder, then you need to write loadView()
manually in the controllers, otherwise you get a crash:
override func loadView() {
self.view = NSView()
}
If this is correct, then maybe it is worth mentioning in the README.
What do you think about adding breowser-like tab switching shortcuts?
By responding to Main Menu elements, this can even be customized.
Hi, I've just replaced the MASPreferences
with your package, amazing work! It works perfectly on macOS Big Sur 11.0.1.
But I've faced with next issue when I open the preferences window on macOS Catalina 10.15.6. My app crashes with this error:
function signature specialization <Arg[0] = Owned To Guaranteed, Arg[1] = Owned To Guaranteed> of SnipperApp_2.GeneralPreferencesController.init(nibName: Swift.String?, bundle: __C.NSBundle?) -> SnipperApp_2.GeneralPreferencesController GeneralPreferencesController.swift:0
SnipperApp 2
@objc SnipperApp_2.GeneralPreferencesController.init(nibName: Swift.String?, bundle: __C.NSBundle?) -> SnipperApp_2.GeneralPreferencesController <compiler-generated>:0
SnipperApp 2
SnipperApp_2.AppDelegate.preferencesWindowController.getter : Preferences.PreferencesWindowController <compiler-generated>:0
SnipperApp 2
function signature specialization <Arg[0] = Dead> of SnipperApp_2.AppDelegate.showPreferences(Swift.AnyObject) -> () AppDelegate.swift:420
SnipperApp 2
merged @objc SnipperApp_2.AppDelegate.showPreferences(Swift.AnyObject) -> ()
AppKit
-[NSApplication(NSResponder) sendAction:to:from:]
AppKit
-[NSMenuItem _corePerformAction]
AppKit
-[NSCarbonMenuImpl performActionWithHighlightingForItemAtIndex:]
AppKit
-[NSMenu performActionForItemAtIndex:]
AppKit
-[NSMenu _internalPerformActionForItemAtIndex:]
AppKit
-[NSCarbonMenuImpl _carbonCommandProcessEvent:handlerCallRef:]
AppKit
NSSLMMenuEventHandler
HIToolbox
DispatchEventToHandlers(EventTargetRec*, OpaqueEventRef*, HandlerCallRec*)
HIToolbox
SendEventToEventTargetInternal(OpaqueEventRef*, OpaqueEventTargetRef*, HandlerCallRec*)
HIToolbox
SendEventToEventTarget
HIToolbox
SendHICommandEvent(unsigned int, HICommand const*, unsigned int, unsigned int, unsigned char, void const*, OpaqueEventTargetRef*, OpaqueEventTargetRef*, OpaqueEventRef**)
HIToolbox
SendMenuCommandWithContextAndModifiers
HIToolbox
SendMenuItemSelectedEvent
HIToolbox
FinishMenuSelection(SelectionData*, MenuResult*, MenuResult*)
HIToolbox
MenuSelectCore(MenuData*, Point, double, unsigned int, OpaqueMenuRef**, unsigned short*)
HIToolbox
_HandleMenuSelection2
AppKit
_NSHandleCarbonMenuEvent
AppKit
_DPSEventHandledByCarbon
AppKit
-[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:]
AppKit
-[NSApplication run]
AppKit
NSApplicationMain
SnipperApp 2
main AppDelegate.swift:32
libdyld.dylib
start
Preferences version: 2.1.0
, installed via cocoapods.
Blocked by feedback-assistant/reports#71 as the expected behavior is not clear.
When we can eventually target macOS 10.15 in the far future, we could use NSToolbarItemGroup
instead of placing a segmented control in the toolbar.
https://developer.apple.com/documentation/appkit/nstoolbaritemgroup/selectionmode/selectone
https://developer.apple.com/documentation/appkit/nstoolbaritem/3237224-isbordered
https://developer.apple.com/documentation/appkit/nstoolbaritem/3237225-title
All the new APIs:
Added NSToolbarItemGroupSelectionMode
Added NSToolbarItemGroupSelectionModeSelectOne
Added NSToolbarItemGroupSelectionModeSelectAny
Added NSToolbarItemGroupSelectionModeMomentary
Added NSToolbarItemGroupControlRepresentation
Added NSToolbarItemGroupControlRepresentationAutomatic
Added NSToolbarItemGroupControlRepresentationExpanded
Added NSToolbarItemGroupControlRepresentationCollapsed
Added +[NSToolbarItemGroup groupWithItemIdentifier:titles:selectionMode:labels:target:action:]
Added +[NSToolbarItemGroup groupWithItemIdentifier:images:selectionMode:labels:target:action:]
Added NSToolbarItemGroup.controlRepresentation
Added NSToolbarItemGroup.selectionMode
Added NSToolbarItemGroup.selectedIndex
Added -[NSToolbarItemGroup setSelected:atIndex:]
Added -[NSToolbarItemGroup isSelectedAtIndex:]
http://codeworkshop.net/objc-diff/sdkdiffs/macos/10.15/AppKit.html
Even if I move it and close the window, the next time it opens in the same position.
I think it should open in the center the first time, and then remember the user's position from there. I think we need to use saveFrame(usingName:)
.
IssueHunt has been backed by the following sponsors. Become a sponsor
NSGridView can be used in Interface Builder in Xcode 10.
We should show how to do a realistic preferences window. It doesn't have to be functional, but it should look so.
Something like:
It should have a General
and Advanced
pane with some controls.
IssueHunt has been backed by the following sponsors. Become a sponsor
I was able to reproduce this issue many times on my second monitor.
However, I was not able to reproduce on my main monitor(the docker monitor)
If I switch my docker to the second monitor to make it become the main monitor, then the problem can be reproduced on the old main monitor(now it become new secondary monitor)
My iMac main monitor is 5k (retina). My secondary monitor is Apple cinema display which is 2560x1440 (non-retina)
macOS 10.14
There is a $80.00 open bounty on this issue. Add more on Issuehunt.
- Checkout the Issuehunt explorer to discover more funded issues.
- Need some help from other developers? Add your repositories on Issuehunt to raise funds.
Later this year.
preferencePaneIdentifier
to paneIdentifier
and preferencePaneTitle
to paneTitle
. And the preferencePanes
parameter to panes
.I was building https://github.com/Mortennn/Dozer and it has this Preferences
dependency. Just updated to v2.3.0 and failed to compile. Complies 👍🏼 with previous v2.2.1.
macOS 11.2.3 (20D91)
Xcode 12.4 (12D4e)
Build log: carthage-xcodebuild.vzJVzq.log
Creating a clean project and integrating Preferences with Carthage does not work.
Here is the project used for testing. test.zip
Preferences.podspec has a version of 0.2.1. The tag 0.2.1 seems not catch up with master branch.
Why is PreferencesWindowController
declared as final
? I would like to subclass it so I can do dependency injection. Any chance you could make it not final? Thanks!
Hi,
For macOS projets it's will be great to make your component Carthage compatible
Take a look at these articles:
On your README.md
add on top and add section for the installation with Carthage.
I just completed the German localization for an app of mine. The app's development language is English.
When I start the app in Xcode with the language set to German, everything's localized correctly except for the Preferences window's title:
Adding "Preferences" = "Einstellungen";
to my Localizable.strings did nothing. Is this a bug or am I missing something?
EDIT: I closed this again, after noticing that XCode has the same blue highlight, so it seems to be a Big Sur thing I wasn't aware of. Using a system icon already rendered the spacing much nicer.
An image speaks more than a thousand words, so let me post that first:
The following is all about the toolbar (not the content below):
I kept it as minimal and slim as possible. This is with XCode 12.2, Big Sur, dark theme. Ignore the two settings icons, I was too lazy to find a different icon. Thanks!
From the HIG:
Restore the last viewed preference pane. If the user switches preference panes, your app should remember this change and show the same pane immediately the next time the user opens your preferences window.
We don't currently do that. I think we should do it when users call .show()
without an argument, and mention in the docs that that should be the preferred way to show the preferences window, and refer to the HIG docs. This would be another benefit of having #14 and we could enforce it there.
divinedominion earned $80.00 by resolving this issue!
- Checkout the Issuehunt explorer to discover more funded issues.
- Need some help from other developers? Add your repositories on Issuehunt to raise funds.
Hi @sindresorhus, thank you for the nice product!
I'm using this package with Carthage.
When I archive and validate my app, I get an "Invalid Code Signature Identifier" error.
As I investigated, I found that if the framework has no dot characters in its bundle identifier, Xcode appends auto-generated string to signing identifier.
And this causes the "Invalid Code Signature Identifier" error.
sindresorhus/KeyboardShortcuts seems to have the same problem, so I'd recommend prepending com.sindresorhus.
or something to their bundle identifier.
My environment:
One is enough. It will better to use a static shared instance instead of the Public init().
I have a need to add a 'Revert' item to my preferences toolbar. I would like this item to be placed on the right of the toolbar with a flexible space between it and the other items. The flexible space pushes the item all the way to the right. I don't see an obvious way to do this in your framework. Is it possible?
Thanks!
When there are multiple tabs, the window menu would look like:
Where General
is the preferences window title. However, I feel it's not clear enough to the user that General
mean the preferences window. Also, what if the main window has a name that is the same or close to the preferences tab name. That would be confusing.
When there's no tabs, the HIG says that the window title should be the app name and then Preferences
, but that can look weird:
The macOS Human Interface Guidelines doesn't say anything about this.
My preference would be to use Preferences — General
for the title in the Window menu when there are multiple tabs, and Preferences
when there's none.
Changing the title of only the "Window" menu items is possible with:
NSApp.changeWindowsItem(window, title: "Preferences — General", filename: false)
Thoughts?
It's probably due to rounding errors. In any case, there is probably a way to fix the jiggling during the transition.
There is a $80.00 open bounty on this issue. Add more on Issuehunt.
- Checkout the Issuehunt explorer to discover more funded issues.
- Need some help from other developers? Add your repositories on Issuehunt to raise funds.
I have a section containing only one SwiftUI List
view. How can I top-align the section title with and the list?
Can I achieve this with current version of Preference
?
If not, maybe offer a parameter to customize this? I think I can help with it becuase I really need this.
The code:
struct ColorThemePane: View {
let colorThemeOptions = ColorTheme.allCases
@State var selectKeeper: Set<ColorTheme> = [Defaults[.colorTheme]]
var body: some View {
Preferences.Container(contentWidth: Preferences.PaneWidth) {
Preferences.Section(title: "Color Theme:", bottomDivider: true) {
List(colorThemeOptions, id: \.self, selection: $selectKeeper){ name in
Text(name.rawValue)
}.listStyle(PlainListStyle())
.frame(width: 290, height: 150)
.cornerRadius(6)
}
}
}
}
Related: #56
Is there a specific reason for having a higher macOS version requirement enforced for the Swift Package Manager?
With the following declaration, the ability to programmatically select a tab is hidden.
private let tabViewController = PreferencesTabViewController()
I suggest we make the following changes/additions in PreferencesWindowController ...
public func showWindow(tabIndex: Int = 0) {
if !window!.isVisible {
window?.center()
}
if tabIndex >= 0 && tabIndex < tabViewController.tabView.numberOfTabViewItems {
tabViewController.tabView.selectTabViewItem(at: tabIndex)
}
showWindow(self)
NSApp.activate(ignoringOtherApps: true)
}
public func selectTab(tabIndex: Int) {
if tabIndex >= 0 && tabIndex < tabViewController.tabView.numberOfTabViewItems {
tabViewController.tabView.selectTabViewItem(at: tabIndex)
}
}
We could provide .general
, .advanced
, .updates
and maybe .license
:
Since almost everyone would have a
General
preference tab. I wonder if we should ship with aPreferenableGeneral
type thing that has all these fields already filled out. My goal is to require the least amount of boilerplate possible to set up a preferences window. Thoughts?We could do this for
Advanced
too. And eventually even ship some localizations for those, so users don't have to care about that either.
(Originally posted by @sindresorhus in #6)
There is a $60.00 open bounty on this issue. Add more on Issuehunt.
- Checkout the Issuehunt explorer to discover more funded issues.
- Need some help from other developers? Add your repositories on Issuehunt to raise funds.
See #47 (If anyone wants to work on this, they can continue where that PR left off)
I noticed that in some apps, the preferences window doesn't show up in the Window
menu. But there's of course no consistency on this.
Apple Feedback Assistant report: feedback-assistant/reports#111
Window
menuBased on my findings, I'm leaning towards keeping it in the Window
menu. But I'm looking for more opinions.
When animating to a preference pane that has not been loaded before and has a larger width than the current pane the view is not correctly laid out initially, which causes an odd animation. The animation is correct in subsequent switches.
The example below is the example app with the width = 450 constraint removed from the Advanced tab, and the app set to open to the Advanced tab.
I'm trying to figure out the exact scenarios that causes this. Starting on Accounts does not cause this same animation to happen so I'm not sure how the size change and animations are linked.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.