├── .gitignore
├── Fluor.xcodeproj
├── project.pbxproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── swiftpm
│ │ └── Package.resolved
└── xcshareddata
│ └── xcschemes
│ └── Fluor.xcscheme
├── Fluor
├── Assets.xcassets
│ ├── About.imageset
│ │ ├── AboutDark.png
│ │ ├── AboutDark@2x.png
│ │ ├── AboutLight.png
│ │ ├── AboutLight@2x.png
│ │ └── Contents.json
│ ├── App.imageset
│ │ ├── Contents.json
│ │ ├── RealAppDark.png
│ │ ├── RealAppDark@2x.png
│ │ ├── RealAppLight.png
│ │ └── RealAppLight@2x.png
│ ├── AppIcon.appiconset
│ │ ├── 128.png
│ │ ├── 128@2x.png
│ │ ├── 16.png
│ │ ├── 16@2x.png
│ │ ├── 256.png
│ │ ├── 256@2x.png
│ │ ├── 32.png
│ │ ├── 32@2x.png
│ │ ├── 512.png
│ │ ├── 512@2x.png
│ │ └── Contents.json
│ ├── AppSwitch.imageset
│ │ ├── AppSwitchDark.png
│ │ ├── AppSwitchDark@2x.png
│ │ ├── AppSwitchLight.png
│ │ ├── AppSwitchLight@2x.png
│ │ └── Contents.json
│ ├── AppleMode.imageset
│ │ ├── AppleMode.png
│ │ ├── AppleMode@2x.png
│ │ └── Contents.json
│ ├── ArrowBackward.imageset
│ │ ├── ArrowBackwardDark.png
│ │ ├── ArrowBackwardDark@2x.png
│ │ ├── ArrowBackwardLight.png
│ │ ├── ArrowBackwardLight@2x.png
│ │ └── Contents.json
│ ├── ArrowForward.imageset
│ │ ├── ArrowButtonDark.png
│ │ ├── ArrowButtonDark@2x.png
│ │ ├── ArrowButtonLight.png
│ │ ├── ArrowButtonLight@2x.png
│ │ └── Contents.json
│ ├── ButtonGithub.imageset
│ │ ├── ButtonGithubDark.png
│ │ ├── ButtonGithubDark@2x.png
│ │ ├── ButtonGithubLight.png
│ │ ├── ButtonGithubLight@2x.png
│ │ └── Contents.json
│ ├── ButtonTwitter.imageset
│ │ ├── ButtonTwitterDark.png
│ │ ├── ButtonTwitterDark@2x.png
│ │ ├── ButtonTwitterLight.png
│ │ ├── ButtonTwitterLight@2x.png
│ │ └── Contents.json
│ ├── ButtonWeb.imageset
│ │ ├── ButtonWebDark.png
│ │ ├── ButtonWebDark@2x.png
│ │ ├── ButtonWebLight.png
│ │ ├── ButtonWebLight@2x.png
│ │ └── Contents.json
│ ├── CheckDisabled.imageset
│ │ ├── CheckDisabledDark.png
│ │ ├── CheckDisabledDark@2x.png
│ │ ├── CheckDisabledLight.png
│ │ ├── CheckDisabledLight@2x.png
│ │ └── Contents.json
│ ├── CheckEnabled.imageset
│ │ ├── CheckEnabledDark.png
│ │ ├── CheckEnabledDark@2x.png
│ │ ├── CheckEnabledLight.png
│ │ ├── CheckEnabledLight@2x.png
│ │ └── Contents.json
│ ├── CheckMixed.imageset
│ │ ├── CheckMixedDark.png
│ │ ├── CheckMixedDark@2x.png
│ │ ├── CheckMixedLight.png
│ │ ├── CheckMixedLight@2x.png
│ │ └── Contents.json
│ ├── Contents.json
│ ├── Cross.imageset
│ │ ├── Contents.json
│ │ ├── CrossDark.png
│ │ ├── CrossDark@2x.png
│ │ ├── CrossLight.png
│ │ └── CrossLight@2x.png
│ ├── DefaultMode.imageset
│ │ ├── Contents.json
│ │ ├── DefaultModeDark.png
│ │ ├── DefaultModeDark@2x.png
│ │ ├── DefaultModeLight.png
│ │ └── DefaultModeLight@2x.png
│ ├── DoubleArrowForward.imageset
│ │ ├── Contents.json
│ │ ├── DoubleArrowButtonDark.png
│ │ ├── DoubleArrowButtonDark@2x.png
│ │ ├── DoubleArrowButtonLight.png
│ │ └── DoubleArrowButtonLight@2x.png
│ ├── FluorBlue.colorset
│ │ └── Contents.json
│ ├── FluorRed.colorset
│ │ └── Contents.json
│ ├── FnKey.imageset
│ │ ├── Contents.json
│ │ ├── FnKeyDark.png
│ │ ├── FnKeyDark@2x.png
│ │ ├── FnKeyLight.png
│ │ └── FnKeyLight@2x.png
│ ├── IconAppleMode.imageset
│ │ ├── Contents.json
│ │ ├── IconAppleMode.png
│ │ └── IconAppleMode@2x.png
│ ├── IconDisabled.imageset
│ │ ├── Contents.json
│ │ ├── IconDisabled.png
│ │ └── IconDisabled@2x.png
│ ├── IconOtherMode.imageset
│ │ ├── Contents.json
│ │ ├── IconOtherMode.png
│ │ └── IconOtherMode@2x.png
│ ├── LighIconDisabled.imageset
│ │ ├── Contents.json
│ │ ├── LighIconDisabled.png
│ │ └── LighIconDisabled@2x.png
│ ├── MixedSwitch.imageset
│ │ ├── Contents.json
│ │ ├── MixedSwitchDark.png
│ │ ├── MixedSwitchDark@2x.png
│ │ ├── MixedSwitchLight.png
│ │ └── MixedSwitchLight@2x.png
│ ├── OtherMode.imageset
│ │ ├── Contents.json
│ │ ├── OtherMode.png
│ │ └── OtherMode@2x.png
│ ├── Preferences.imageset
│ │ ├── Contents.json
│ │ ├── PreferencesDark.png
│ │ ├── PreferencesDark@2x.png
│ │ ├── PreferencesLight.png
│ │ └── PreferencesLight@2x.png
│ ├── QuestionMark.imageset
│ │ ├── Contents.json
│ │ ├── QuestionMark.png
│ │ └── QuestionMark@2x.png
│ ├── Quit.imageset
│ │ ├── Contents.json
│ │ ├── Quit.png
│ │ └── Quit@2x.png
│ ├── Rules.imageset
│ │ ├── Contents.json
│ │ ├── RulesDark.png
│ │ ├── RulesDark@2x.png
│ │ ├── RulesLight.png
│ │ └── RulesLight@2x.png
│ ├── RunningApps.imageset
│ │ ├── Contents.json
│ │ ├── RunningAppsDark.png
│ │ ├── RunningAppsDark@2x.png
│ │ ├── RunningAppsLight.png
│ │ └── RunningAppsLight@2x.png
│ └── Service.imageset
│ │ ├── Contents.json
│ │ ├── ServiceDark.png
│ │ ├── ServiceDark@2x.png
│ │ ├── ServiceLight.png
│ │ └── ServiceLight@2x.png
├── Base.lproj
│ ├── About.storyboard
│ ├── Main.xib
│ ├── MainMenu.xib
│ ├── Preferences.storyboard
│ ├── RulesEditor.storyboard
│ ├── RunningApps.storyboard
│ └── Welcome.storyboard
├── Controllers
│ ├── BehaviorController.swift
│ ├── LaunchAtLoginController.h
│ ├── LaunchAtLoginController.m
│ ├── MenuItemsController.swift
│ ├── StatusMenuController.swift
│ ├── ViewControllers
│ │ ├── AboutViewController.swift
│ │ ├── CurrentAppViewController.swift
│ │ ├── DefaultModeViewController.swift
│ │ ├── PreferencesTabViewController.swift
│ │ ├── ReleaseNotesViewController.swift
│ │ ├── RulesEditorViewController.swift
│ │ ├── RunningAppsViewController.swift
│ │ ├── SwitchMethodSelectionViewController.swift
│ │ ├── SwitchMethodViewController.swift
│ │ └── UserNotificationEnablementViewController.swift
│ └── WindowControllers
│ │ ├── AboutWindowController.swift
│ │ ├── PreferencesWindowController.swift
│ │ ├── ReleaseNotesWindowController.swift
│ │ ├── RulesEditorWindowController.swift
│ │ └── RunningAppWindowController.swift
├── Extensions
│ ├── NSStoryboardNamesExtension.swift
│ ├── NSViewExtension.swift
│ ├── ResultExtension.swift
│ └── SetExtension.swift
├── Fluor-Bridging-Header.h
├── Fluor.entitlements
├── Info.plist
├── Misc
│ ├── AppDelegate.swift
│ ├── AppErrorManager.swift
│ ├── FKeyManager.swift
│ ├── PFMoveApplication.h
│ ├── PFMoveApplication.m
│ ├── TableViewContentAnimator.swift
│ └── UserNotificationHelper.swift
├── Models
│ ├── AppManager.swift
│ ├── Enums.swift
│ ├── Items.swift
│ ├── Release.swift
│ └── RuleValueTransformer.swift
├── Protocols
│ ├── NotificationHelpers.swift
│ └── StoryboardInstantiableProtocol.swift
├── ReleaseNotes.rtf
├── Views
│ ├── CheckableMenuItem.swift
│ ├── LinkButton.swift
│ ├── MenuItemView.swift
│ ├── MoverEffectView.swift
│ ├── MoverImageView.swift
│ ├── MultilinesCheckBoxLabel.swift
│ ├── PoppingLinkButton.swift
│ ├── RuleCellView.swift
│ └── SelectableBox.swift
├── dsa_pub.pem
├── en.lproj
│ └── Localizable.strings
├── fr.lproj
│ ├── About.strings
│ ├── Localizable.strings
│ ├── MainMenu.strings
│ ├── Preferences.strings
│ ├── RulesEditor.strings
│ └── RunningApps.strings
└── zh-Hans.lproj
│ ├── About.strings
│ ├── Localizable.strings
│ ├── MainMenu.strings
│ ├── Preferences.strings
│ ├── RulesEditor.strings
│ └── RunningApps.strings
├── LICENSE
├── README.md
└── ressources
├── banner.png
├── mainmenu.png
├── preferences.png
├── ruleseditor.png
├── runningapps.png
└── statusbar.png
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 |
3 | ## Build generated
4 | build/
5 | DerivedData/
6 |
7 | ## Various settings
8 | *.pbxuser
9 | !default.pbxuser
10 | *.mode1v3
11 | !default.mode1v3
12 | *.mode2v3
13 | !default.mode2v3
14 | *.perspectivev3
15 | !default.perspectivev3
16 | xcuserdata/
17 |
18 | ## Other
19 | *.moved-aside
20 | *.xccheckout
21 | *.xcscmblueprint
22 |
23 | ## Obj-C/Swift specific
24 | *.hmap
25 | *.ipa
26 |
27 | ## Playgrounds
28 | timeline.xctimeline
29 | playground.xcworkspace
30 |
31 | # Swift Package Manager
32 | #
33 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
34 | # Packages/
35 | .build/
36 |
37 | # CocoaPods
38 | #
39 | # We recommend against adding the Pods directory to your .gitignore. However
40 | # you should judge for yourself, the pros and cons are mentioned at:
41 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
42 | #
43 | # Pods/
44 |
45 | # Carthage
46 | #
47 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
48 | # Carthage/Checkouts
49 |
50 | Carthage/Build
51 |
52 | # fastlane
53 | #
54 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
55 | # screenshots whenever they are needed.
56 | # For more information about the recommended setup visit:
57 | # https://github.com/fastlane/fastlane/blob/master/docs/Gitignore.md
58 |
59 | fastlane/report.xml
60 | fastlane/screenshots
61 |
62 | # Documentation
63 | Documentation/docs
64 | /Fluor/Sparkle.framework
65 | /Fluor/Sparkle.framework.dSYM
66 |
--------------------------------------------------------------------------------
/Fluor.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Fluor.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Fluor.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved:
--------------------------------------------------------------------------------
1 | {
2 | "object": {
3 | "pins": [
4 | {
5 | "package": "CoreGeometry",
6 | "repositoryURL": "https://gitlab.com/Pyroh/CoreGeometry.git",
7 | "state": {
8 | "branch": null,
9 | "revision": "a59affa331972263980f8a2af4cfd5f37ad42d3d",
10 | "version": "3.0.0"
11 | }
12 | },
13 | {
14 | "package": "DefaultsWrapper",
15 | "repositoryURL": "https://github.com/Pyroh/DefaultsWrapper.git",
16 | "state": {
17 | "branch": null,
18 | "revision": "649794e5c7af45f69d1e128a3c9fd0fe1cde282e",
19 | "version": "1.2.0"
20 | }
21 | },
22 | {
23 | "package": "SmoothOperators",
24 | "repositoryURL": "https://github.com/Pyroh/SmoothOperators.git",
25 | "state": {
26 | "branch": null,
27 | "revision": "12f0d7cc9ade6bc826a822f9d2021b4dd394c4a0",
28 | "version": "0.4.0"
29 | }
30 | }
31 | ]
32 | },
33 | "version": 1
34 | }
35 |
--------------------------------------------------------------------------------
/Fluor.xcodeproj/xcshareddata/xcschemes/Fluor.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
11 |
14 |
15 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
33 |
39 |
40 |
41 |
42 |
43 |
48 |
49 |
55 |
56 |
57 |
58 |
59 |
60 |
71 |
73 |
79 |
80 |
81 |
82 |
86 |
87 |
88 |
89 |
95 |
97 |
103 |
104 |
105 |
106 |
108 |
109 |
112 |
113 |
115 |
118 |
119 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/About.imageset/AboutDark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/About.imageset/AboutDark.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/About.imageset/AboutDark@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/About.imageset/AboutDark@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/About.imageset/AboutLight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/About.imageset/AboutLight.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/About.imageset/AboutLight@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/About.imageset/AboutLight@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/About.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "filename" : "AboutLight.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "mac",
10 | "filename" : "AboutDark.png",
11 | "appearances" : [
12 | {
13 | "appearance" : "luminosity",
14 | "value" : "dark"
15 | }
16 | ],
17 | "scale" : "1x"
18 | },
19 | {
20 | "idiom" : "mac",
21 | "filename" : "AboutLight@2x.png",
22 | "scale" : "2x"
23 | },
24 | {
25 | "idiom" : "mac",
26 | "filename" : "AboutDark@2x.png",
27 | "appearances" : [
28 | {
29 | "appearance" : "luminosity",
30 | "value" : "dark"
31 | }
32 | ],
33 | "scale" : "2x"
34 | }
35 | ],
36 | "info" : {
37 | "version" : 1,
38 | "author" : "xcode"
39 | },
40 | "properties" : {
41 | "template-rendering-intent" : "template"
42 | }
43 | }
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/App.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "RealAppLight.png",
5 | "idiom" : "mac",
6 | "scale" : "1x"
7 | },
8 | {
9 | "appearances" : [
10 | {
11 | "appearance" : "luminosity",
12 | "value" : "dark"
13 | }
14 | ],
15 | "filename" : "RealAppDark.png",
16 | "idiom" : "mac",
17 | "scale" : "1x"
18 | },
19 | {
20 | "filename" : "RealAppLight@2x.png",
21 | "idiom" : "mac",
22 | "scale" : "2x"
23 | },
24 | {
25 | "appearances" : [
26 | {
27 | "appearance" : "luminosity",
28 | "value" : "dark"
29 | }
30 | ],
31 | "filename" : "RealAppDark@2x.png",
32 | "idiom" : "mac",
33 | "scale" : "2x"
34 | }
35 | ],
36 | "info" : {
37 | "author" : "xcode",
38 | "version" : 1
39 | },
40 | "properties" : {
41 | "template-rendering-intent" : "template"
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/App.imageset/RealAppDark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/App.imageset/RealAppDark.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/App.imageset/RealAppDark@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/App.imageset/RealAppDark@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/App.imageset/RealAppLight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/App.imageset/RealAppLight.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/App.imageset/RealAppLight@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/App.imageset/RealAppLight@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/AppIcon.appiconset/128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/AppIcon.appiconset/128.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/AppIcon.appiconset/128@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/AppIcon.appiconset/128@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/AppIcon.appiconset/16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/AppIcon.appiconset/16.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/AppIcon.appiconset/16@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/AppIcon.appiconset/16@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/AppIcon.appiconset/256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/AppIcon.appiconset/256.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/AppIcon.appiconset/256@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/AppIcon.appiconset/256@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/AppIcon.appiconset/32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/AppIcon.appiconset/32.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/AppIcon.appiconset/32@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/AppIcon.appiconset/32@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/AppIcon.appiconset/512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/AppIcon.appiconset/512.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/AppIcon.appiconset/512@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/AppIcon.appiconset/512@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "16x16",
5 | "idiom" : "mac",
6 | "filename" : "16.png",
7 | "scale" : "1x"
8 | },
9 | {
10 | "size" : "16x16",
11 | "idiom" : "mac",
12 | "filename" : "16@2x.png",
13 | "scale" : "2x"
14 | },
15 | {
16 | "size" : "32x32",
17 | "idiom" : "mac",
18 | "filename" : "32.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "32x32",
23 | "idiom" : "mac",
24 | "filename" : "32@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "128x128",
29 | "idiom" : "mac",
30 | "filename" : "128.png",
31 | "scale" : "1x"
32 | },
33 | {
34 | "size" : "128x128",
35 | "idiom" : "mac",
36 | "filename" : "128@2x.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "256x256",
41 | "idiom" : "mac",
42 | "filename" : "256.png",
43 | "scale" : "1x"
44 | },
45 | {
46 | "size" : "256x256",
47 | "idiom" : "mac",
48 | "filename" : "256@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "512x512",
53 | "idiom" : "mac",
54 | "filename" : "512.png",
55 | "scale" : "1x"
56 | },
57 | {
58 | "size" : "512x512",
59 | "idiom" : "mac",
60 | "filename" : "512@2x.png",
61 | "scale" : "2x"
62 | }
63 | ],
64 | "info" : {
65 | "version" : 1,
66 | "author" : "xcode"
67 | }
68 | }
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/AppSwitch.imageset/AppSwitchDark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/AppSwitch.imageset/AppSwitchDark.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/AppSwitch.imageset/AppSwitchDark@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/AppSwitch.imageset/AppSwitchDark@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/AppSwitch.imageset/AppSwitchLight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/AppSwitch.imageset/AppSwitchLight.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/AppSwitch.imageset/AppSwitchLight@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/AppSwitch.imageset/AppSwitchLight@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/AppSwitch.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "filename" : "AppSwitchLight.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "mac",
10 | "filename" : "AppSwitchDark.png",
11 | "appearances" : [
12 | {
13 | "appearance" : "luminosity",
14 | "value" : "dark"
15 | }
16 | ],
17 | "scale" : "1x"
18 | },
19 | {
20 | "idiom" : "mac",
21 | "filename" : "AppSwitchLight@2x.png",
22 | "scale" : "2x"
23 | },
24 | {
25 | "idiom" : "mac",
26 | "filename" : "AppSwitchDark@2x.png",
27 | "appearances" : [
28 | {
29 | "appearance" : "luminosity",
30 | "value" : "dark"
31 | }
32 | ],
33 | "scale" : "2x"
34 | }
35 | ],
36 | "info" : {
37 | "version" : 1,
38 | "author" : "xcode"
39 | },
40 | "properties" : {
41 | "template-rendering-intent" : "template"
42 | }
43 | }
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/AppleMode.imageset/AppleMode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/AppleMode.imageset/AppleMode.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/AppleMode.imageset/AppleMode@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/AppleMode.imageset/AppleMode@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/AppleMode.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "filename" : "AppleMode.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "mac",
10 | "filename" : "AppleMode@2x.png",
11 | "scale" : "2x"
12 | }
13 | ],
14 | "info" : {
15 | "version" : 1,
16 | "author" : "xcode"
17 | },
18 | "properties" : {
19 | "template-rendering-intent" : "template"
20 | }
21 | }
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/ArrowBackward.imageset/ArrowBackwardDark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/ArrowBackward.imageset/ArrowBackwardDark.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/ArrowBackward.imageset/ArrowBackwardDark@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/ArrowBackward.imageset/ArrowBackwardDark@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/ArrowBackward.imageset/ArrowBackwardLight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/ArrowBackward.imageset/ArrowBackwardLight.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/ArrowBackward.imageset/ArrowBackwardLight@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/ArrowBackward.imageset/ArrowBackwardLight@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/ArrowBackward.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "ArrowBackwardLight.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "appearances" : [
10 | {
11 | "appearance" : "luminosity",
12 | "value" : "dark"
13 | }
14 | ],
15 | "filename" : "ArrowBackwardDark.png",
16 | "idiom" : "universal",
17 | "scale" : "1x"
18 | },
19 | {
20 | "filename" : "ArrowBackwardLight@2x.png",
21 | "idiom" : "universal",
22 | "scale" : "2x"
23 | },
24 | {
25 | "appearances" : [
26 | {
27 | "appearance" : "luminosity",
28 | "value" : "dark"
29 | }
30 | ],
31 | "filename" : "ArrowBackwardDark@2x.png",
32 | "idiom" : "universal",
33 | "scale" : "2x"
34 | },
35 | {
36 | "idiom" : "universal",
37 | "scale" : "3x"
38 | },
39 | {
40 | "appearances" : [
41 | {
42 | "appearance" : "luminosity",
43 | "value" : "dark"
44 | }
45 | ],
46 | "idiom" : "universal",
47 | "scale" : "3x"
48 | }
49 | ],
50 | "info" : {
51 | "author" : "xcode",
52 | "version" : 1
53 | },
54 | "properties" : {
55 | "template-rendering-intent" : "template"
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/ArrowForward.imageset/ArrowButtonDark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/ArrowForward.imageset/ArrowButtonDark.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/ArrowForward.imageset/ArrowButtonDark@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/ArrowForward.imageset/ArrowButtonDark@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/ArrowForward.imageset/ArrowButtonLight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/ArrowForward.imageset/ArrowButtonLight.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/ArrowForward.imageset/ArrowButtonLight@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/ArrowForward.imageset/ArrowButtonLight@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/ArrowForward.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "ArrowButtonLight.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "appearances" : [
10 | {
11 | "appearance" : "luminosity",
12 | "value" : "dark"
13 | }
14 | ],
15 | "filename" : "ArrowButtonDark.png",
16 | "idiom" : "universal",
17 | "scale" : "1x"
18 | },
19 | {
20 | "filename" : "ArrowButtonLight@2x.png",
21 | "idiom" : "universal",
22 | "scale" : "2x"
23 | },
24 | {
25 | "appearances" : [
26 | {
27 | "appearance" : "luminosity",
28 | "value" : "dark"
29 | }
30 | ],
31 | "filename" : "ArrowButtonDark@2x.png",
32 | "idiom" : "universal",
33 | "scale" : "2x"
34 | },
35 | {
36 | "idiom" : "universal",
37 | "scale" : "3x"
38 | },
39 | {
40 | "appearances" : [
41 | {
42 | "appearance" : "luminosity",
43 | "value" : "dark"
44 | }
45 | ],
46 | "idiom" : "universal",
47 | "scale" : "3x"
48 | }
49 | ],
50 | "info" : {
51 | "author" : "xcode",
52 | "version" : 1
53 | },
54 | "properties" : {
55 | "template-rendering-intent" : "template"
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/ButtonGithub.imageset/ButtonGithubDark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/ButtonGithub.imageset/ButtonGithubDark.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/ButtonGithub.imageset/ButtonGithubDark@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/ButtonGithub.imageset/ButtonGithubDark@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/ButtonGithub.imageset/ButtonGithubLight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/ButtonGithub.imageset/ButtonGithubLight.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/ButtonGithub.imageset/ButtonGithubLight@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/ButtonGithub.imageset/ButtonGithubLight@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/ButtonGithub.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "filename" : "ButtonGithubLight.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "mac",
10 | "filename" : "ButtonGithubDark.png",
11 | "appearances" : [
12 | {
13 | "appearance" : "luminosity",
14 | "value" : "dark"
15 | }
16 | ],
17 | "scale" : "1x"
18 | },
19 | {
20 | "idiom" : "mac",
21 | "filename" : "ButtonGithubLight@2x.png",
22 | "scale" : "2x"
23 | },
24 | {
25 | "idiom" : "mac",
26 | "filename" : "ButtonGithubDark@2x.png",
27 | "appearances" : [
28 | {
29 | "appearance" : "luminosity",
30 | "value" : "dark"
31 | }
32 | ],
33 | "scale" : "2x"
34 | }
35 | ],
36 | "info" : {
37 | "version" : 1,
38 | "author" : "xcode"
39 | }
40 | }
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/ButtonTwitter.imageset/ButtonTwitterDark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/ButtonTwitter.imageset/ButtonTwitterDark.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/ButtonTwitter.imageset/ButtonTwitterDark@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/ButtonTwitter.imageset/ButtonTwitterDark@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/ButtonTwitter.imageset/ButtonTwitterLight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/ButtonTwitter.imageset/ButtonTwitterLight.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/ButtonTwitter.imageset/ButtonTwitterLight@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/ButtonTwitter.imageset/ButtonTwitterLight@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/ButtonTwitter.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "filename" : "ButtonTwitterLight.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "mac",
10 | "filename" : "ButtonTwitterDark.png",
11 | "appearances" : [
12 | {
13 | "appearance" : "luminosity",
14 | "value" : "dark"
15 | }
16 | ],
17 | "scale" : "1x"
18 | },
19 | {
20 | "idiom" : "mac",
21 | "filename" : "ButtonTwitterLight@2x.png",
22 | "scale" : "2x"
23 | },
24 | {
25 | "idiom" : "mac",
26 | "filename" : "ButtonTwitterDark@2x.png",
27 | "appearances" : [
28 | {
29 | "appearance" : "luminosity",
30 | "value" : "dark"
31 | }
32 | ],
33 | "scale" : "2x"
34 | }
35 | ],
36 | "info" : {
37 | "version" : 1,
38 | "author" : "xcode"
39 | }
40 | }
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/ButtonWeb.imageset/ButtonWebDark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/ButtonWeb.imageset/ButtonWebDark.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/ButtonWeb.imageset/ButtonWebDark@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/ButtonWeb.imageset/ButtonWebDark@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/ButtonWeb.imageset/ButtonWebLight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/ButtonWeb.imageset/ButtonWebLight.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/ButtonWeb.imageset/ButtonWebLight@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/ButtonWeb.imageset/ButtonWebLight@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/ButtonWeb.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "filename" : "ButtonWebLight.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "mac",
10 | "filename" : "ButtonWebDark.png",
11 | "appearances" : [
12 | {
13 | "appearance" : "luminosity",
14 | "value" : "dark"
15 | }
16 | ],
17 | "scale" : "1x"
18 | },
19 | {
20 | "idiom" : "mac",
21 | "filename" : "ButtonWebLight@2x.png",
22 | "scale" : "2x"
23 | },
24 | {
25 | "idiom" : "mac",
26 | "filename" : "ButtonWebDark@2x.png",
27 | "appearances" : [
28 | {
29 | "appearance" : "luminosity",
30 | "value" : "dark"
31 | }
32 | ],
33 | "scale" : "2x"
34 | }
35 | ],
36 | "info" : {
37 | "version" : 1,
38 | "author" : "xcode"
39 | }
40 | }
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/CheckDisabled.imageset/CheckDisabledDark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/CheckDisabled.imageset/CheckDisabledDark.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/CheckDisabled.imageset/CheckDisabledDark@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/CheckDisabled.imageset/CheckDisabledDark@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/CheckDisabled.imageset/CheckDisabledLight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/CheckDisabled.imageset/CheckDisabledLight.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/CheckDisabled.imageset/CheckDisabledLight@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/CheckDisabled.imageset/CheckDisabledLight@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/CheckDisabled.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "filename" : "CheckDisabledLight.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "mac",
10 | "filename" : "CheckDisabledDark.png",
11 | "appearances" : [
12 | {
13 | "appearance" : "luminosity",
14 | "value" : "dark"
15 | }
16 | ],
17 | "scale" : "1x"
18 | },
19 | {
20 | "idiom" : "mac",
21 | "filename" : "CheckDisabledLight@2x.png",
22 | "scale" : "2x"
23 | },
24 | {
25 | "idiom" : "mac",
26 | "filename" : "CheckDisabledDark@2x.png",
27 | "appearances" : [
28 | {
29 | "appearance" : "luminosity",
30 | "value" : "dark"
31 | }
32 | ],
33 | "scale" : "2x"
34 | }
35 | ],
36 | "info" : {
37 | "version" : 1,
38 | "author" : "xcode"
39 | },
40 | "properties" : {
41 | "template-rendering-intent" : "template"
42 | }
43 | }
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/CheckEnabled.imageset/CheckEnabledDark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/CheckEnabled.imageset/CheckEnabledDark.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/CheckEnabled.imageset/CheckEnabledDark@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/CheckEnabled.imageset/CheckEnabledDark@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/CheckEnabled.imageset/CheckEnabledLight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/CheckEnabled.imageset/CheckEnabledLight.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/CheckEnabled.imageset/CheckEnabledLight@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/CheckEnabled.imageset/CheckEnabledLight@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/CheckEnabled.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "filename" : "CheckEnabledLight.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "mac",
10 | "filename" : "CheckEnabledDark.png",
11 | "appearances" : [
12 | {
13 | "appearance" : "luminosity",
14 | "value" : "dark"
15 | }
16 | ],
17 | "scale" : "1x"
18 | },
19 | {
20 | "idiom" : "mac",
21 | "filename" : "CheckEnabledLight@2x.png",
22 | "scale" : "2x"
23 | },
24 | {
25 | "idiom" : "mac",
26 | "filename" : "CheckEnabledDark@2x.png",
27 | "appearances" : [
28 | {
29 | "appearance" : "luminosity",
30 | "value" : "dark"
31 | }
32 | ],
33 | "scale" : "2x"
34 | }
35 | ],
36 | "info" : {
37 | "version" : 1,
38 | "author" : "xcode"
39 | },
40 | "properties" : {
41 | "template-rendering-intent" : "template"
42 | }
43 | }
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/CheckMixed.imageset/CheckMixedDark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/CheckMixed.imageset/CheckMixedDark.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/CheckMixed.imageset/CheckMixedDark@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/CheckMixed.imageset/CheckMixedDark@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/CheckMixed.imageset/CheckMixedLight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/CheckMixed.imageset/CheckMixedLight.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/CheckMixed.imageset/CheckMixedLight@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/CheckMixed.imageset/CheckMixedLight@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/CheckMixed.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "filename" : "CheckMixedLight.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "mac",
10 | "filename" : "CheckMixedDark.png",
11 | "appearances" : [
12 | {
13 | "appearance" : "luminosity",
14 | "value" : "dark"
15 | }
16 | ],
17 | "scale" : "1x"
18 | },
19 | {
20 | "idiom" : "mac",
21 | "filename" : "CheckMixedLight@2x.png",
22 | "scale" : "2x"
23 | },
24 | {
25 | "idiom" : "mac",
26 | "filename" : "CheckMixedDark@2x.png",
27 | "appearances" : [
28 | {
29 | "appearance" : "luminosity",
30 | "value" : "dark"
31 | }
32 | ],
33 | "scale" : "2x"
34 | }
35 | ],
36 | "info" : {
37 | "version" : 1,
38 | "author" : "xcode"
39 | },
40 | "properties" : {
41 | "template-rendering-intent" : "template"
42 | }
43 | }
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/Cross.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "CrossLight.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "appearances" : [
10 | {
11 | "appearance" : "luminosity",
12 | "value" : "dark"
13 | }
14 | ],
15 | "filename" : "CrossDark.png",
16 | "idiom" : "universal",
17 | "scale" : "1x"
18 | },
19 | {
20 | "filename" : "CrossLight@2x.png",
21 | "idiom" : "universal",
22 | "scale" : "2x"
23 | },
24 | {
25 | "appearances" : [
26 | {
27 | "appearance" : "luminosity",
28 | "value" : "dark"
29 | }
30 | ],
31 | "filename" : "CrossDark@2x.png",
32 | "idiom" : "universal",
33 | "scale" : "2x"
34 | },
35 | {
36 | "idiom" : "universal",
37 | "scale" : "3x"
38 | },
39 | {
40 | "appearances" : [
41 | {
42 | "appearance" : "luminosity",
43 | "value" : "dark"
44 | }
45 | ],
46 | "idiom" : "universal",
47 | "scale" : "3x"
48 | }
49 | ],
50 | "info" : {
51 | "author" : "xcode",
52 | "version" : 1
53 | },
54 | "properties" : {
55 | "template-rendering-intent" : "template"
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/Cross.imageset/CrossDark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/Cross.imageset/CrossDark.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/Cross.imageset/CrossDark@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/Cross.imageset/CrossDark@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/Cross.imageset/CrossLight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/Cross.imageset/CrossLight.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/Cross.imageset/CrossLight@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/Cross.imageset/CrossLight@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/DefaultMode.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "filename" : "DefaultModeLight.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "mac",
10 | "filename" : "DefaultModeDark.png",
11 | "appearances" : [
12 | {
13 | "appearance" : "luminosity",
14 | "value" : "dark"
15 | }
16 | ],
17 | "scale" : "1x"
18 | },
19 | {
20 | "idiom" : "mac",
21 | "filename" : "DefaultModeLight@2x.png",
22 | "scale" : "2x"
23 | },
24 | {
25 | "idiom" : "mac",
26 | "filename" : "DefaultModeDark@2x.png",
27 | "appearances" : [
28 | {
29 | "appearance" : "luminosity",
30 | "value" : "dark"
31 | }
32 | ],
33 | "scale" : "2x"
34 | }
35 | ],
36 | "info" : {
37 | "version" : 1,
38 | "author" : "xcode"
39 | },
40 | "properties" : {
41 | "template-rendering-intent" : "template"
42 | }
43 | }
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/DefaultMode.imageset/DefaultModeDark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/DefaultMode.imageset/DefaultModeDark.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/DefaultMode.imageset/DefaultModeDark@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/DefaultMode.imageset/DefaultModeDark@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/DefaultMode.imageset/DefaultModeLight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/DefaultMode.imageset/DefaultModeLight.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/DefaultMode.imageset/DefaultModeLight@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/DefaultMode.imageset/DefaultModeLight@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/DoubleArrowForward.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "DoubleArrowButtonLight.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "appearances" : [
10 | {
11 | "appearance" : "luminosity",
12 | "value" : "dark"
13 | }
14 | ],
15 | "filename" : "DoubleArrowButtonDark.png",
16 | "idiom" : "universal",
17 | "scale" : "1x"
18 | },
19 | {
20 | "filename" : "DoubleArrowButtonLight@2x.png",
21 | "idiom" : "universal",
22 | "scale" : "2x"
23 | },
24 | {
25 | "appearances" : [
26 | {
27 | "appearance" : "luminosity",
28 | "value" : "dark"
29 | }
30 | ],
31 | "filename" : "DoubleArrowButtonDark@2x.png",
32 | "idiom" : "universal",
33 | "scale" : "2x"
34 | },
35 | {
36 | "idiom" : "universal",
37 | "scale" : "3x"
38 | },
39 | {
40 | "appearances" : [
41 | {
42 | "appearance" : "luminosity",
43 | "value" : "dark"
44 | }
45 | ],
46 | "idiom" : "universal",
47 | "scale" : "3x"
48 | }
49 | ],
50 | "info" : {
51 | "author" : "xcode",
52 | "version" : 1
53 | },
54 | "properties" : {
55 | "template-rendering-intent" : "template"
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/DoubleArrowForward.imageset/DoubleArrowButtonDark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/DoubleArrowForward.imageset/DoubleArrowButtonDark.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/DoubleArrowForward.imageset/DoubleArrowButtonDark@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/DoubleArrowForward.imageset/DoubleArrowButtonDark@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/DoubleArrowForward.imageset/DoubleArrowButtonLight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/DoubleArrowForward.imageset/DoubleArrowButtonLight.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/DoubleArrowForward.imageset/DoubleArrowButtonLight@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/DoubleArrowForward.imageset/DoubleArrowButtonLight@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/FluorBlue.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0.635",
9 | "green" : "0.447",
10 | "red" : "0.282"
11 | }
12 | },
13 | "idiom" : "universal"
14 | }
15 | ],
16 | "info" : {
17 | "author" : "xcode",
18 | "version" : 1
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/FluorRed.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0.374",
9 | "green" : "0.317",
10 | "red" : "0.961"
11 | }
12 | },
13 | "idiom" : "universal"
14 | }
15 | ],
16 | "info" : {
17 | "author" : "xcode",
18 | "version" : 1
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/FnKey.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "filename" : "FnKeyLight.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "mac",
10 | "filename" : "FnKeyDark.png",
11 | "appearances" : [
12 | {
13 | "appearance" : "luminosity",
14 | "value" : "dark"
15 | }
16 | ],
17 | "scale" : "1x"
18 | },
19 | {
20 | "idiom" : "mac",
21 | "filename" : "FnKeyLight@2x.png",
22 | "scale" : "2x"
23 | },
24 | {
25 | "idiom" : "mac",
26 | "filename" : "FnKeyDark@2x.png",
27 | "appearances" : [
28 | {
29 | "appearance" : "luminosity",
30 | "value" : "dark"
31 | }
32 | ],
33 | "scale" : "2x"
34 | }
35 | ],
36 | "info" : {
37 | "version" : 1,
38 | "author" : "xcode"
39 | },
40 | "properties" : {
41 | "template-rendering-intent" : "template"
42 | }
43 | }
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/FnKey.imageset/FnKeyDark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/FnKey.imageset/FnKeyDark.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/FnKey.imageset/FnKeyDark@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/FnKey.imageset/FnKeyDark@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/FnKey.imageset/FnKeyLight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/FnKey.imageset/FnKeyLight.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/FnKey.imageset/FnKeyLight@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/FnKey.imageset/FnKeyLight@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/IconAppleMode.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "filename" : "IconAppleMode.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "mac",
10 | "filename" : "IconAppleMode@2x.png",
11 | "scale" : "2x"
12 | }
13 | ],
14 | "info" : {
15 | "version" : 1,
16 | "author" : "xcode"
17 | },
18 | "properties" : {
19 | "template-rendering-intent" : "template"
20 | }
21 | }
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/IconAppleMode.imageset/IconAppleMode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/IconAppleMode.imageset/IconAppleMode.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/IconAppleMode.imageset/IconAppleMode@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/IconAppleMode.imageset/IconAppleMode@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/IconDisabled.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "filename" : "IconDisabled.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "mac",
10 | "filename" : "IconDisabled@2x.png",
11 | "scale" : "2x"
12 | }
13 | ],
14 | "info" : {
15 | "version" : 1,
16 | "author" : "xcode"
17 | },
18 | "properties" : {
19 | "template-rendering-intent" : "template"
20 | }
21 | }
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/IconDisabled.imageset/IconDisabled.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/IconDisabled.imageset/IconDisabled.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/IconDisabled.imageset/IconDisabled@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/IconDisabled.imageset/IconDisabled@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/IconOtherMode.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "filename" : "IconOtherMode.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "mac",
10 | "filename" : "IconOtherMode@2x.png",
11 | "scale" : "2x"
12 | }
13 | ],
14 | "info" : {
15 | "version" : 1,
16 | "author" : "xcode"
17 | },
18 | "properties" : {
19 | "template-rendering-intent" : "template"
20 | }
21 | }
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/IconOtherMode.imageset/IconOtherMode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/IconOtherMode.imageset/IconOtherMode.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/IconOtherMode.imageset/IconOtherMode@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/IconOtherMode.imageset/IconOtherMode@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/LighIconDisabled.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "filename" : "LighIconDisabled.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "mac",
10 | "filename" : "LighIconDisabled@2x.png",
11 | "scale" : "2x"
12 | }
13 | ],
14 | "info" : {
15 | "version" : 1,
16 | "author" : "xcode"
17 | },
18 | "properties" : {
19 | "template-rendering-intent" : "template"
20 | }
21 | }
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/LighIconDisabled.imageset/LighIconDisabled.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/LighIconDisabled.imageset/LighIconDisabled.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/LighIconDisabled.imageset/LighIconDisabled@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/LighIconDisabled.imageset/LighIconDisabled@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/MixedSwitch.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "filename" : "MixedSwitchLight.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "mac",
10 | "filename" : "MixedSwitchDark.png",
11 | "appearances" : [
12 | {
13 | "appearance" : "luminosity",
14 | "value" : "dark"
15 | }
16 | ],
17 | "scale" : "1x"
18 | },
19 | {
20 | "idiom" : "mac",
21 | "filename" : "MixedSwitchLight@2x.png",
22 | "scale" : "2x"
23 | },
24 | {
25 | "idiom" : "mac",
26 | "filename" : "MixedSwitchDark@2x.png",
27 | "appearances" : [
28 | {
29 | "appearance" : "luminosity",
30 | "value" : "dark"
31 | }
32 | ],
33 | "scale" : "2x"
34 | }
35 | ],
36 | "info" : {
37 | "version" : 1,
38 | "author" : "xcode"
39 | }
40 | }
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/MixedSwitch.imageset/MixedSwitchDark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/MixedSwitch.imageset/MixedSwitchDark.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/MixedSwitch.imageset/MixedSwitchDark@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/MixedSwitch.imageset/MixedSwitchDark@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/MixedSwitch.imageset/MixedSwitchLight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/MixedSwitch.imageset/MixedSwitchLight.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/MixedSwitch.imageset/MixedSwitchLight@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/MixedSwitch.imageset/MixedSwitchLight@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/OtherMode.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "filename" : "OtherMode.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "mac",
10 | "filename" : "OtherMode@2x.png",
11 | "scale" : "2x"
12 | }
13 | ],
14 | "info" : {
15 | "version" : 1,
16 | "author" : "xcode"
17 | },
18 | "properties" : {
19 | "template-rendering-intent" : "template"
20 | }
21 | }
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/OtherMode.imageset/OtherMode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/OtherMode.imageset/OtherMode.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/OtherMode.imageset/OtherMode@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/OtherMode.imageset/OtherMode@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/Preferences.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "filename" : "PreferencesLight.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "mac",
10 | "filename" : "PreferencesDark.png",
11 | "appearances" : [
12 | {
13 | "appearance" : "luminosity",
14 | "value" : "dark"
15 | }
16 | ],
17 | "scale" : "1x"
18 | },
19 | {
20 | "idiom" : "mac",
21 | "filename" : "PreferencesLight@2x.png",
22 | "scale" : "2x"
23 | },
24 | {
25 | "idiom" : "mac",
26 | "filename" : "PreferencesDark@2x.png",
27 | "appearances" : [
28 | {
29 | "appearance" : "luminosity",
30 | "value" : "dark"
31 | }
32 | ],
33 | "scale" : "2x"
34 | }
35 | ],
36 | "info" : {
37 | "version" : 1,
38 | "author" : "xcode"
39 | },
40 | "properties" : {
41 | "template-rendering-intent" : "template"
42 | }
43 | }
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/Preferences.imageset/PreferencesDark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/Preferences.imageset/PreferencesDark.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/Preferences.imageset/PreferencesDark@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/Preferences.imageset/PreferencesDark@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/Preferences.imageset/PreferencesLight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/Preferences.imageset/PreferencesLight.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/Preferences.imageset/PreferencesLight@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/Preferences.imageset/PreferencesLight@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/QuestionMark.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "QuestionMark.png",
5 | "idiom" : "mac",
6 | "scale" : "1x"
7 | },
8 | {
9 | "filename" : "QuestionMark@2x.png",
10 | "idiom" : "mac",
11 | "scale" : "2x"
12 | }
13 | ],
14 | "info" : {
15 | "author" : "xcode",
16 | "version" : 1
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/QuestionMark.imageset/QuestionMark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/QuestionMark.imageset/QuestionMark.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/QuestionMark.imageset/QuestionMark@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/QuestionMark.imageset/QuestionMark@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/Quit.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "filename" : "Quit.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "mac",
10 | "filename" : "Quit@2x.png",
11 | "scale" : "2x"
12 | }
13 | ],
14 | "info" : {
15 | "version" : 1,
16 | "author" : "xcode"
17 | },
18 | "properties" : {
19 | "template-rendering-intent" : "template"
20 | }
21 | }
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/Quit.imageset/Quit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/Quit.imageset/Quit.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/Quit.imageset/Quit@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/Quit.imageset/Quit@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/Rules.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "filename" : "RulesLight.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "mac",
10 | "filename" : "RulesDark.png",
11 | "appearances" : [
12 | {
13 | "appearance" : "luminosity",
14 | "value" : "dark"
15 | }
16 | ],
17 | "scale" : "1x"
18 | },
19 | {
20 | "idiom" : "mac",
21 | "filename" : "RulesLight@2x.png",
22 | "scale" : "2x"
23 | },
24 | {
25 | "idiom" : "mac",
26 | "filename" : "RulesDark@2x.png",
27 | "appearances" : [
28 | {
29 | "appearance" : "luminosity",
30 | "value" : "dark"
31 | }
32 | ],
33 | "scale" : "2x"
34 | }
35 | ],
36 | "info" : {
37 | "version" : 1,
38 | "author" : "xcode"
39 | },
40 | "properties" : {
41 | "template-rendering-intent" : "template"
42 | }
43 | }
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/Rules.imageset/RulesDark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/Rules.imageset/RulesDark.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/Rules.imageset/RulesDark@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/Rules.imageset/RulesDark@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/Rules.imageset/RulesLight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/Rules.imageset/RulesLight.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/Rules.imageset/RulesLight@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/Rules.imageset/RulesLight@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/RunningApps.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "filename" : "RunningAppsLight.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "mac",
10 | "filename" : "RunningAppsDark.png",
11 | "appearances" : [
12 | {
13 | "appearance" : "luminosity",
14 | "value" : "dark"
15 | }
16 | ],
17 | "scale" : "1x"
18 | },
19 | {
20 | "idiom" : "mac",
21 | "filename" : "RunningAppsLight@2x.png",
22 | "scale" : "2x"
23 | },
24 | {
25 | "idiom" : "mac",
26 | "filename" : "RunningAppsDark@2x.png",
27 | "appearances" : [
28 | {
29 | "appearance" : "luminosity",
30 | "value" : "dark"
31 | }
32 | ],
33 | "scale" : "2x"
34 | }
35 | ],
36 | "info" : {
37 | "version" : 1,
38 | "author" : "xcode"
39 | },
40 | "properties" : {
41 | "template-rendering-intent" : "template"
42 | }
43 | }
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/RunningApps.imageset/RunningAppsDark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/RunningApps.imageset/RunningAppsDark.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/RunningApps.imageset/RunningAppsDark@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/RunningApps.imageset/RunningAppsDark@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/RunningApps.imageset/RunningAppsLight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/RunningApps.imageset/RunningAppsLight.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/RunningApps.imageset/RunningAppsLight@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/RunningApps.imageset/RunningAppsLight@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/Service.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "ServiceLight.png",
5 | "idiom" : "mac",
6 | "scale" : "1x"
7 | },
8 | {
9 | "appearances" : [
10 | {
11 | "appearance" : "luminosity",
12 | "value" : "dark"
13 | }
14 | ],
15 | "filename" : "ServiceDark.png",
16 | "idiom" : "mac",
17 | "scale" : "1x"
18 | },
19 | {
20 | "filename" : "ServiceLight@2x.png",
21 | "idiom" : "mac",
22 | "scale" : "2x"
23 | },
24 | {
25 | "appearances" : [
26 | {
27 | "appearance" : "luminosity",
28 | "value" : "dark"
29 | }
30 | ],
31 | "filename" : "ServiceDark@2x.png",
32 | "idiom" : "mac",
33 | "scale" : "2x"
34 | }
35 | ],
36 | "info" : {
37 | "author" : "xcode",
38 | "version" : 1
39 | },
40 | "properties" : {
41 | "template-rendering-intent" : "template"
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/Service.imageset/ServiceDark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/Service.imageset/ServiceDark.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/Service.imageset/ServiceDark@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/Service.imageset/ServiceDark@2x.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/Service.imageset/ServiceLight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/Service.imageset/ServiceLight.png
--------------------------------------------------------------------------------
/Fluor/Assets.xcassets/Service.imageset/ServiceLight@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/Assets.xcassets/Service.imageset/ServiceLight@2x.png
--------------------------------------------------------------------------------
/Fluor/Base.lproj/Main.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/Fluor/Controllers/LaunchAtLoginController.h:
--------------------------------------------------------------------------------
1 | //
2 | // LaunchAtLoginController.h
3 | //
4 | // Copyright 2011 Tomáš Znamenáček
5 | // Copyright 2010 Ben Clark-Robinson
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining
8 | // a copy of this software and associated documentation files (the ‘Software’),
9 | // to deal in the Software without restriction, including without limitation
10 | // the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 | // and/or sell copies of the Software, and to permit persons to whom the
12 | // Software is furnished to do so, subject to the following conditions:
13 | //
14 | // The above copyright notice and this permission notice shall be
15 | // included in all copies or substantial portions of the Software.
16 | //
17 | // THE SOFTWARE IS PROVIDED ‘AS IS’, WITHOUT WARRANTY OF ANY KIND,
18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21 | // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 | // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 | // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 |
25 | @import Foundation;
26 | @import CoreServices;
27 |
28 | @interface LaunchAtLoginController : NSObject {}
29 |
30 | @property(assign) BOOL launchAtLogin;
31 |
32 | - (BOOL) willLaunchAtLogin: (NSURL*) itemURL;
33 | - (void) setLaunchAtLogin: (BOOL) enabled forURL: (NSURL*) itemURL;
34 |
35 | @end
36 |
--------------------------------------------------------------------------------
/Fluor/Controllers/LaunchAtLoginController.m:
--------------------------------------------------------------------------------
1 | //
2 | // LaunchAtLoginController.m
3 | //
4 | // Copyright 2011 Tomáš Znamenáček
5 | // Copyright 2010 Ben Clark-Robinson
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining
8 | // a copy of this software and associated documentation files (the ‘Software’),
9 | // to deal in the Software without restriction, including without limitation
10 | // the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 | // and/or sell copies of the Software, and to permit persons to whom the
12 | // Software is furnished to do so, subject to the following conditions:
13 | //
14 | // The above copyright notice and this permission notice shall be
15 | // included in all copies or substantial portions of the Software.
16 | //
17 | // THE SOFTWARE IS PROVIDED ‘AS IS’, WITHOUT WARRANTY OF ANY KIND,
18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21 | // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 | // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 | // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 |
25 | #import "LaunchAtLoginController.h"
26 |
27 | #pragma clang diagnostic push
28 | #pragma clang diagnostic ignored "-Wdeprecated-declarations"
29 |
30 | static NSString *const StartAtLoginKey = @"launchAtLogin";
31 |
32 | @interface LaunchAtLoginController ()
33 | @property(assign) LSSharedFileListRef loginItems;
34 | @end
35 |
36 | @implementation LaunchAtLoginController
37 | @synthesize loginItems;
38 |
39 | #pragma mark Change Observing
40 |
41 | void sharedFileListDidChange(LSSharedFileListRef inList, void *context)
42 | {
43 | LaunchAtLoginController *self = (__bridge id) context;
44 | [self willChangeValueForKey:StartAtLoginKey];
45 | [self didChangeValueForKey:StartAtLoginKey];
46 | }
47 |
48 | #pragma mark Initialization
49 |
50 | - (id) init
51 | {
52 | self = [super init];
53 | loginItems = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL);
54 | LSSharedFileListAddObserver(loginItems, CFRunLoopGetMain(),
55 | (CFStringRef)NSDefaultRunLoopMode, sharedFileListDidChange, (voidPtr)CFBridgingRetain(self));
56 | return self;
57 | }
58 |
59 | - (void) dealloc
60 | {
61 | LSSharedFileListRemoveObserver(loginItems, CFRunLoopGetMain(),
62 | (CFStringRef)NSDefaultRunLoopMode, sharedFileListDidChange, (__bridge void *)(self));
63 | CFRelease(loginItems);
64 | }
65 |
66 | #pragma mark Launch List Control
67 | #pragma clang diagnostic push
68 | #pragma clang diagnostic ignored "-Wdeprecated-declarations"
69 | LSSharedFileListItemRef copyItemWithURLinFileList(NSURL* wantedURL, LSSharedFileListRef fileList) {
70 | if (wantedURL == NULL || fileList == NULL)
71 | return NULL;
72 |
73 | NSArray *listSnapshot = (__bridge_transfer NSArray *)LSSharedFileListCopySnapshot(fileList, NULL);
74 | for(NSUInteger i = 0; i< [listSnapshot count]; i++) {
75 | LSSharedFileListItemRef item = (__bridge LSSharedFileListItemRef)[listSnapshot objectAtIndex:i];
76 | UInt32 resolutionFlags = kLSSharedFileListNoUserInteraction | kLSSharedFileListDoNotMountVolumes;
77 | CFURLRef currentItemURL = NULL;
78 | LSSharedFileListItemResolve(item, resolutionFlags, ¤tItemURL, NULL);
79 | if (currentItemURL && [(__bridge_transfer NSURL*)currentItemURL isEqual:wantedURL]) {
80 | CFRetain(item);
81 | return item;
82 | }
83 | }
84 |
85 | return NULL;
86 | }
87 | #pragma clang diagnostic pop
88 |
89 | - (BOOL) willLaunchAtLogin: (NSURL*) itemURL
90 | {
91 | return !!copyItemWithURLinFileList(itemURL, loginItems);
92 | }
93 |
94 | - (void) setLaunchAtLogin: (BOOL) enabled forURL: (NSURL*) itemURL
95 | {
96 | LSSharedFileListItemRef appItem = copyItemWithURLinFileList(itemURL, loginItems);
97 | if (enabled && !appItem) {
98 | LSSharedFileListInsertItemURL(loginItems, kLSSharedFileListItemBeforeFirst,
99 | NULL, NULL, (__bridge CFURLRef)itemURL, NULL, NULL);
100 | } else if (!enabled && appItem) {
101 | LSSharedFileListItemRemove(loginItems, appItem);
102 | }
103 | if (appItem) {
104 | CFRelease(appItem);
105 | }
106 | }
107 |
108 | #pragma mark Basic Interface
109 |
110 | - (NSURL*) appURL
111 | {
112 | return [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]];
113 | }
114 |
115 | - (void) setLaunchAtLogin: (BOOL) enabled
116 | {
117 | [self willChangeValueForKey:StartAtLoginKey];
118 | [self setLaunchAtLogin:enabled forURL:[self appURL]];
119 | [self didChangeValueForKey:StartAtLoginKey];
120 | }
121 |
122 | - (BOOL) launchAtLogin
123 | {
124 | return [self willLaunchAtLogin:[self appURL]];
125 | }
126 |
127 | @end
128 | #pragma clang diagnostic pop
129 |
--------------------------------------------------------------------------------
/Fluor/Controllers/MenuItemsController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MenuItemsController.swift
3 | //
4 | // Fluor
5 | //
6 | // MIT License
7 | //
8 | // Copyright (c) 2020 Pierre Tacchi
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining a copy
11 | // of this software and associated documentation files (the "Software"), to deal
12 | // in the Software without restriction, including without limitation the rights
13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | // copies of the Software, and to permit persons to whom the Software is
15 | // furnished to do so, subject to the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be included in all
18 | // copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | // SOFTWARE.
27 | //
28 |
29 |
30 | import Cocoa
31 |
32 | class MenuItemsController: NSObject, SwitchMethodDidChangeObserver, TriggerSectionVisibilityDidChangeObserver {
33 | @IBOutlet weak var menu: NSMenu!
34 | @IBOutlet var switchMethodViewController: SwitchMethodViewController!
35 | @IBOutlet var currentAppViewController: CurrentAppViewController!
36 | @IBOutlet weak var defaultModeViewController: DefaultModeViewController!
37 |
38 | override init() {
39 | super.init()
40 | self.startObservingSwitchMethodDidChange()
41 | self.startObservingTriggerSectionVisibilityDidChange()
42 | }
43 |
44 | deinit {
45 | self.stopObservingSwitchMethodDidChange()
46 | self.stopObservingTriggerSectionVisibilityDidChange()
47 | }
48 |
49 | func setupController() {
50 | let switchingPlaceHolder = menu.item(withTag: 1)
51 | let statePlaceHolder = menu.item(withTag: 3)
52 | let currentPlaceHolder = menu.item(withTag: 5)
53 | switchingPlaceHolder?.view = switchMethodViewController.view
54 | statePlaceHolder?.view = defaultModeViewController.view
55 | currentPlaceHolder?.view = currentAppViewController.view
56 | if case SwitchMethod.key = AppManager.default.switchMethod {
57 | currentAppViewController.shrinkView()
58 | }
59 | }
60 |
61 | // MARK: - SwitchMethodDidChangeObserver
62 |
63 | func switchMethodDidChange(notification: Notification) {
64 | guard let method = notification.userInfo?["method"] as? SwitchMethod,
65 | method != currentAppViewController.currentSwitchMethod else { return }
66 | switch method {
67 | case .key:
68 | currentAppViewController.shrinkView()
69 | case .window, .hybrid:
70 | currentAppViewController.expandView()
71 | }
72 | }
73 |
74 | // MARK: - TriggerSectionVisibilityDidChangeObserver
75 |
76 | @objc func triggerSectionVisibilityDidChange(notification: Notification) {
77 | guard let visible = notification.userInfo?["visible"] as? Bool else { return }
78 | if visible {
79 | self.showTriggerSection()
80 | } else {
81 | self.hideTriggerSection()
82 | }
83 | }
84 |
85 | // MARK: - Private functions
86 |
87 | private func showTriggerSection() {
88 | guard let switchMethodItem = self.menu.item(at: 0), let separatorItem = self.menu.item(at: 1) else { return }
89 | switchMethodItem.view = self.switchMethodViewController.view
90 | switchMethodItem.isHidden = false
91 | separatorItem.isHidden = false
92 | }
93 |
94 | private func hideTriggerSection() {
95 | guard let switchMethodItem = self.menu.item(at: 0), let separatorItem = self.menu.item(at: 1) else { return }
96 | switchMethodItem.view = nil
97 | switchMethodItem.isHidden = true
98 | separatorItem.isHidden = true
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/Fluor/Controllers/ViewControllers/AboutViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AboutViewController.swift
3 | //
4 | // Fluor
5 | //
6 | // MIT License
7 | //
8 | // Copyright (c) 2020 Pierre Tacchi
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining a copy
11 | // of this software and associated documentation files (the "Software"), to deal
12 | // in the Software without restriction, including without limitation the rights
13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | // copies of the Software, and to permit persons to whom the Software is
15 | // furnished to do so, subject to the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be included in all
18 | // copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | // SOFTWARE.
27 | //
28 |
29 |
30 | import Cocoa
31 |
32 | class AboutViewController: NSViewController {
33 | @IBOutlet weak var versionLabel: NSTextField!
34 | @IBOutlet weak var webpageButton: NSButton!
35 | @IBOutlet weak var twitterButton: NSButton!
36 | @IBOutlet weak var githubButton: NSButton!
37 | @IBOutlet weak var supportButton: NSButton!
38 | @IBOutlet weak var iconView: NSImageView!
39 |
40 | override func viewDidLoad() {
41 | super.viewDidLoad()
42 |
43 | let bundleVersion = getBundleVersion()
44 | versionLabel.stringValue = "Version \(bundleVersion.version) build \(bundleVersion.build)"
45 | }
46 |
47 | private func getBundleVersion() -> (version: String, build: String) {
48 | let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as! String
49 | let build = Bundle.main.infoDictionary?[kCFBundleVersionKey as String] as! String
50 |
51 | return (version, build)
52 | }
53 |
54 | private func openUrlForInfo(key: String) {
55 | guard let url = self.urlForInfo(key: key) else { return }
56 | NSWorkspace.shared.open(url)
57 | }
58 |
59 | private func urlForInfo(key: String) -> URL? {
60 | guard let str = Bundle.main.infoDictionary?[key] as? String,
61 | let url = URL(string: str) else { return nil }
62 |
63 | return url
64 | }
65 |
66 | @IBAction func closeWindow(_ sender: Any) {
67 | view.window?.close()
68 | }
69 |
70 | @IBAction func goToWebpage(_ sender: Any) {
71 | self.openUrlForInfo(key: "FLPyrolyseURL")
72 | }
73 |
74 | @IBAction func goToTwitter(_ sender: Any) {
75 | self.openUrlForInfo(key: "FLTwitterURL")
76 | }
77 |
78 | @IBAction func goToGithub(_ sender: Any) {
79 | self.openUrlForInfo(key: "FLGithubURL")
80 | }
81 |
82 | @IBAction func goToSupport(_ sender: Any) {
83 | self.openUrlForInfo(key: "FLSupportEmail")
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/Fluor/Controllers/ViewControllers/CurrentAppViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CurrentAppViewController.swift
3 | //
4 | // Fluor
5 | //
6 | // MIT License
7 | //
8 | // Copyright (c) 2020 Pierre Tacchi
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining a copy
11 | // of this software and associated documentation files (the "Software"), to deal
12 | // in the Software without restriction, including without limitation the rights
13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | // copies of the Software, and to permit persons to whom the Software is
15 | // furnished to do so, subject to the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be included in all
18 | // copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | // SOFTWARE.
27 | //
28 |
29 |
30 | import Cocoa
31 |
32 | class CurrentAppViewController: NSViewController, BehaviorDidChangeObserver, ActiveApplicationDidChangeObserver {
33 |
34 | @IBOutlet weak var appIconView: NSImageView!
35 | @IBOutlet weak var appNameLabel: NSTextField!
36 | @IBOutlet weak var behaviorSegment: NSSegmentedControl!
37 | @IBOutlet weak var imageConstraint: NSLayoutConstraint!
38 |
39 | internal var currentSwitchMethod = SwitchMethod.window
40 |
41 | private var currentAppID: String = ""
42 | private var currentAppURL: URL?
43 |
44 | deinit {
45 | self.stopObservingBehaviorDidChange()
46 | self.stopObservingActiveApplicationDidChange()
47 | }
48 |
49 | override func viewDidLoad() {
50 | self.startObservingBehaviorDidChange()
51 | self.startObservingActiveApplicationDidChange()
52 |
53 | if let currentApp = NSWorkspace.shared.frontmostApplication {
54 | self.setCurrent(app: currentApp)
55 | }
56 | }
57 |
58 | func shrinkView() {
59 | self.currentSwitchMethod = .key
60 | var newFrame = self.view.frame
61 | newFrame.size.height = 32
62 | self.imageConstraint.constant = 24
63 | self.behaviorSegment.isHidden = true
64 | self.view.setFrameSize(newFrame.size)
65 | }
66 |
67 | func expandView() {
68 | self.currentSwitchMethod = .window
69 | var newFrame = self.view.frame
70 | newFrame.size.height = 72
71 | self.imageConstraint.constant = 64
72 | self.behaviorSegment.isHidden = false
73 | self.view.setFrameSize(newFrame.size)
74 | }
75 |
76 | /// Change the behavior for the current running application.
77 | /// It makes sure the behavior manager gets notfified of this change.
78 | ///
79 | /// - parameter sender: The object that sent the action.
80 | @IBAction func behaviorChanged(_ sender: NSSegmentedControl) {
81 | guard let behavior = AppBehavior(rawValue: sender.selectedSegment), let url = self.currentAppURL else { return }
82 | AppManager.default.propagate(behavior: behavior, forApp: self.currentAppID, at: url, from: .mainMenu)
83 | }
84 |
85 | // MARK: - Private functions
86 |
87 | /// Change the current running application presented by the view.
88 | ///
89 | /// - parameter app: The running application.
90 | /// - parameter behavior: The behavior for the application. Either from the rules collection or infered if none.
91 | private func setCurrent(app: NSRunningApplication) {
92 | guard let id = app.bundleIdentifier ?? app.executableURL?.lastPathComponent,
93 | let url = app.bundleURL ?? app.executableURL else { return }
94 |
95 | self.currentAppID = id
96 | self.currentAppURL = url
97 | let behavior = AppManager.default.behaviorForApp(id: id)
98 |
99 | behaviorSegment.setSelected(true, forSegment: behavior.rawValue)
100 | appIconView.image = app.icon
101 | if let name = app.localizedName {
102 | appNameLabel.stringValue = name
103 | } else {
104 | appNameLabel.stringValue = "An app"
105 | }
106 | }
107 |
108 | // MARK: - ActiveApplicationDidChangeObserver
109 |
110 | func activeApplicationDidChangw(notification: Notification) {
111 | guard let app = notification.userInfo?[NSWorkspace.applicationUserInfoKey] as? NSRunningApplication else { return }
112 | self.setCurrent(app: app)
113 | }
114 |
115 | // MARK: - BehaviorDidChangeObserver
116 |
117 | func behaviorDidChangeForApp(notification: Notification) {
118 | guard let userInfo = notification.userInfo as? [String: Any], userInfo["source"] as? NotificationSource != .mainMenu else { return }
119 | guard let id = userInfo["id"] as? String, self.currentAppID == id, let behavior = userInfo["behavior"] as? AppBehavior else { return }
120 |
121 | behaviorSegment.setSelected(true, forSegment: behavior.rawValue)
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/Fluor/Controllers/ViewControllers/DefaultModeViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DefaultModeViewController.swift
3 | //
4 | // Fluor
5 | //
6 | // MIT License
7 | //
8 | // Copyright (c) 2020 Pierre Tacchi
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining a copy
11 | // of this software and associated documentation files (the "Software"), to deal
12 | // in the Software without restriction, including without limitation the rights
13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | // copies of the Software, and to permit persons to whom the Software is
15 | // furnished to do so, subject to the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be included in all
18 | // copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | // SOFTWARE.
27 | //
28 |
29 |
30 | import Cocoa
31 |
32 | @objc protocol DefaultModeViewControllerDelegate: class {
33 | @objc optional func defaultModeController(_ controller: DefaultModeViewController, willChangeModeTo mode: FKeyMode)
34 | func defaultModeController(_ controller: DefaultModeViewController, didChangeModeTo mode: FKeyMode)
35 | }
36 |
37 | class DefaultModeViewController: NSViewController {
38 | @IBOutlet weak var delegate: (AnyObject & DefaultModeViewControllerDelegate)?
39 |
40 | /// Change the current keyboard state.
41 | ///
42 | /// - parameter sender: The object that sent the action.
43 | @IBAction func changeMode(_ sender: NSSegmentedControl) {
44 | guard let state = FKeyMode(rawValue: sender.selectedSegment) else { return }
45 | delegate?.defaultModeController?(self, willChangeModeTo: state)
46 | delegate?.defaultModeController(self, didChangeModeTo: state)
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Fluor/Controllers/ViewControllers/PreferencesTabViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PreferencesTabViewController.swift
3 | //
4 | // Fluor
5 | //
6 | // MIT License
7 | //
8 | // Copyright (c) 2020 Pierre Tacchi
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining a copy
11 | // of this software and associated documentation files (the "Software"), to deal
12 | // in the Software without restriction, including without limitation the rights
13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | // copies of the Software, and to permit persons to whom the Software is
15 | // furnished to do so, subject to the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be included in all
18 | // copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | // SOFTWARE.
27 | //
28 |
29 |
30 | import Cocoa
31 |
32 | class PreferencesTabViewController: NSTabViewController, TriggerSectionVisibilityDidChangePoster, SwitchMethodDidChangePoster {
33 | @IBAction func changeTriggerSectionVisibility(_ sender: NSButton) {
34 | let visible = sender.state == .off
35 | if !visible {
36 | self.postSwitchMethodDidChangeNotification(method: .window)
37 | AppManager.default.switchMethod = .window
38 | }
39 | self.postTriggerSectionVisibilityDidChange(visible: visible)
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Fluor/Controllers/ViewControllers/ReleaseNotesViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ReleaseNotesViewController.swift
3 | //
4 | // Fluor
5 | //
6 | // MIT License
7 | //
8 | // Copyright (c) 2020 Pierre Tacchi
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining a copy
11 | // of this software and associated documentation files (the "Software"), to deal
12 | // in the Software without restriction, including without limitation the rights
13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | // copies of the Software, and to permit persons to whom the Software is
15 | // furnished to do so, subject to the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be included in all
18 | // copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | // SOFTWARE.
27 | //
28 |
29 |
30 | import Cocoa
31 | import WebKit
32 |
33 | class ReleaseNotesViewController: NSViewController, WKNavigationDelegate {
34 | @IBOutlet weak var webView: WKWebView!
35 |
36 | func show(url: URL) {
37 | let request = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalCacheData)
38 | self.webView.load(request)
39 | }
40 |
41 | // MARK: - WKNavigationDelegate
42 |
43 | func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
44 | if navigationAction.navigationType == .linkActivated{
45 | if let url = navigationAction.request.url {
46 | NSWorkspace.shared.open(url)
47 | }
48 |
49 | decisionHandler(.cancel)
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/Fluor/Controllers/ViewControllers/RunningAppsViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RunningAppsViewController.swift
3 | //
4 | // Fluor
5 | //
6 | // MIT License
7 | //
8 | // Copyright (c) 2020 Pierre Tacchi
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining a copy
11 | // of this software and associated documentation files (the "Software"), to deal
12 | // in the Software without restriction, including without limitation the rights
13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | // copies of the Software, and to permit persons to whom the Software is
15 | // furnished to do so, subject to the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be included in all
18 | // copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | // SOFTWARE.
27 | //
28 |
29 |
30 | import Cocoa
31 |
32 | class RunningAppsViewController: NSViewController, NSTableViewDelegate {
33 | @IBOutlet weak var tableView: NSTableView!
34 | @IBOutlet var itemsArrayController: NSArrayController!
35 |
36 | @objc dynamic var runningAppsArray = [RunningApp]()
37 | @objc dynamic var showAll: Bool = AppManager.default.showAllRunningProcesses {
38 | didSet { self.reloadData() }
39 | }
40 | @objc dynamic var searchPredicate: NSPredicate?
41 | @objc dynamic var sortDescriptors: [NSSortDescriptor] = [.init(key: "name", ascending: true, selector: #selector(NSString.caseInsensitiveCompare(_:)))]
42 |
43 | private var tableContentAnimator: TableViewContentAnimator!
44 |
45 | override func viewDidLoad() {
46 | super.viewDidLoad()
47 |
48 | self.tableContentAnimator = TableViewContentAnimator(tableView: tableView, arrayController: itemsArrayController)
49 | self.tableContentAnimator.performUnanimated {
50 | self.reloadData()
51 | }
52 |
53 | self.applyAsObserver()
54 | }
55 |
56 | deinit {
57 | NSWorkspace.shared.notificationCenter.removeObserver(self)
58 | }
59 |
60 | /// Called whenever an application is launched by the system or the user.
61 | ///
62 | /// - parameter notification: The notification.
63 | @objc private func appDidLaunch(notification: Notification) {
64 | guard let app = notification.userInfo?[NSWorkspace.applicationUserInfoKey] as? NSRunningApplication,
65 | let id = app.bundleIdentifier ?? app.executableURL?.lastPathComponent,
66 | let url = app.bundleURL ?? app.executableURL else { return }
67 | let isApp = app.activationPolicy == .regular
68 | guard self.showAll || isApp else { return }
69 | let behavior = AppManager.default.behaviorForApp(id: id)
70 | let item = RunningApp(id: id, url: url, behavior: behavior, pid: app.processIdentifier, isApp: isApp)
71 |
72 | self.runningAppsArray.append(item)
73 | }
74 |
75 | /// Called whenever an application is terminated by the system or the user.
76 | ///
77 | /// - parameter notification: The notification.
78 | @objc private func appDidTerminate(notification: Notification) {
79 | guard let app = notification.userInfo?[NSWorkspace.applicationUserInfoKey] as? NSRunningApplication,
80 | let item = runningAppsArray.first(where: { $0.pid == app.processIdentifier }), let index = runningAppsArray.firstIndex(of: item) else { return }
81 | self.runningAppsArray.remove(at: index)
82 | }
83 |
84 | /// Set `self` as an observer for *launch* and *terminate* notfications.
85 | private func applyAsObserver() {
86 | NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(appDidLaunch(notification:)), name: NSWorkspace.didLaunchApplicationNotification, object: nil)
87 | NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(appDidTerminate(notification:)), name: NSWorkspace.didTerminateApplicationNotification, object: nil)
88 | }
89 |
90 | /// Load all running applications and populate the table view with corresponding data.
91 | private func reloadData() {
92 | self.runningAppsArray = self.getRunningApps()
93 | }
94 |
95 | private func getRunningApps() -> [RunningApp] {
96 | return NSWorkspace.shared.runningApplications.compactMap { (app) -> RunningApp? in
97 | guard let id = app.bundleIdentifier ?? app.executableURL?.lastPathComponent, let url = app.bundleURL ?? app.executableURL else { return nil }
98 | let isApp = app.activationPolicy == .regular
99 | guard showAll || isApp else { return nil }
100 |
101 | let behavior = AppManager.default.behaviorForApp(id: id)
102 | let pid = app.processIdentifier
103 |
104 | return RunningApp(id: id, url: url, behavior: behavior, pid: pid, isApp: isApp)
105 | }
106 | }
107 |
108 | // MARK: - Table View Delegate
109 |
110 | func tableView(_ tableView: NSTableView, shouldSelectRow row: Int) -> Bool { false }
111 | }
112 |
--------------------------------------------------------------------------------
/Fluor/Controllers/ViewControllers/SwitchMethodSelectionViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SwitchMethodSelectionViewController.swift
3 | // Fluor
4 | //
5 | // Created by Pierre TACCHI on 26/02/2020.
6 | // Copyright © 2020 Pyrolyse. All rights reserved.
7 | //
8 |
9 | import Cocoa
10 |
11 | protocol WelcomeTabViewChildren: NSViewController {
12 | var welcomeTabViewController: WelcomeTabViewController? { get }
13 | }
14 |
15 | extension WelcomeTabViewChildren {
16 | var welcomeTabViewController: WelcomeTabViewController? {
17 | self.presentingViewController as? WelcomeTabViewController
18 | }
19 | }
20 |
21 | class SwitchMethodSelectionViewController: NSViewController, WelcomeTabViewChildren {
22 | @IBOutlet weak var activeAppSelectableView: SelectableView!
23 | @IBOutlet weak var fnKeySelectableView: SelectableView!
24 |
25 | deinit {
26 | self.resignAsObserver()
27 | }
28 |
29 | override func viewDidLoad() {
30 | super.viewDidLoad()
31 | self.applyAsObserver()
32 | }
33 |
34 | private func applyAsObserver() {
35 | self.activeAppSelectableView.addObserver(self, forKeyPath: "isSelected", options: [.new], context: nil)
36 | self.fnKeySelectableView.addObserver(self, forKeyPath: "isSelected", options: [.new], context: nil)
37 | }
38 |
39 | private func resignAsObserver() {
40 | self.activeAppSelectableView.removeObserver(self, forKeyPath: "isSelected")
41 | self.fnKeySelectableView.removeObserver(self, forKeyPath: "isSelected")
42 | }
43 |
44 | override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
45 | switch keyPath {
46 | case "isSelected":
47 | if object as AnyObject === self.activeAppSelectableView, change?[.newKey] as? Bool == true {
48 | self.activeAppHasBeenSelected()
49 | }
50 | if object as AnyObject === self.fnKeySelectableView, change?[.newKey] as? Bool == true {
51 | self.fnKeyHasBeenSelected()
52 | }
53 | default:
54 | super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
55 | }
56 | }
57 |
58 | private func activeAppHasBeenSelected() {
59 | self.fnKeySelectableView.isSelected = false
60 | }
61 |
62 | private func fnKeyHasBeenSelected() {
63 | self.activeAppSelectableView.isSelected = false
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/Fluor/Controllers/ViewControllers/SwitchMethodViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SwitchModeViewController.swift
3 | //
4 | // Fluor
5 | //
6 | // MIT License
7 | //
8 | // Copyright (c) 2020 Pierre Tacchi
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining a copy
11 | // of this software and associated documentation files (the "Software"), to deal
12 | // in the Software without restriction, including without limitation the rights
13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | // copies of the Software, and to permit persons to whom the Software is
15 | // furnished to do so, subject to the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be included in all
18 | // copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | // SOFTWARE.
27 | //
28 |
29 |
30 | import Cocoa
31 |
32 | class SwitchMethodViewController: NSViewController, MenuControlPoster, SwitchMethodDidChangePoster {
33 | @IBOutlet weak var methodSegmentedControl: NSSegmentedControl!
34 | @objc private dynamic var switchCapable: Bool = true
35 |
36 | @IBAction func changeSwitchMethod(_ sender: NSSegmentedControl) {
37 | guard let method = SwitchMethod(rawValue: sender.selectedSegment) else { return }
38 | self.postSwitchMethodDidChangeNotification(method: method)
39 | }
40 |
41 | @IBAction func askAccessibilityPersmission(_ sender: Any) {
42 | self.postMenuNeedsToCloseNotification()
43 | let options : NSDictionary = [kAXTrustedCheckOptionPrompt.takeRetainedValue(): true]
44 | AXIsProcessTrustedWithOptions(options)
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/Fluor/Controllers/ViewControllers/UserNotificationEnablementViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UserNotificationEnablementViewController.swift
3 | //
4 | // Fluor
5 | //
6 | // MIT License
7 | //
8 | // Copyright (c) 2020 Pierre Tacchi
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining a copy
11 | // of this software and associated documentation files (the "Software"), to deal
12 | // in the Software without restriction, including without limitation the rights
13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | // copies of the Software, and to permit persons to whom the Software is
15 | // furnished to do so, subject to the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be included in all
18 | // copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | // SOFTWARE.
27 | //
28 |
29 |
30 | import Cocoa
31 | import UserNotifications
32 |
33 | final class UserNotificationEnablementViewController: NSViewController, StoryboardInstantiable {
34 | static var storyboardName: NSStoryboard.Name { .preferences }
35 | static var sceneIdentifier: NSStoryboard.SceneIdentifier? { "NotificationsEnablement" }
36 |
37 | @IBOutlet weak var trailiingConstraint: NSLayoutConstraint!
38 | @IBOutlet weak var topConstraint: NSLayoutConstraint!
39 | @IBOutlet weak var bottomConstraint: NSLayoutConstraint!
40 | @IBOutlet weak var leadingConstraint: NSLayoutConstraint!
41 | private var stackViewConstraints: [NSLayoutConstraint] {
42 | [trailiingConstraint, topConstraint, bottomConstraint, leadingConstraint]
43 | }
44 |
45 | @objc dynamic var activeAppSwitch: Bool = true
46 | @objc dynamic var activeAppFnKey: Bool = true
47 | @objc dynamic var globalFnKey: Bool = true
48 | @objc dynamic var everytime: Bool = true
49 |
50 | @objc dynamic var isShownInAlert: Bool = false
51 |
52 | @objc dynamic var canEnableNotifications: Bool {
53 | everytime || activeAppSwitch || activeAppFnKey || globalFnKey
54 | }
55 |
56 | override func viewWillAppear() {
57 | self.adaptStackConstraints()
58 | guard !isShownInAlert, AppManager.default.userNotificationEnablement != .none else {
59 | if !isShownInAlert { UserNotificationEnablement.none.apply(to: self) }
60 | return
61 | }
62 | UserNotificationHelper.ifAuthorized(perform: {
63 | AppManager.default.userNotificationEnablement.apply(to: self)
64 | }) {
65 | UserNotificationEnablement.none.apply(to: self)
66 | }
67 | }
68 |
69 | @IBAction func checkBoxDidChange(_ sender: NSButton?) {
70 | if let tag = sender?.tag, tag == 1 {
71 | activeAppSwitch = everytime
72 | activeAppFnKey = everytime
73 | globalFnKey = everytime
74 | } else {
75 | everytime = activeAppSwitch && activeAppFnKey && globalFnKey
76 | }
77 | guard !isShownInAlert else { return }
78 | self.checkAuthorizations()
79 | }
80 |
81 | private func adaptStackConstraints() {
82 | stackViewConstraints.forEach { $0.constant = isShownInAlert ? 2 : 0 }
83 | }
84 |
85 | private func checkAuthorizations() {
86 | UserNotificationHelper.askUser { (isAuthorized) in
87 | if isAuthorized {
88 | AppManager.default.userNotificationEnablement = .from(self)
89 | } else {
90 | UserNotificationEnablement.none.apply(to: self)
91 | }
92 | }
93 | }
94 |
95 | override class func keyPathsForValuesAffectingValue(forKey key: String) -> Set {
96 | guard key == "canEnableNotifications" else {
97 | return super.keyPathsForValuesAffectingValue(forKey: key)
98 | }
99 |
100 | return .init(["activeAppSwitch", "activeAppFnKey", "globalFnKey", "everytime"])
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/Fluor/Controllers/WindowControllers/AboutWindowController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AboutWindowController.swift
3 | //
4 | // Fluor
5 | //
6 | // MIT License
7 | //
8 | // Copyright (c) 2020 Pierre Tacchi
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining a copy
11 | // of this software and associated documentation files (the "Software"), to deal
12 | // in the Software without restriction, including without limitation the rights
13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | // copies of the Software, and to permit persons to whom the Software is
15 | // furnished to do so, subject to the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be included in all
18 | // copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | // SOFTWARE.
27 | //
28 |
29 |
30 | import Cocoa
31 |
32 | final class AboutWindowController: NSWindowController, StoryboardInstantiable {
33 | static var storyboardName: NSStoryboard.Name = .about
34 | }
35 |
--------------------------------------------------------------------------------
/Fluor/Controllers/WindowControllers/PreferencesWindowController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PreferencesWindowController.swift
3 | //
4 | // Fluor
5 | //
6 | // MIT License
7 | //
8 | // Copyright (c) 2020 Pierre Tacchi
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining a copy
11 | // of this software and associated documentation files (the "Software"), to deal
12 | // in the Software without restriction, including without limitation the rights
13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | // copies of the Software, and to permit persons to whom the Software is
15 | // furnished to do so, subject to the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be included in all
18 | // copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | // SOFTWARE.
27 | //
28 |
29 |
30 | import Cocoa
31 |
32 | final class PreferencesWindowController: NSWindowController, StoryboardInstantiable {
33 | static var storyboardName: NSStoryboard.Name = .preferences
34 |
35 | override func windowDidLoad() {
36 | super.windowDidLoad()
37 |
38 | let toolbar = window?.toolbar
39 | toolbar?.insertItem(withItemIdentifier: .flexibleSpace, at: (toolbar?.items.count ?? 0) - 1)
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Fluor/Controllers/WindowControllers/ReleaseNotesWindowController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ReleaseNotesWindowController.swift
3 | //
4 | // Fluor
5 | //
6 | // MIT License
7 | //
8 | // Copyright (c) 2020 Pierre Tacchi
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining a copy
11 | // of this software and associated documentation files (the "Software"), to deal
12 | // in the Software without restriction, including without limitation the rights
13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | // copies of the Software, and to permit persons to whom the Software is
15 | // furnished to do so, subject to the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be included in all
18 | // copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | // SOFTWARE.
27 | //
28 |
29 |
30 | import Cocoa
31 |
32 | class ReleaseNotesWindowController: NSWindowController, NSWindowDelegate, StoryboardInstantiable {
33 | static var storyboardName: NSStoryboard.Name { .about }
34 | static var sceneIdentifier: NSStoryboard.SceneIdentifier? { "RNWC" }
35 |
36 | @objc dynamic var releases: [Release] = []
37 | private var session: URLSession?
38 |
39 | override func windowDidLoad() {
40 | super.windowDidLoad()
41 | self.populateList()
42 | }
43 |
44 | override func cancelOperation(_ sender: Any?) {
45 | window?.close()
46 | }
47 |
48 | // MARK: - NSWindowDelegate
49 |
50 | func windowWillClose(_ notification: Notification) {
51 | self.session?.invalidateAndCancel()
52 | }
53 |
54 | // MARK: - Actions
55 |
56 | @IBAction func changeVersion(_ sender: NSPopUpButton) {
57 | guard let release = sender.selectedItem?.representedObject as? Release else { fatalError() }
58 | self.show(url: release.url)
59 | }
60 |
61 | // MARK: - Private functions
62 |
63 | private func populateList() {
64 | guard let str = Bundle.main.infoDictionary?["FLRNListURL"] as? String,
65 | let url = URL(string: str) else {
66 | fatalError("No RN String !")
67 | }
68 |
69 | self.session = URLSession(configuration: .ephemeral)
70 |
71 | self.session?.dataTask(with: url, completionHandler: { (data, response, error) in
72 | if let error = error {
73 | DispatchQueue.main.async { [unowned self] in
74 | self.presentError(error, modalFor: self.window!, delegate: nil, didPresent: nil, contextInfo: nil)
75 | }
76 | } else if let data = data {
77 | do {
78 | let entries = try JSONDecoder().decode([Release].self, from: data)
79 | DispatchQueue.main.async {
80 | [unowned self] in self.releases = entries
81 | if let last = entries.first {
82 | self.show(url: last.url)
83 | }
84 | }
85 | } catch {
86 | DispatchQueue.main.async { [unowned self] in
87 | self.presentError(error, modalFor: self.window!, delegate: nil, didPresent: nil, contextInfo: nil)
88 | }
89 | }
90 | }
91 | }).resume()
92 | }
93 |
94 | private func show(url: URL) {
95 | guard let ctrl = self.contentViewController as? ReleaseNotesViewController else { fatalError() }
96 | ctrl.show(url: url)
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/Fluor/Controllers/WindowControllers/RulesEditorWindowController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RulesEditorWindowController.swift
3 | //
4 | // Fluor
5 | //
6 | // MIT License
7 | //
8 | // Copyright (c) 2020 Pierre Tacchi
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining a copy
11 | // of this software and associated documentation files (the "Software"), to deal
12 | // in the Software without restriction, including without limitation the rights
13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | // copies of the Software, and to permit persons to whom the Software is
15 | // furnished to do so, subject to the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be included in all
18 | // copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | // SOFTWARE.
27 | //
28 |
29 |
30 | import Cocoa
31 |
32 | final class RulesEditorWindowController: NSWindowController, StoryboardInstantiable {
33 | static let storyboardName: NSStoryboard.Name = .rulesEditor
34 |
35 | @IBAction func filterRuleList(_ sender: NSSearchField) {
36 | let searchString = sender.stringValue
37 | if searchString != "" {
38 | let predicate = NSPredicate(format: "name CONTAINS[cd] %@", searchString)
39 | (self.contentViewController as? RulesEditorViewController)?.searchPredicate = predicate
40 | } else {
41 | (self.contentViewController as? RulesEditorViewController)?.searchPredicate = nil
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/Fluor/Controllers/WindowControllers/RunningAppWindowController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RunningAppWindowController.swift
3 | //
4 | // Fluor
5 | //
6 | // MIT License
7 | //
8 | // Copyright (c) 2020 Pierre Tacchi
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining a copy
11 | // of this software and associated documentation files (the "Software"), to deal
12 | // in the Software without restriction, including without limitation the rights
13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | // copies of the Software, and to permit persons to whom the Software is
15 | // furnished to do so, subject to the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be included in all
18 | // copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | // SOFTWARE.
27 | //
28 |
29 |
30 | import Cocoa
31 |
32 | final class RunningAppWindowController: NSWindowController, StoryboardInstantiable {
33 | static let storyboardName: NSStoryboard.Name = .runningApps
34 |
35 | @IBAction func filterAppList(_ sender: NSSearchField) {
36 | let searchString = sender.stringValue
37 | if searchString != "" {
38 | let predicate = NSPredicate(format: "name CONTAINS[cd] %@", searchString)
39 | (self.contentViewController as? RunningAppsViewController)?.searchPredicate = predicate
40 | } else {
41 | (self.contentViewController as? RunningAppsViewController)?.searchPredicate = nil
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/Fluor/Extensions/NSStoryboardNamesExtension.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NSStoryboardNamesExtension.swift
3 | //
4 | // Fluor
5 | //
6 | // MIT License
7 | //
8 | // Copyright (c) 2020 Pierre Tacchi
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining a copy
11 | // of this software and associated documentation files (the "Software"), to deal
12 | // in the Software without restriction, including without limitation the rights
13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | // copies of the Software, and to permit persons to whom the Software is
15 | // furnished to do so, subject to the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be included in all
18 | // copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | // SOFTWARE.
27 | //
28 |
29 |
30 | import Cocoa
31 |
32 | extension NSStoryboard.Name {
33 | static let preferences = "Preferences"
34 | static let runningApps = "RunningApps"
35 | static let rulesEditor = "RulesEditor"
36 | static let about = "About"
37 | static let welcome = "Welcome"
38 | }
39 |
--------------------------------------------------------------------------------
/Fluor/Extensions/NSViewExtension.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NSViewExtension.swift
3 | //
4 | // Fluor
5 | //
6 | // MIT License
7 | //
8 | // Copyright (c) 2020 Pierre Tacchi
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining a copy
11 | // of this software and associated documentation files (the "Software"), to deal
12 | // in the Software without restriction, including without limitation the rights
13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | // copies of the Software, and to permit persons to whom the Software is
15 | // furnished to do so, subject to the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be included in all
18 | // copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | // SOFTWARE.
27 | //
28 |
29 |
30 | import Cocoa
31 |
32 | extension NSView {
33 | var isDark: Bool {
34 | if #available(OSX 10.14, *) {
35 | return effectiveAppearance.bestMatch(from: [.darkAqua,
36 | .accessibilityHighContrastDarkAqua,
37 | .vibrantDark,
38 | .accessibilityHighContrastVibrantDark]) != nil
39 | } else {
40 | return false
41 | }
42 | }
43 |
44 | var isAccessible: Bool {
45 | if #available(OSX 10.14, *) {
46 | return effectiveAppearance.bestMatch(from: [.accessibilityHighContrastAqua,
47 | .accessibilityHighContrastVibrantLight,
48 | .accessibilityHighContrastDarkAqua,
49 | .accessibilityHighContrastVibrantDark]) != nil
50 | } else {
51 | return false
52 | }
53 | }
54 |
55 | func centerLayerAnchor() {
56 | let x = self.frame.midX
57 | let y = self.frame.midY
58 |
59 | self.layer?.anchorPoint = CGPoint(x: 0.5, y: 0.5)
60 | self.layer?.position = CGPoint(x: x, y: y)
61 | self.layer?.contentsGravity = CALayerContentsGravity.center
62 | }
63 | }
64 |
65 |
--------------------------------------------------------------------------------
/Fluor/Extensions/ResultExtension.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ResultExtension.swift
3 | //
4 | // Fluor
5 | //
6 | // MIT License
7 | //
8 | // Copyright (c) 2020 Pierre Tacchi
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining a copy
11 | // of this software and associated documentation files (the "Software"), to deal
12 | // in the Software without restriction, including without limitation the rights
13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | // copies of the Software, and to permit persons to whom the Software is
15 | // furnished to do so, subject to the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be included in all
18 | // copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | // SOFTWARE.
27 | //
28 |
29 |
30 | extension Result {
31 | func getOrFailWith(_ block: (Failure) -> Never) -> Success {
32 | switch self {
33 | case .success(let success):
34 | return success
35 | case .failure(let failure):
36 | block(failure)
37 | }
38 | }
39 | }
40 |
41 |
--------------------------------------------------------------------------------
/Fluor/Extensions/SetExtension.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SetExtension.swift
3 | //
4 | // Fluor
5 | //
6 | // MIT License
7 | //
8 | // Copyright (c) 2020 Pierre Tacchi
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining a copy
11 | // of this software and associated documentation files (the "Software"), to deal
12 | // in the Software without restriction, including without limitation the rights
13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | // copies of the Software, and to permit persons to whom the Software is
15 | // furnished to do so, subject to the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be included in all
18 | // copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | // SOFTWARE.
27 | //
28 |
29 |
30 | import DefaultsWrapper
31 |
32 | extension Set: UserDefaultsConvertible where Element: UserDefaultsConvertible {
33 | public func convertedObject() -> [Element.PropertyListSerializableType] {
34 | self.map { $0.convertedObject() }
35 | }
36 |
37 | public static func instanciate(from object: [Element.PropertyListSerializableType]) -> Self? {
38 | Set(object.compactMap(Element.instanciate(from:)))
39 | }
40 | }
41 |
42 |
--------------------------------------------------------------------------------
/Fluor/Fluor-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | //
2 | // Fluor-Bridging-Header.h
3 | //
4 | // Fluor
5 | //
6 | // Use this file to import your target's public headers that you would like to expose to Swift.
7 | //
8 |
9 | #include "LaunchAtLoginController.h"
10 | #include "PFMoveApplication.h"
11 |
--------------------------------------------------------------------------------
/Fluor/Fluor.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.cs.disable-library-validation
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Fluor/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | $(MARKETING_VERSION)
21 | CFBundleVersion
22 | 2345
23 | FLGithubURL
24 | https://github.com/Pyroh/Fluor
25 | FLPyrolyseURL
26 | https://pyrolyse.it
27 | FLRNListURL
28 | https://resources.pyrolyse.it/releasenotes/Fluor/versions.json
29 | FLSupportEmail
30 | mailto:fluor.support@pyrolyse.it?subject=Fluor%20Issue
31 | FLSupportURL
32 | https://pyrolyse.it
33 | FLTwitterURL
34 | https://twitter.com/__pyroh
35 | LSApplicationCategoryType
36 | public.app-category.productivity
37 | LSMinimumSystemVersion
38 | $(MACOSX_DEPLOYMENT_TARGET)
39 | LSUIElement
40 |
41 | NSHumanReadableCopyright
42 | Copyright © 2016 - 2020 Pierre TACCHI. All rights reserved.
43 | NSMainNibFile
44 | Main
45 | NSPrincipalClass
46 | NSApplication
47 | NSServices
48 |
49 |
50 | NSMenuItem
51 |
52 |
53 |
54 | NSSupportsAutomaticGraphicsSwitching
55 |
56 | SUFeedURL
57 | https://updates.pyrolyse.co/Fluor/2.0/appcast.xml
58 | SUPublicDSAKeyFile
59 | dsa_pub.pem
60 | SUPublicEDKey
61 | 2SzTTYB9kulc+kJ8i0YdyKel2RoNIRKrJ8xp/wXWVyk=
62 |
63 |
64 |
--------------------------------------------------------------------------------
/Fluor/Misc/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | //
4 | // Fluor
5 | //
6 | // MIT License
7 | //
8 | // Copyright (c) 2020 Pierre Tacchi
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining a copy
11 | // of this software and associated documentation files (the "Software"), to deal
12 | // in the Software without restriction, including without limitation the rights
13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | // copies of the Software, and to permit persons to whom the Software is
15 | // furnished to do so, subject to the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be included in all
18 | // copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | // SOFTWARE.
27 | //
28 |
29 |
30 | import Cocoa
31 |
32 | @NSApplicationMain
33 | class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate {
34 | let statusMenuController: StatusMenuController = .init()
35 |
36 | func applicationDidFinishLaunching(_ notification: Notification) {
37 | #if RELEASE
38 | PFMoveToApplicationsFolderIfNecessary()
39 | #endif
40 |
41 | ValueTransformer.setValueTransformer(RuleValueTransformer(), forName: NSValueTransformerName("RuleValueTransformer"))
42 |
43 | // Check accessibility
44 | if !AXIsProcessTrusted() && !AppManager.default.hasAlreadyAnsweredAccessibility {
45 | let options : NSDictionary = [kAXTrustedCheckOptionPrompt.takeRetainedValue(): true]
46 | AXIsProcessTrustedWithOptions(options)
47 | AppManager.default.hasAlreadyAnsweredAccessibility = true
48 | }
49 |
50 | if AppManager.default.lastRunVersion != self.getBundleVersion() {
51 | AppManager.default.lastRunVersion = self.getBundleVersion()
52 | let rnctrl = ReleaseNotesWindowController.instantiate()
53 | rnctrl.window?.orderFrontRegardless()
54 | }
55 |
56 | UserNotificationHelper.askUserAtLaunch()
57 |
58 | self.loadMainMenu()
59 | }
60 |
61 | private func loadMainMenu() {
62 | let nib = NSNib(nibNamed: "MainMenu", bundle: nil)
63 | nib?.instantiate(withOwner: self.statusMenuController, topLevelObjects: nil)
64 |
65 | NSApp.hide(self)
66 | }
67 |
68 | private func getBundleVersion() -> String {
69 | Bundle.main.infoDictionary?["CFBundleShortVersionString"] as! String
70 | }
71 |
72 | func windowWillClose(_ notification: Notification) {
73 | self.loadMainMenu()
74 | }
75 | }
76 |
77 |
78 |
--------------------------------------------------------------------------------
/Fluor/Misc/AppErrorManager.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppExterminator.swift
3 | //
4 | // Fluor
5 | //
6 | // MIT License
7 | //
8 | // Copyright (c) 2020 Pierre Tacchi
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining a copy
11 | // of this software and associated documentation files (the "Software"), to deal
12 | // in the Software without restriction, including without limitation the rights
13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | // copies of the Software, and to permit persons to whom the Software is
15 | // furnished to do so, subject to the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be included in all
18 | // copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | // SOFTWARE.
27 | //
28 |
29 |
30 | import Cocoa
31 |
32 | enum AppErrorManager {
33 | static func showError(withReason reason: @autoclosure () -> String, andMessage msg: String? = nil) {
34 | let info = reason()
35 | let message = msg ?? NSLocalizedString("Sorry, an unexpected error occured.", comment: "")
36 | let alert = NSAlert()
37 |
38 | alert.alertStyle = .warning
39 | alert.informativeText = info
40 | alert.messageText = message
41 | alert.runModal()
42 | }
43 |
44 | static func terminateApp(withReason reason: @autoclosure () -> String, andMessage msg: String? = nil) -> Never {
45 | let info = reason()
46 | let message = msg ?? NSLocalizedString("Sorry, an unexpected error occured.", comment: "")
47 | let alert = NSAlert()
48 |
49 | alert.alertStyle = .critical
50 | alert.informativeText = info
51 | alert.messageText = message
52 | alert.runModal()
53 |
54 | NSApp.terminate(self)
55 | fatalError(info)
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Fluor/Misc/FKeyManager.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FKeyManager.swift
3 | //
4 | // Fluor
5 | //
6 | // MIT License
7 | //
8 | // Copyright (c) 2020 Pierre Tacchi
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining a copy
11 | // of this software and associated documentation files (the "Software"), to deal
12 | // in the Software without restriction, including without limitation the rights
13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | // copies of the Software, and to permit persons to whom the Software is
15 | // furnished to do so, subject to the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be included in all
18 | // copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | // SOFTWARE.
27 | //
28 |
29 |
30 | enum FKeyManager {
31 | typealias FKeyManagerResult = Result
32 |
33 | enum FKeyManagerError: Error {
34 | case cannotCreateMasterPort
35 | case cannotOpenService
36 | case cannotSetParameter
37 | case cannotGetParameter
38 |
39 | case otherError
40 |
41 | var localizedDescription: String {
42 | switch self {
43 | case .cannotCreateMasterPort:
44 | return "Master port creation failed (E1)"
45 | case .cannotOpenService:
46 | return "Service opening failed (E2)"
47 | case .cannotSetParameter:
48 | return "Parameter set not possible (E3)"
49 | case .cannotGetParameter:
50 | return "Parameter read not possible (E4)"
51 | default:
52 | return "Unknown error (E99)"
53 | }
54 | }
55 | }
56 |
57 | static func setCurrentFKeyMode(_ mode: FKeyMode) throws {
58 | let connect = try FKeyManager.getServiceConnect()
59 | let value = mode.rawValue as CFNumber
60 |
61 | guard IOHIDSetCFTypeParameter(connect, kIOHIDFKeyModeKey as CFString, value) == KERN_SUCCESS else {
62 | throw FKeyManagerError.cannotSetParameter
63 | }
64 |
65 | IOServiceClose(connect)
66 | }
67 |
68 | static func getCurrentFKeyMode() -> FKeyManagerResult {
69 | FKeyManagerResult {
70 | let ri = try self.getIORegistry()
71 | defer { IOObjectRelease(ri) }
72 |
73 | let entry = IORegistryEntryCreateCFProperty(ri, "HIDParameters" as CFString, kCFAllocatorDefault, 0).autorelease()
74 |
75 | guard let dict = entry.takeUnretainedValue() as? NSDictionary,
76 | let mode = dict.value(forKey: "HIDFKeyMode") as? Int,
77 | let currentMode = FKeyMode(rawValue: mode) else {
78 | throw FKeyManagerError.cannotGetParameter
79 | }
80 |
81 | return currentMode
82 | }
83 | }
84 |
85 | private static func getIORegistry() throws -> io_registry_entry_t {
86 | var masterPort: mach_port_t = .zero
87 | guard IOMasterPort(bootstrap_port, &masterPort) == KERN_SUCCESS else { throw FKeyManagerError.cannotCreateMasterPort }
88 |
89 | return IORegistryEntryFromPath(masterPort, "IOService:/IOResources/IOHIDSystem")
90 | }
91 |
92 | private static func getIOHandle() throws -> io_service_t {
93 | try self.getIORegistry() as io_service_t
94 | }
95 |
96 | private static func getServiceConnect() throws -> io_connect_t {
97 | var service: io_connect_t = .zero
98 | let handle = try self.getIOHandle()
99 | defer { IOObjectRelease(handle) }
100 |
101 | guard IOServiceOpen(handle, mach_task_self_, UInt32(kIOHIDParamConnectType), &service) == KERN_SUCCESS else {
102 | throw FKeyManagerError.cannotOpenService
103 | }
104 |
105 | return service
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/Fluor/Misc/PFMoveApplication.h:
--------------------------------------------------------------------------------
1 | //
2 | // PFMoveApplication.h, version 1.24
3 | // LetsMove
4 | //
5 | // Created by Andy Kim at Potion Factory LLC on 9/17/09
6 | //
7 | // The contents of this file are dedicated to the public domain.
8 |
9 | #ifdef __cplusplus
10 | extern "C" {
11 | #endif
12 |
13 | #import
14 |
15 | /**
16 | Moves the running application to ~/Applications or /Applications if the former does not exist.
17 | After the move, it relaunches app from the new location.
18 | DOES NOT work for sandboxed applications.
19 |
20 | Call from \c NSApplication's delegate method \c -applicationWillFinishLaunching: method. */
21 | void PFMoveToApplicationsFolderIfNecessary(void);
22 |
23 | /**
24 | Check whether an app move is currently in progress.
25 | Returns YES if LetsMove is currently in-progress trying to move the app to the Applications folder, or NO otherwise.
26 | This can be used to work around a crash with apps that terminate after last window is closed.
27 | See https://github.com/potionfactory/LetsMove/issues/64 for details. */
28 | BOOL PFMoveIsInProgress(void);
29 |
30 | #ifdef __cplusplus
31 | }
32 | #endif
33 |
--------------------------------------------------------------------------------
/Fluor/Models/Enums.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Enums.swift
3 | //
4 | // Fluor
5 | //
6 | // MIT License
7 | //
8 | // Copyright (c) 2020 Pierre Tacchi
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining a copy
11 | // of this software and associated documentation files (the "Software"), to deal
12 | // in the Software without restriction, including without limitation the rights
13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | // copies of the Software, and to permit persons to whom the Software is
15 | // furnished to do so, subject to the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be included in all
18 | // copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | // SOFTWARE.
27 | //
28 |
29 | import DefaultsWrapper
30 |
31 | @objc enum FKeyMode: Int {
32 | case media = 0
33 | case function
34 |
35 | var behavior: AppBehavior {
36 | switch self {
37 | case .media:
38 | return .media
39 | case .function:
40 | return .function
41 | }
42 | }
43 |
44 | var counterPart: FKeyMode {
45 | switch self {
46 | case .media: return .function
47 | case .function: return .media
48 | }
49 | }
50 |
51 | var label: String {
52 | switch self {
53 | case .media:
54 | return NSLocalizedString("Media keys", comment: "")
55 | case .function:
56 | return NSLocalizedString("Function keys", comment: "")
57 | }
58 | }
59 | }
60 |
61 | @objc enum AppBehavior: Int {
62 | case inferred = 0
63 | case media
64 | case function
65 |
66 | var counterPart: AppBehavior {
67 | switch self {
68 | case .media:
69 | return .function
70 | case .function:
71 | return .media
72 | default:
73 | return .inferred
74 | }
75 | }
76 |
77 | var label: String {
78 | switch self {
79 | case .inferred:
80 | return NSLocalizedString("Same as default", comment: "")
81 | case .media:
82 | return NSLocalizedString("Media keys", comment: "")
83 | case .function:
84 | return NSLocalizedString("Function keys", comment: "")
85 | }
86 | }
87 | }
88 |
89 | @objc enum SwitchMethod: Int {
90 | case window = 0
91 | case hybrid
92 | case key
93 | }
94 |
95 | enum ItemKind {
96 | case rule
97 | case runningApp
98 |
99 | var source: NotificationSource {
100 | switch self {
101 | case .rule:
102 | return .rule
103 | case .runningApp:
104 | return .runningApp
105 | }
106 | }
107 | }
108 |
109 | enum NotificationSource {
110 | case rule
111 | case runningApp
112 | case mainMenu
113 | case fnKey
114 | case behaviorManager
115 | case undefined
116 | }
117 |
118 | struct UserNotificationEnablement: OptionSet {
119 | let rawValue: Int
120 |
121 | static let appSwitch: Self = .init(rawValue: 1 << 0)
122 | static let appKey: Self = .init(rawValue: 1 << 1)
123 | static let globalKey: Self = .init(rawValue: 1 << 2)
124 |
125 | static let all: Self = [.appSwitch, .appKey, .globalKey]
126 | static let none: Self = []
127 |
128 | static func from(_ vc: UserNotificationEnablementViewController) -> Self {
129 | guard !vc.everytime else { return .all }
130 | return Self.none
131 | .union(vc.activeAppSwitch ? .appSwitch : .none)
132 | .union(vc.activeAppFnKey ? .appKey : .none)
133 | .union(vc.globalFnKey ? .globalKey : .none)
134 | }
135 |
136 | func apply(to vc: UserNotificationEnablementViewController) {
137 | if self == .all {
138 | vc.everytime = true
139 | vc.activeAppSwitch = true
140 | vc.activeAppFnKey = true
141 | vc.globalFnKey = true
142 | } else if self == .none {
143 | vc.everytime = false
144 | vc.activeAppSwitch = false
145 | vc.activeAppFnKey = false
146 | vc.globalFnKey = false
147 | } else {
148 | vc.everytime = false
149 | vc.activeAppSwitch = self.contains(.appSwitch)
150 | vc.activeAppFnKey = self.contains(.appKey)
151 | vc.globalFnKey = self.contains(.globalKey)
152 | }
153 | }
154 | }
155 |
--------------------------------------------------------------------------------
/Fluor/Models/Items.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RulesTableItem.swift
3 | //
4 | // Fluor
5 | //
6 | // MIT License
7 | //
8 | // Copyright (c) 2020 Pierre Tacchi
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining a copy
11 | // of this software and associated documentation files (the "Software"), to deal
12 | // in the Software without restriction, including without limitation the rights
13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | // copies of the Software, and to permit persons to whom the Software is
15 | // furnished to do so, subject to the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be included in all
18 | // copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | // SOFTWARE.
27 | //
28 |
29 | import Cocoa
30 | import DefaultsWrapper
31 |
32 | class Item: NSObject, Identifiable {
33 | var notificationSource: NotificationSource { .undefined }
34 |
35 | let id: String
36 | @objc let url: URL
37 | @objc dynamic var behavior: AppBehavior
38 |
39 | @objc var icon: NSImage { NSWorkspace.shared.icon(forFile: self.url.path) }
40 | @objc var name: String { Bundle(path: self.url.path)?.localizedInfoDictionary?["CFBundleName"] as? String ?? self.url.deletingPathExtension().lastPathComponent }
41 |
42 | override var hash: Int {
43 | self.url.hashValue
44 | }
45 |
46 | init(id: String, url: URL, behavior: AppBehavior) {
47 | self.id = id
48 | self.url = url
49 | self.behavior = behavior
50 | }
51 | }
52 |
53 | final class RunningApp: Item, BehaviorDidChangeObserver {
54 | override var notificationSource: NotificationSource { .runningApp }
55 |
56 | let pid: pid_t
57 | @objc let isApp: Bool
58 |
59 | override var hash: Int {
60 | Int(self.pid)
61 | }
62 |
63 | init(id: String, url: URL, behavior: AppBehavior, pid: pid_t, isApp: Bool) {
64 | self.pid = pid
65 | self.isApp = isApp
66 |
67 | super.init(id: id, url: url, behavior: behavior)
68 |
69 | self.startObservingBehaviorDidChange()
70 | }
71 |
72 | deinit {
73 | self.stopObservingBehaviorDidChange()
74 | }
75 |
76 | // MARK: BehaviorDidChangeObserver
77 | func behaviorDidChangeForApp(notification: Notification) {
78 | guard let id = notification.userInfo?["id"] as? String, self.id == id,
79 | let appBehavior = notification.userInfo?["behavior"] as? AppBehavior else { return }
80 | self.behavior = appBehavior
81 | }
82 | }
83 |
84 |
85 | final class Rule: Item, UserDefaultsConvertible {
86 | override var notificationSource: NotificationSource { .rule }
87 |
88 | override var hash: Int {
89 | self.url.hashValue
90 | }
91 |
92 | // MARK: UserDefaultsConvertible
93 |
94 | func convertedObject() -> [String: Any] {
95 | ["id": self.id, "path": self.url.path, "behavior": self.behavior.rawValue]
96 | }
97 |
98 | static func instanciate(from object: [String: Any]) -> Rule? {
99 | guard let id = object["id"] as? String, let path = object["path"] as? String, let rawBehavior = object["behavior"] as? Int, let behavior = AppBehavior(rawValue: rawBehavior) else { return nil }
100 | let url = URL(fileURLWithPath: path)
101 | return Rule(id: id, url: url, behavior: behavior)
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/Fluor/Models/Release.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Release.swift
3 | //
4 | // Fluor
5 | //
6 | // MIT License
7 | //
8 | // Copyright (c) 2020 Pierre Tacchi
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining a copy
11 | // of this software and associated documentation files (the "Software"), to deal
12 | // in the Software without restriction, including without limitation the rights
13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | // copies of the Software, and to permit persons to whom the Software is
15 | // furnished to do so, subject to the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be included in all
18 | // copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | // SOFTWARE.
27 | //
28 |
29 |
30 | import Foundation
31 |
32 | @objcMembers
33 | class Release: NSObject, Decodable {
34 | dynamic let tag: String
35 | dynamic let url: URL
36 | dynamic var displayName: String {
37 | return String(format: NSLocalizedString("version %@", comment: ""), tag)
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/Fluor/Models/RuleValueTransformer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RuleValueTransformer.swift
3 | //
4 | // Fluor
5 | //
6 | // MIT License
7 | //
8 | // Copyright (c) 2020 Pierre Tacchi
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining a copy
11 | // of this software and associated documentation files (the "Software"), to deal
12 | // in the Software without restriction, including without limitation the rights
13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | // copies of the Software, and to permit persons to whom the Software is
15 | // furnished to do so, subject to the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be included in all
18 | // copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | // SOFTWARE.
27 | //
28 |
29 | import Cocoa
30 |
31 | class RuleValueTransformer: ValueTransformer {
32 | override class func allowsReverseTransformation() -> Bool {
33 | true
34 | }
35 |
36 | override class func transformedValueClass() -> AnyClass {
37 | NSNumber.self
38 | }
39 |
40 | override func transformedValue(_ value: Any?) -> Any? {
41 | (value as? Int).map { NSNumber(value: $0 - 1) }
42 | }
43 |
44 | override func reverseTransformedValue(_ value: Any?) -> Any? {
45 | (value as? Int).map { NSNumber(value: $0 + 1) }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/Fluor/Protocols/StoryboardInstantiableProtocol.swift:
--------------------------------------------------------------------------------
1 | //
2 | // StoryboardInstantiableProtocol.swift
3 | //
4 | // Fluor
5 | //
6 | // MIT License
7 | //
8 | // Copyright (c) 2020 Pierre Tacchi
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining a copy
11 | // of this software and associated documentation files (the "Software"), to deal
12 | // in the Software without restriction, including without limitation the rights
13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | // copies of the Software, and to permit persons to whom the Software is
15 | // furnished to do so, subject to the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be included in all
18 | // copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | // SOFTWARE.
27 | //
28 |
29 |
30 | import Cocoa
31 |
32 | protocol StoryboardInstantiable: NSObjectProtocol {
33 | static var storyboardName: NSStoryboard.Name { get }
34 | static var sceneIdentifier: NSStoryboard.SceneIdentifier? { get }
35 | static var bundle: Bundle? { get }
36 |
37 | static func instantiate() -> Self
38 | }
39 |
40 | extension StoryboardInstantiable {
41 | static var sceneIdentifier: NSStoryboard.SceneIdentifier? { nil }
42 | static var bundle: Bundle? { nil }
43 |
44 | static func instantiate() -> Self {
45 | if let id = sceneIdentifier {
46 | return NSStoryboard(name: storyboardName, bundle: bundle).instantiateController(withIdentifier: id) as! Self
47 | } else {
48 | return NSStoryboard(name: storyboardName, bundle: bundle).instantiateInitialController() as! Self
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/Fluor/Views/CheckableMenuItem.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CheckableMenuItem.swift
3 | //
4 | // Fluor
5 | //
6 | // MIT License
7 | //
8 | // Copyright (c) 2020 Pierre Tacchi
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining a copy
11 | // of this software and associated documentation files (the "Software"), to deal
12 | // in the Software without restriction, including without limitation the rights
13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | // copies of the Software, and to permit persons to whom the Software is
15 | // furnished to do so, subject to the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be included in all
18 | // copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | // SOFTWARE.
27 | //
28 |
29 |
30 | import Cocoa
31 |
32 | class CheckableMenuItem: NSMenuItem {
33 | private static let eraserImage = NSImage(size: NSSize(width: 16.0, height: 16.0))
34 |
35 | private var onStateImageShadow: NSImage?
36 | private var offStateImageShadow: NSImage?
37 | private var mixedStateImageShadow: NSImage?
38 |
39 | override var onStateImage: NSImage! {
40 | didSet {
41 | guard self.onStateImage != Self.eraserImage else { return }
42 | self.onStateImageShadow = self.onStateImage
43 | self.onStateImage = Self.eraserImage
44 | }
45 | }
46 |
47 | override var state: NSControl.StateValue {
48 | didSet {
49 | self.adaptImageToState()
50 | }
51 | }
52 |
53 | override init(title string: String, action selector: Selector?, keyEquivalent charCode: String) {
54 | super.init(title: string, action: selector, keyEquivalent: charCode)
55 | self.setup()
56 | self.adaptImageToState()
57 | }
58 |
59 | required init(coder decoder: NSCoder) {
60 | super.init(coder: decoder)
61 | self.setup()
62 | self.adaptImageToState()
63 | }
64 |
65 | private func setup() {
66 | self.onStateImageShadow = self.onStateImage
67 | self.offStateImageShadow = self.offStateImage
68 | self.mixedStateImageShadow = self.mixedStateImage
69 | self.onStateImage = Self.eraserImage
70 | self.offStateImage = Self.eraserImage
71 | self.mixedStateImage = Self.eraserImage
72 | }
73 |
74 | private func adaptImageToState() {
75 | switch self.state {
76 | case .on:
77 | self.image = self.onStateImageShadow
78 | case .off:
79 | self.image = self.offStateImageShadow
80 | default:
81 | self.image = self.mixedStateImageShadow
82 | }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/Fluor/Views/LinkButton.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LinkButton.swift
3 | //
4 | // Fluor
5 | //
6 | // MIT License
7 | //
8 | // Copyright (c) 2020 Pierre Tacchi
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining a copy
11 | // of this software and associated documentation files (the "Software"), to deal
12 | // in the Software without restriction, including without limitation the rights
13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | // copies of the Software, and to permit persons to whom the Software is
15 | // furnished to do so, subject to the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be included in all
18 | // copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | // SOFTWARE.
27 | //
28 |
29 |
30 | import Cocoa
31 | import SmoothOperators
32 |
33 | final class LinkButton: NSButton {
34 | @IBInspectable var url: String?
35 | private var actualURL: URL? {
36 | guard let url = url else { return nil }
37 | return URL(string: url)
38 | }
39 |
40 | override init(frame frameRect: NSRect) {
41 | super.init(frame: frameRect)
42 | setupAppearance()
43 | createAction()
44 | }
45 |
46 | required init?(coder: NSCoder) {
47 | super.init(coder: coder)
48 | setupAppearance()
49 | createAction()
50 | }
51 |
52 | private func setupAppearance() {
53 | isBordered = false
54 | imagePosition = .noImage
55 | alternateTitle = title
56 |
57 | var attributes = attributedTitle.fontAttributes(in: .init(location: 0, length: attributedTitle.length))
58 | attributes[.foregroundColor] = NSColor.linkColor
59 | attributes[.underlineStyle] = NSUnderlineStyle.single.rawValue
60 |
61 | let newAttributedTitle = NSAttributedString(string: title, attributes: attributes)
62 |
63 | attributedTitle = newAttributedTitle
64 | attributedAlternateTitle = newAttributedTitle
65 | }
66 |
67 | private func createAction() {
68 | target = self
69 | action = #selector(openURL(_:))
70 | }
71 |
72 | override func resetCursorRects() {
73 | super.resetCursorRects()
74 | self.addCursorRect(self.bounds, cursor: .pointingHand)
75 | }
76 |
77 | @IBAction func openURL(_ sender: Any?){
78 | guard !!url else { return }
79 | guard let destinationURL = actualURL else { return assertionFailure("\(self.url!) is not a valid URL.") }
80 | NSWorkspace.shared.open(destinationURL)
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/Fluor/Views/MenuItemView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OpaqueView.swift
3 | //
4 | // Fluor
5 | //
6 | // MIT License
7 | //
8 | // Copyright (c) 2020 Pierre Tacchi
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining a copy
11 | // of this software and associated documentation files (the "Software"), to deal
12 | // in the Software without restriction, including without limitation the rights
13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | // copies of the Software, and to permit persons to whom the Software is
15 | // furnished to do so, subject to the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be included in all
18 | // copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | // SOFTWARE.
27 | //
28 |
29 |
30 | import AppKit
31 |
32 | class MenuItemView: NSView {
33 | override func draw(_ dirtyRect: NSRect) {
34 | if #available(OSX 10.14, *), isAccessible {
35 | let darkComponent: CGFloat = 42.0/255
36 | let lightComponent: CGFloat = 244.0/255
37 | let component = isDark ? darkComponent : lightComponent
38 |
39 | NSColor(calibratedRed: component, green: component, blue: component, alpha: 1).setFill()
40 | dirtyRect.fill()
41 | } else {
42 | super.draw(dirtyRect)
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Fluor/Views/MoverEffectView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MoverEffectView.swift
3 | //
4 | // Fluor
5 | //
6 | // MIT License
7 | //
8 | // Copyright (c) 2020 Pierre Tacchi
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining a copy
11 | // of this software and associated documentation files (the "Software"), to deal
12 | // in the Software without restriction, including without limitation the rights
13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | // copies of the Software, and to permit persons to whom the Software is
15 | // furnished to do so, subject to the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be included in all
18 | // copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | // SOFTWARE.
27 | //
28 |
29 |
30 | import Cocoa
31 |
32 | class MoverEffectView: NSVisualEffectView {
33 | override func mouseDown(with event: NSEvent) {
34 | guard let window = self.window else { return }
35 | window.performDrag(with: event)
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Fluor/Views/MoverImageView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PassthroughImageView.swift
3 | //
4 | // Fluor
5 | //
6 | // MIT License
7 | //
8 | // Copyright (c) 2020 Pierre Tacchi
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining a copy
11 | // of this software and associated documentation files (the "Software"), to deal
12 | // in the Software without restriction, including without limitation the rights
13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | // copies of the Software, and to permit persons to whom the Software is
15 | // furnished to do so, subject to the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be included in all
18 | // copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | // SOFTWARE.
27 | //
28 |
29 |
30 | import Cocoa
31 |
32 | class MoverImageView: NSImageView {
33 | override var mouseDownCanMoveWindow: Bool { true }
34 | }
35 |
--------------------------------------------------------------------------------
/Fluor/Views/MultilinesCheckBoxLabel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MultilinesCheckBoxLabel.swift
3 | //
4 | // Fluor
5 | //
6 | // MIT License
7 | //
8 | // Copyright (c) 2020 Pierre Tacchi
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining a copy
11 | // of this software and associated documentation files (the "Software"), to deal
12 | // in the Software without restriction, including without limitation the rights
13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | // copies of the Software, and to permit persons to whom the Software is
15 | // furnished to do so, subject to the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be included in all
18 | // copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | // SOFTWARE.
27 | //
28 |
29 |
30 | import Cocoa
31 |
32 | class MultilinesCheckBoxLabel: NSTextField {
33 | @IBOutlet weak var checkBox: NSButton!
34 |
35 | override var isHighlighted: Bool {
36 | didSet {
37 | checkBox.isHighlighted = isHighlighted
38 | }
39 | }
40 | private var isClicked = false
41 |
42 | override func updateTrackingAreas() {
43 | super.updateTrackingAreas()
44 |
45 | self.trackingAreas.forEach(self.removeTrackingArea(_:))
46 | let trackingArea = NSTrackingArea(rect: self.bounds, options: [.activeAlways, .mouseEnteredAndExited, .enabledDuringMouseDrag], owner: self, userInfo: nil)
47 | self.addTrackingArea(trackingArea)
48 | }
49 |
50 | override func mouseDown(with event: NSEvent) {
51 | isClicked = true
52 | isHighlighted = true
53 | }
54 |
55 | override func mouseUp(with event: NSEvent) {
56 | if isHighlighted { checkBox.performClick(self) }
57 | isClicked = false
58 | }
59 |
60 | override func mouseEntered(with event: NSEvent) {
61 | if isClicked { isHighlighted = true }
62 | }
63 |
64 | override func mouseExited(with event: NSEvent) {
65 | if isClicked { isHighlighted = false }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/Fluor/Views/PoppingLinkButton.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PoppingLinkButton.swift
3 | //
4 | // Fluor
5 | //
6 | // MIT License
7 | //
8 | // Copyright (c) 2020 Pierre Tacchi
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining a copy
11 | // of this software and associated documentation files (the "Software"), to deal
12 | // in the Software without restriction, including without limitation the rights
13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | // copies of the Software, and to permit persons to whom the Software is
15 | // furnished to do so, subject to the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be included in all
18 | // copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | // SOFTWARE.
27 | //
28 |
29 |
30 | import Cocoa
31 |
32 | @IBDesignable
33 | class PoppingLinkButton: NSButton {
34 | @IBInspectable var growsOnHover: Bool = true
35 | @IBInspectable var growFactor: CGFloat = 1.15
36 |
37 | override func layout() {
38 | super.layout()
39 | self.centerLayerAnchor()
40 | }
41 |
42 | override func updateTrackingAreas() {
43 | super.updateTrackingAreas()
44 |
45 | self.trackingAreas.forEach(self.removeTrackingArea(_:))
46 | let trackingArea = NSTrackingArea(rect: self.bounds, options: [.activeAlways, .mouseEnteredAndExited], owner: self, userInfo: nil)
47 | self.addTrackingArea(trackingArea)
48 | }
49 |
50 | override func resetCursorRects() {
51 | super.resetCursorRects()
52 | self.addCursorRect(self.bounds, cursor: .pointingHand)
53 | }
54 |
55 | // Thanks to Kite Compositor (kiteapp.co)
56 | override func mouseEntered(with event: NSEvent) {
57 | guard self.growsOnHover, let layer = self.layer else { return }
58 |
59 | let transformScaleAnimation = CASpringAnimation()
60 |
61 | transformScaleAnimation.fillMode = CAMediaTimingFillMode.forwards
62 | transformScaleAnimation.duration = 0.99321
63 | transformScaleAnimation.isRemovedOnCompletion = false
64 | transformScaleAnimation.keyPath = "transform.scale"
65 | transformScaleAnimation.toValue = self.growFactor
66 | transformScaleAnimation.stiffness = 200
67 | transformScaleAnimation.damping = 10
68 | transformScaleAnimation.mass = 0.7
69 | transformScaleAnimation.initialVelocity = 4
70 |
71 | layer.add(transformScaleAnimation, forKey: "growAnimation")
72 | }
73 |
74 | // Thanks to Kite Compositor (kiteapp.co)
75 | override func mouseExited(with event: NSEvent) {
76 | guard self.growsOnHover, let layer = self.layer else { return }
77 |
78 | let transformScaleAnimation1 = CASpringAnimation()
79 |
80 | transformScaleAnimation1.duration = 0.99321
81 | transformScaleAnimation1.fillMode = CAMediaTimingFillMode.forwards
82 | transformScaleAnimation1.isRemovedOnCompletion = false
83 | transformScaleAnimation1.keyPath = "transform.scale"
84 | transformScaleAnimation1.toValue = 1
85 | transformScaleAnimation1.stiffness = 200
86 | transformScaleAnimation1.damping = 10
87 | transformScaleAnimation1.mass = 0.7
88 | transformScaleAnimation1.initialVelocity = 4
89 |
90 | layer.add(transformScaleAnimation1, forKey: "shrinkAnimation")
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/Fluor/Views/RuleCellView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RuleCellView.swift
3 | //
4 | // Fluor
5 | //
6 | // MIT License
7 | //
8 | // Copyright (c) 2020 Pierre Tacchi
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining a copy
11 | // of this software and associated documentation files (the "Software"), to deal
12 | // in the Software without restriction, including without limitation the rights
13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | // copies of the Software, and to permit persons to whom the Software is
15 | // furnished to do so, subject to the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be included in all
18 | // copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | // SOFTWARE.
27 | //
28 |
29 |
30 | import Cocoa
31 |
32 | class RuleCellView: NSTableCellView {
33 | override var backgroundStyle: NSView.BackgroundStyle {
34 | didSet {
35 | switch self.backgroundStyle {
36 | case .light:
37 | self.textField?.textColor = .textColor
38 | default:
39 | self.textField?.textColor = .selectedMenuItemTextColor
40 | }
41 | }
42 | }
43 |
44 | @IBAction func action(_ sender: Any?) {
45 | guard let item = objectValue as? Item else {
46 | return AppErrorManager.showError(withReason: "Can't set behavior")
47 | }
48 |
49 | AppManager.default.propagate(behavior: item.behavior, forApp: item.id, at: item.url, from: item.notificationSource)
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/Fluor/Views/SelectableBox.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SelectableBox.swift
3 | // Fluor
4 | //
5 | // Created by Pierre TACCHI on 24/02/2020.
6 | // Copyright © 2020 Pyrolyse. All rights reserved
7 | //
8 |
9 | import Cocoa
10 |
11 | class SelectableView: NSBox {
12 | private var isClicked: Bool = false {
13 | didSet { self.updateState() }
14 | }
15 |
16 | private var isHighlighted: Bool = false {
17 | didSet { self.updateState() }
18 | }
19 |
20 | private var highlightedColor: NSColor {
21 | .controlColor
22 | }
23 |
24 | private var clickedColor: NSColor {
25 | .selectedControlColor
26 | }
27 |
28 | override var mouseDownCanMoveWindow: Bool { false }
29 |
30 | override func updateTrackingAreas() {
31 | self.trackingAreas.forEach(self.removeTrackingArea(_:))
32 | self.addTrackingArea(.init(rect: self.bounds, options: [.activeAlways, .mouseEnteredAndExited, .enabledDuringMouseDrag], owner: self, userInfo: nil))
33 | }
34 |
35 | override func mouseEntered(with event: NSEvent) {
36 | super.mouseEntered(with: event)
37 | guard NSEvent.pressedMouseButtons == 0 || self.isClicked else { return }
38 | self.isHighlighted = true
39 | }
40 |
41 | override func mouseExited(with event: NSEvent) {
42 | super.mouseExited(with: event)
43 | self.isHighlighted = false
44 | }
45 |
46 | override func mouseDown(with event: NSEvent) {
47 | self.isClicked = true
48 | }
49 |
50 | override func mouseUp(with event: NSEvent) {
51 | self.isClicked = false
52 | if self.isHighlighted {
53 |
54 | }
55 | }
56 |
57 | private func updateState() {
58 | switch (self.isHighlighted, self.isClicked) {
59 | case (false, true):
60 | self.fillColor = .clear
61 | case (_, true):
62 | self.fillColor = self.clickedColor
63 | case (true, _):
64 | if self.fillColor == self.clickedColor {
65 | self.fillColor = self.highlightedColor
66 | } else {
67 | self.animator().fillColor = self.highlightedColor
68 | }
69 | default:
70 | if self.fillColor == self.highlightedColor {
71 | self.animator().fillColor = .clear
72 | } else {
73 | self.fillColor = .clear
74 | }
75 | }
76 | }
77 |
78 | private func handleClick() {
79 |
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/Fluor/dsa_pub.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PUBLIC KEY-----
2 | MIIGRzCCBDkGByqGSM44BAEwggQsAoICAQCQx6TQEbKejJRlvpUbTXKHCZEHifHm
3 | dfJmi/abYBJcKNYpFWFvZdi94xswYt0RX9xzIrvseDPdcSJNGr4cvHCfBEdgRbk0
4 | PHmo80lGCtMi9EvVxlYvZqcN/k/O8YtgRv5YMLJzoVQqmIDRZYR+zgstUX+5dqZF
5 | OVoRBMnmg7P4tVTcFaCs6QXbyABAOQrM45EbEzDEgaC5CvGmw7uavKdt9FB5+CNx
6 | bud64mPcButwr127g4oZHx/x5E2N1xzd2myCEksVm6e2MNEOmzU6UcMcnv6kq/ib
7 | e8Xd4sI21YSBQQo0J0i0tBevCtoXo0vMQhxhauRZD53x8zFeZyXmMcO48qej3dfF
8 | /4LDqKekHy0rcZuBGOkFbIR5AojGZXIjxdYYLiFz86y1MIpEt4Agr3HslP9TdzJX
9 | Qg5tdIA+1Qi5kBA4581KaIt/xtEi6fV8UAtoRO16ILnp0yYyqKxw/XodqhPO3m1M
10 | NgAXNbKFncnZUDwVYjAx/Bb8HkfhaSfFb2ihS3MMQmZuRY7r4H1Utp4ZjWrGIimN
11 | xZbEDqAwYlcmEP82/ALC+R1Y92N9BxR1T5BjQP5OwyfgHO7kpKuFraxhBK57UFE/
12 | l1fHQhmQAbu6bPCLwP4Jr8TZYcLwNPg9VvZDt6ThxCkxhk2DGGPPzIc0Vknvfe3L
13 | epUWKV3qUbH5qQIhAJ7yDbYPljsZQ9Nfr8HTXTH+p+2j0eHF19p31rJJFmIZAoIC
14 | ABk3RNEz7+ttAMlkUNCQt9t6cORrNS1zUpkPOCFfVrctYn4U/eGDEzrxmvrTZeaU
15 | 9/X+DDd/7f2eMPnwGgailyXoU68g0yyuUyK9afIXmj6QfA0Tm6E+1hzUywmhNPMO
16 | A+hT3TVRES98tyDfLg2gRvmWQh7GAnW3edMpk9Q2gCl8Nn4AjRjs77hsM+d1OHUS
17 | N9ZFZoTT3MQJpjaSr0ei0ZOdf0LqTsEc54gofWSv85JUrWnEcJzVmc06ex5W/MTd
18 | ZxAjHtbhz/YVlG5fFP2JlifxaBlkRA6sqZbTykdQVso9T5uCiW1Dc8euWfz1QLdE
19 | rwldrOyMjr8/RVVobMlgTOcjWPKXrsrb8M1PgJ5Dxm292qFId63mIuLm9oRf1UX6
20 | aJVbcgm6qr9W7JMTEdEJxM2EnTDKafPNy1wng2d3qPyglaw0Nw3H2K7kckMXS7tq
21 | aRNMwQdS+apy0F+hHctklJDbYnAB+YIYQuQbaRjgS8/ih+KPPlW1JdmKyNbaejR+
22 | pOAOsPxIP6jzaWTlL/Q36OA3CpM3VSFzktCxyP1vlIZva4U0VRX1pFexPKf+VXBz
23 | c1V7Ap+BzmgHU2qkLwdtj9lq3hMUGBdceFjlQjb5a7eniUN5pFFDAXdE2B57ti0k
24 | QHBelNfpKlZFf1erzm6LjXjmcy5G9i7Tc7au1lSl0HbdA4ICBgACggIBAI993Nil
25 | aqchhltIobZz+KTaRuIT6lmVg0geIlpdFTIexVofveGMz6Ms+bFBTWIPyDtWNGXb
26 | i/fNBnPtjdwbAoXrdSAqL2Bq/+p3hfvqtlqaEVRTPLXUlr9mSto8efoExJGNoAAi
27 | D0J/0Je3bt9womWdlCejYAK0ilwCjAimOLiNZStDHkafuiC7g3avHz20GW8F3SNx
28 | mGIG9G8dS+aL0Tm32/SHSfaMjuTaE69Wl5RyzrDGe95g06eadEJseCQWYf5+sp4Q
29 | vzt0xTRxOQ92p0nhjmP56Y+3gWXdJFBHWFtapzeTkwCL7Ldzzf8eZW192v6a8ukd
30 | FXk5wwBmNYDoblYl6/0tA8siqBaCXI9WM4pPC4a7g1o/LzOM7Az/dRJVRtlN7nn4
31 | 9Yi83zhdKxz55L4VCCxubd3y85/pdsQNm9aSTuVT4y/6yzmm2z/h0PUFmPXUWoU1
32 | SweG+wDiAVG1Fzlv39hKvI+4E6VPhZujuwno6GQBHzwDHyzcn4W6TJeK8jC2FuJK
33 | fI7C5SSjPPprx1Px3ovfA5SDRannYsipFheVm3AFu4geswxr9p20S6rdDkjDln16
34 | t3B8j8wKNgk+E54XCp2yBpoSE4uuKWJ/ya/WHGwW0VW1eK/Po9RnBl/DYiYt5wBS
35 | lzW4UcgE8CEJr9dV2P5WUve3FHRz7Zf7qmiQ
36 | -----END PUBLIC KEY-----
37 |
--------------------------------------------------------------------------------
/Fluor/en.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/en.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Fluor/fr.lproj/About.strings:
--------------------------------------------------------------------------------
1 | /* Class = "NSButtonCell"; title = "Release notes"; ObjectID = "3LZ-kH-mRF"; */
2 | "3LZ-kH-mRF.title" = "Notes de version";
3 |
4 | /* Class = "NSTextFieldCell"; title = "Copyright (c) Pyrolyse 2016-2019"; ObjectID = "D9M-Xx-uVv"; */
5 | "D9M-Xx-uVv.title" = "Copyright (c) Pyrolyse 2016-2019";
6 |
7 | /* Class = "NSWindow"; title = "Window"; ObjectID = "Iyh-kg-rFF"; */
8 | "Iyh-kg-rFF.title" = "Window";
9 |
10 | /* Class = "NSButtonCell"; title = "Technical support"; ObjectID = "k51-I5-gTD"; */
11 | "k51-I5-gTD.title" = "Support technique";
12 |
13 | /* Class = "NSButton"; ibShadowedToolTip = "Pyrolyse Website"; ObjectID = "LAF-Vr-LJH"; */
14 | "LAF-Vr-LJH.ibShadowedToolTip" = "Site web Pyrolyse";
15 |
16 | /* Class = "NSTextFieldCell"; title = "Version"; ObjectID = "nBp-xh-w5r"; */
17 | "nBp-xh-w5r.title" = "Version";
18 |
19 | /* Class = "NSTextFieldCell"; title = "Fluor"; ObjectID = "Rb1-qw-yPI"; */
20 | "Rb1-qw-yPI.title" = "Fluor";
21 |
22 | /* Class = "NSButton"; ibShadowedToolTip = "Twitter Account"; ObjectID = "tcP-8l-Eun"; */
23 | "tcP-8l-Eun.ibShadowedToolTip" = "Compte Twitter";
24 |
25 | /* Class = "NSButton"; ibShadowedToolTip = "Fork me on GitHub"; ObjectID = "z33-BR-yuW"; */
26 | "z33-BR-yuW.ibShadowedToolTip" = "Fork me on GitHub";
27 |
28 |
--------------------------------------------------------------------------------
/Fluor/fr.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 | /* No comment provided by engineer. */
2 | "Default mode changed" = "Modification du mode par défaut";
3 |
4 | /* No comment provided by engineer. */
5 | "Don't ask me on startup again" = "Ne pas me demander au démarrage de l'application";
6 |
7 | /* No comment provided by engineer. */
8 | "Don't enable notifications" = "Ne pas activer les notifications";
9 |
10 | /* No comment provided by engineer. */
11 | "Enable notfications" = "Activer les notifications";
12 |
13 | /* No comment provided by engineer. */
14 | "Enable notifications ?" = "Voulez-vous recevoir des notifications ?";
15 |
16 | /* No comment provided by engineer. */
17 | "F-Keys mode changed" = "Le mode des touches F a changé";
18 |
19 | /* No comment provided by engineer. */
20 | "F-Keys mode changed for %@" = "Le mode des touches F a changé pour %@";
21 |
22 | /* No comment provided by engineer. */
23 | "Fluor can send notifications when the F-Keys mode change." = "Fluor peut envoyer des notifications quand le mode des touches F est modifié";
24 |
25 | /* No comment provided by engineer. */
26 | "Function keys" = "Touches de fonction";
27 |
28 | /* No comment provided by engineer. */
29 | "I allowed it" = "Je l'ai autorisé";
30 |
31 | /* No comment provided by engineer. */
32 | "I won't allow it" = "Je ne l'autoriserai pas";
33 |
34 | /* No comment provided by engineer. */
35 | "Media keys" = "Touches média";
36 |
37 | /* No comment provided by engineer. */
38 | "Notifications are not allowed from Fluor" = "Fluor n'est pas autorisé à envoyer des notifications";
39 |
40 | /* No comment provided by engineer. */
41 | "Same as default" = "Identique au mode par défaut";
42 |
43 | /* No comment provided by engineer. */
44 | "Sorry, an unexpected error occured." = "Désolé une erreur inattendue est survenue";
45 |
46 | /* No comment provided by engineer. */
47 | "version %@" = "version %@";
48 |
49 |
--------------------------------------------------------------------------------
/Fluor/fr.lproj/MainMenu.strings:
--------------------------------------------------------------------------------
1 | /* Class = "NSSegmentedCell"; 1I5-bW-HGh.ibShadowedToolTips[0] = "Same as default mode"; ObjectID = "1I5-bW-HGh"; */
2 | "1I5-bW-HGh.ibShadowedToolTips[0]" = "Identique au mode par défaut";
3 |
4 | /* Class = "NSSegmentedCell"; 1I5-bW-HGh.ibShadowedToolTips[1] = "Media keys mode"; ObjectID = "1I5-bW-HGh"; */
5 | "1I5-bW-HGh.ibShadowedToolTips[1]" = "Choisir sur les touches Apple";
6 |
7 | /* Class = "NSSegmentedCell"; 1I5-bW-HGh.ibShadowedToolTips[2] = "Function keys mode"; ObjectID = "1I5-bW-HGh"; */
8 | "1I5-bW-HGh.ibShadowedToolTips[2]" = "Choisir sur les touches de function";
9 |
10 | /* Class = "NSTextFieldCell"; title = "Trigger"; ObjectID = "AiN-Qo-Ikx"; */
11 | "AiN-Qo-Ikx.title" = "Déclencheur";
12 |
13 | /* Class = "NSMenuItem"; title = "Running applications..."; ObjectID = "Ark-Du-XrQ"; */
14 | "Ark-Du-XrQ.title" = "Applications en cours...";
15 |
16 | /* Class = "NSMenuItem"; title = "Disabled"; ObjectID = "DqN-qz-yQz"; */
17 | "DqN-qz-yQz.title" = "Désactivé";
18 |
19 | /* Class = "NSMenuItem"; title = "Start Fluor at login"; ObjectID = "eWy-d7-62P"; */
20 | "eWy-d7-62P.title" = "Lancer Fluor au démarrage";
21 |
22 | /* Class = "NSButtonCell"; title = "Ask permission"; ObjectID = "gP8-wU-Xyk"; */
23 | "gP8-wU-Xyk.title" = "Gérer permission";
24 |
25 | /* Class = "NSMenuItem"; title = "Switch method"; ObjectID = "hM4-Z2-ndk"; */
26 | "hM4-Z2-ndk.title" = "Switch method";
27 |
28 | /* Class = "NSMenuItem"; title = "About Fluor"; ObjectID = "Ib7-Rw-HnK"; */
29 | "Ib7-Rw-HnK.title" = "À propos de Fluor";
30 |
31 | /* Class = "NSMenuItem"; title = "Manage rules..."; ObjectID = "MHf-OK-jHk"; */
32 | "MHf-OK-jHk.title" = "Gérer les règles...";
33 |
34 | /* Class = "NSTextFieldCell"; title = "Label"; ObjectID = "nND-dO-QEg"; */
35 | "nND-dO-QEg.title" = "Label";
36 |
37 | /* Class = "NSMenuItem"; title = "Default mode"; ObjectID = "PtY-YF-jEr"; */
38 | "PtY-YF-jEr.title" = "Mode par défaut";
39 |
40 | /* Class = "NSMenuItem"; title = "Quit"; ObjectID = "QjA-WT-wFW"; */
41 | "QjA-WT-wFW.title" = "Quitter";
42 |
43 | /* Class = "NSSegmentedCell"; qZf-Wa-JJt.ibShadowedToolTips[0] = "Change mode with the active application"; ObjectID = "qZf-Wa-JJt"; */
44 | "qZf-Wa-JJt.ibShadowedToolTips[0]" = "Bascule le mode en fonction de l'application active";
45 |
46 | /* Class = "NSSegmentedCell"; qZf-Wa-JJt.ibShadowedToolTips[1] = "Set mode for the active application when the fn key is pressed"; ObjectID = "qZf-Wa-JJt"; */
47 | "qZf-Wa-JJt.ibShadowedToolTips[1]" = "Bascule le mode quand la touche Fn est pressée";
48 |
49 | /* Class = "NSSegmentedCell"; qZf-Wa-JJt.ibShadowedToolTips[2] = "Set the default mode when the fn key is pressed"; ObjectID = "qZf-Wa-JJt"; */
50 | "qZf-Wa-JJt.ibShadowedToolTips[2]" = "Modifie le mode par défaut lors d'un appui sur le touche fn";
51 |
52 | /* Class = "NSTextFieldCell"; title = "Default mode"; ObjectID = "S28-Jt-nN1"; */
53 | "S28-Jt-nN1.title" = "Mode par défaut";
54 |
55 | /* Class = "NSMenuItem"; title = "Preferences..."; ObjectID = "sjb-Ql-h6c"; */
56 | "sjb-Ql-h6c.title" = "Préférences...";
57 |
58 | /* Class = "NSMenuItem"; title = "Current application"; ObjectID = "ulH-vE-QEF"; */
59 | "ulH-vE-QEF.title" = "Application active";
60 |
61 | /* Class = "NSSegmentedCell"; Vfh-zJ-Axi.ibShadowedToolTips[0] = "Media keys mode"; ObjectID = "Vfh-zJ-Axi"; */
62 | "Vfh-zJ-Axi.ibShadowedToolTips[0]" = "Switch to Apple mode";
63 |
64 | /* Class = "NSSegmentedCell"; Vfh-zJ-Axi.ibShadowedToolTips[1] = "Function keys mode"; ObjectID = "Vfh-zJ-Axi"; */
65 | "Vfh-zJ-Axi.ibShadowedToolTips[1]" = "Switch to function key mode";
66 |
67 |
--------------------------------------------------------------------------------
/Fluor/fr.lproj/RulesEditor.strings:
--------------------------------------------------------------------------------
1 | /* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "3Tm-fC-RsQ"; */
2 | "3Tm-fC-RsQ.title" = "Text Cell";
3 |
4 | /* Class = "NSTextFieldCell"; title = "Label"; ObjectID = "Bp2-iW-iXC"; */
5 | "Bp2-iW-iXC.title" = "Label";
6 |
7 | /* Class = "CocoaBindingsConnection"; ibShadowedDisplayPattern = "%{value1}@ rules"; ObjectID = "Ddg-CJ-Ktm"; */
8 | "Ddg-CJ-Ktm.ibShadowedDisplayPattern" = "%{value1}@ règles";
9 |
10 | /* Class = "NSWindow"; title = "Rules"; ObjectID = "eXk-yp-Np1"; */
11 | "eXk-yp-Np1.title" = "Règles";
12 |
13 | /* Class = "NSToolbarItem"; paletteLabel = "Search"; ObjectID = "Fxg-EK-kQD"; */
14 | "Fxg-EK-kQD.paletteLabel" = "Rechercher";
15 |
16 | /* Class = "NSSegmentedCell"; qsY-JB-wQQ.ibShadowedToolTips[0] = "Add rule"; ObjectID = "qsY-JB-wQQ"; */
17 | "qsY-JB-wQQ.ibShadowedToolTips[0]" = "Ajouter une règle";
18 |
19 | /* Class = "NSSegmentedCell"; qsY-JB-wQQ.ibShadowedToolTips[1] = "Delete selected rule"; ObjectID = "qsY-JB-wQQ"; */
20 | "qsY-JB-wQQ.ibShadowedToolTips[1]" = "Supprimer la règle selectionnée";
21 |
22 | /* Class = "NSSegmentedCell"; Xfv-1b-Hu4.ibShadowedToolTips[0] = "Media keys mode"; ObjectID = "Xfv-1b-Hu4"; */
23 | "Xfv-1b-Hu4.ibShadowedToolTips[0]" = "Touches Apple";
24 |
25 | /* Class = "NSSegmentedCell"; Xfv-1b-Hu4.ibShadowedToolTips[1] = "Function keys mode"; ObjectID = "Xfv-1b-Hu4"; */
26 | "Xfv-1b-Hu4.ibShadowedToolTips[1]" = "Touches de fonction";
27 |
28 | /* Class = "NSTextFieldCell"; title = "Label"; ObjectID = "Y1u-Fa-sgm"; */
29 | "Y1u-Fa-sgm.title" = "Label";
30 |
31 |
--------------------------------------------------------------------------------
/Fluor/fr.lproj/RunningApps.strings:
--------------------------------------------------------------------------------
1 | /* Class = "CocoaBindingsConnection"; ibShadowedDisplayPattern = "%{value1}@ running"; ObjectID = "8nZ-Ag-ymF"; */
2 | "8nZ-Ag-ymF.ibShadowedDisplayPattern" = "%{value1}@ en cours d'exécution";
3 |
4 | /* Class = "NSTextFieldCell"; title = "Label"; ObjectID = "b56-33-3LM"; */
5 | "b56-33-3LM.title" = "Label";
6 |
7 | /* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "bZs-z5-c1g"; */
8 | "bZs-z5-c1g.title" = "Text Cell";
9 |
10 | /* Class = "NSSegmentedCell"; q73-3D-poM.ibShadowedToolTips[0] = "Same as default"; ObjectID = "q73-3D-poM"; */
11 | "q73-3D-poM.ibShadowedToolTips[0]" = "Par défaut";
12 |
13 | /* Class = "NSSegmentedCell"; q73-3D-poM.ibShadowedToolTips[1] = "Media keys mode"; ObjectID = "q73-3D-poM"; */
14 | "q73-3D-poM.ibShadowedToolTips[1]" = "Touches Apple";
15 |
16 | /* Class = "NSSegmentedCell"; q73-3D-poM.ibShadowedToolTips[2] = "Function keys mode"; ObjectID = "q73-3D-poM"; */
17 | "q73-3D-poM.ibShadowedToolTips[2]" = "Touches de fonction";
18 |
19 | /* Class = "NSTextFieldCell"; title = "Label"; ObjectID = "Twm-uj-Z9c"; */
20 | "Twm-uj-Z9c.title" = "Label";
21 |
22 | /* Class = "NSToolbarItem"; label = "Search"; ObjectID = "u25-IX-3ln"; */
23 | "u25-IX-3ln.label" = "Rechercher";
24 |
25 | /* Class = "NSToolbarItem"; paletteLabel = "Search"; ObjectID = "u25-IX-3ln"; */
26 | "u25-IX-3ln.paletteLabel" = "Rechercher";
27 |
28 | /* Class = "NSWindow"; title = "Running Applications"; ObjectID = "Vdh-R9-Luc"; */
29 | "Vdh-R9-Luc.title" = "Applications en cours";
30 |
31 | /* Class = "NSButtonCell"; alternateTitle = "Hide services"; ObjectID = "Yb5-hU-zbp"; */
32 | "Yb5-hU-zbp.alternateTitle" = "Cacher les services";
33 |
34 | /* Class = "NSButtonCell"; title = "Show all"; ObjectID = "Yb5-hU-zbp"; */
35 | "Yb5-hU-zbp.title" = "Montrer tout";
36 |
37 |
--------------------------------------------------------------------------------
/Fluor/zh-Hans.lproj/About.strings:
--------------------------------------------------------------------------------
1 |
2 | /* Class = "NSButtonCell"; title = "Release notes"; ObjectID = "3LZ-kH-mRF"; */
3 | "3LZ-kH-mRF.title" = "发行说明";
4 |
5 | /* Class = "NSTextFieldCell"; title = "Copyright (c) Pyrolyse 2016-2019"; ObjectID = "D9M-Xx-uVv"; */
6 | "D9M-Xx-uVv.title" = "版权所有 (c) Pyrolyse 2016-2019";
7 |
8 | /* Class = "NSButtonCell"; title = "Update"; ObjectID = "DN8-JH-bOp"; */
9 | "DN8-JH-bOp.title" = "更新";
10 |
11 | /* Class = "NSToolbarItem"; label = "Custom View"; ObjectID = "F1c-dv-XMN"; */
12 | "F1c-dv-XMN.label" = "Custom View";
13 |
14 | /* Class = "NSToolbarItem"; paletteLabel = "Custom View"; ObjectID = "F1c-dv-XMN"; */
15 | "F1c-dv-XMN.paletteLabel" = "Custom View";
16 |
17 | /* Class = "NSWindow"; title = "Window"; ObjectID = "Iyh-kg-rFF"; */
18 | "Iyh-kg-rFF.title" = "Window";
19 |
20 | /* Class = "NSButton"; ibShadowedToolTip = "Pyrolyse Website"; ObjectID = "LAF-Vr-LJH"; */
21 | "LAF-Vr-LJH.ibShadowedToolTip" = "Pyrolyse 网站";
22 |
23 | /* Class = "NSTextFieldCell"; title = "Fluor"; ObjectID = "Rb1-qw-yPI"; */
24 | "Rb1-qw-yPI.title" = "Fluor";
25 |
26 | /* Class = "NSWindow"; title = "Window"; ObjectID = "Xar-Fu-9dh"; */
27 | "Xar-Fu-9dh.title" = "Window";
28 |
29 | /* Class = "NSToolbarItem"; label = "Custom View"; ObjectID = "c5J-iu-x6L"; */
30 | "c5J-iu-x6L.label" = "Custom View";
31 |
32 | /* Class = "NSToolbarItem"; paletteLabel = "Custom View"; ObjectID = "c5J-iu-x6L"; */
33 | "c5J-iu-x6L.paletteLabel" = "Custom View";
34 |
35 | /* Class = "NSButtonCell"; title = "Technical support"; ObjectID = "k51-I5-gTD"; */
36 | "k51-I5-gTD.title" = "技术支持";
37 |
38 | /* Class = "NSTextFieldCell"; title = "Version"; ObjectID = "nBp-xh-w5r"; */
39 | "nBp-xh-w5r.title" = "版本";
40 |
41 | /* Class = "NSButton"; ibShadowedToolTip = "Twitter Account"; ObjectID = "tcP-8l-Eun"; */
42 | "tcP-8l-Eun.ibShadowedToolTip" = "Twitter 帐号";
43 |
44 | /* Class = "NSButton"; ibShadowedToolTip = "Fork me on GitHub"; ObjectID = "z33-BR-yuW"; */
45 | "z33-BR-yuW.ibShadowedToolTip" = "Fork me on GitHub";
46 |
--------------------------------------------------------------------------------
/Fluor/zh-Hans.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/Fluor/zh-Hans.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Fluor/zh-Hans.lproj/MainMenu.strings:
--------------------------------------------------------------------------------
1 |
2 | /* Class = "NSSegmentedCell"; 1I5-bW-HGh.ibShadowedToolTips[0] = "Same as default mode"; ObjectID = "1I5-bW-HGh"; */
3 | "1I5-bW-HGh.ibShadowedToolTips[0]" = "与默认模式相同";
4 |
5 | /* Class = "NSSegmentedCell"; 1I5-bW-HGh.ibShadowedToolTips[1] = "Media keys mode"; ObjectID = "1I5-bW-HGh"; */
6 | "1I5-bW-HGh.ibShadowedToolTips[1]" = "媒体键模式";
7 |
8 | /* Class = "NSSegmentedCell"; 1I5-bW-HGh.ibShadowedToolTips[2] = "Function keys mode"; ObjectID = "1I5-bW-HGh"; */
9 | "1I5-bW-HGh.ibShadowedToolTips[2]" = "功能键模式";
10 |
11 | /* Class = "NSTextFieldCell"; title = "Trigger"; ObjectID = "AiN-Qo-Ikx"; */
12 | "AiN-Qo-Ikx.title" = "切换方式";
13 |
14 | /* Class = "NSMenuItem"; title = "Running applications..."; ObjectID = "Ark-Du-XrQ"; */
15 | "Ark-Du-XrQ.title" = "运行中的应用...";
16 |
17 | /* Class = "NSMenuItem"; title = "Disabled"; ObjectID = "DqN-qz-yQz"; */
18 | "DqN-qz-yQz.title" = "禁用";
19 |
20 | /* Class = "NSMenuItem"; title = "About Fluor"; ObjectID = "Ib7-Rw-HnK"; */
21 | "Ib7-Rw-HnK.title" = "关于 Fluor";
22 |
23 | /* Class = "NSMenuItem"; title = "Manage rules..."; ObjectID = "MHf-OK-jHk"; */
24 | "MHf-OK-jHk.title" = "规则...";
25 |
26 | /* Class = "NSMenuItem"; title = "Default mode"; ObjectID = "PtY-YF-jEr"; */
27 | "PtY-YF-jEr.title" = "默认模式";
28 |
29 | /* Class = "NSMenuItem"; title = "sep2"; ObjectID = "QCJ-IJ-MMQ"; */
30 | "QCJ-IJ-MMQ.title" = "sep2";
31 |
32 | /* Class = "NSMenuItem"; title = "Quit"; ObjectID = "QjA-WT-wFW"; */
33 | "QjA-WT-wFW.title" = "退出";
34 |
35 | /* Class = "NSTextFieldCell"; title = "Default mode"; ObjectID = "S28-Jt-nN1"; */
36 | "S28-Jt-nN1.title" = "默认模式";
37 |
38 | /* Class = "NSSegmentedCell"; Vfh-zJ-Axi.ibShadowedToolTips[0] = "Media keys mode"; ObjectID = "Vfh-zJ-Axi"; */
39 | "Vfh-zJ-Axi.ibShadowedToolTips[0]" = "媒体键模式";
40 |
41 | /* Class = "NSSegmentedCell"; Vfh-zJ-Axi.ibShadowedToolTips[1] = "Function keys mode"; ObjectID = "Vfh-zJ-Axi"; */
42 | "Vfh-zJ-Axi.ibShadowedToolTips[1]" = "功能键模式";
43 |
44 | /* Class = "NSMenuItem"; title = "Start Fluor at login"; ObjectID = "eWy-d7-62P"; */
45 | "eWy-d7-62P.title" = "自动启动";
46 |
47 | /* Class = "NSButtonCell"; title = "Ask permission"; ObjectID = "gP8-wU-Xyk"; */
48 | "gP8-wU-Xyk.title" = "请求权限";
49 |
50 | /* Class = "NSMenuItem"; title = "Switch method"; ObjectID = "hM4-Z2-ndk"; */
51 | "hM4-Z2-ndk.title" = "Switch method";
52 |
53 | /* Class = "NSTextFieldCell"; title = "Label"; ObjectID = "nND-dO-QEg"; */
54 | "nND-dO-QEg.title" = "Label";
55 |
56 | /* Class = "NSSegmentedCell"; qZf-Wa-JJt.ibShadowedToolTips[0] = "Change mode with the active application"; ObjectID = "qZf-Wa-JJt"; */
57 | "qZf-Wa-JJt.ibShadowedToolTips[0]" = "随活动的应用自动切换模式";
58 |
59 | /* Class = "NSSegmentedCell"; qZf-Wa-JJt.ibShadowedToolTips[1] = "Set mode for the active application when the fn key is pressed"; ObjectID = "qZf-Wa-JJt"; */
60 | "qZf-Wa-JJt.ibShadowedToolTips[1]" = "通过按 fn 键为活动的应用切换模式";
61 |
62 | /* Class = "NSSegmentedCell"; qZf-Wa-JJt.ibShadowedToolTips[2] = "Set the default mode when the fn key is pressed"; ObjectID = "qZf-Wa-JJt"; */
63 | "qZf-Wa-JJt.ibShadowedToolTips[2]" = "通过按 fn 键切换默认模式";
64 |
65 | /* Class = "NSMenuItem"; title = "sep1"; ObjectID = "qvx-bn-WPk"; */
66 | "qvx-bn-WPk.title" = "sep1";
67 |
68 | /* Class = "NSMenuItem"; title = "Preferences..."; ObjectID = "sjb-Ql-h6c"; */
69 | "sjb-Ql-h6c.title" = "偏好设置...";
70 |
71 | /* Class = "NSMenuItem"; title = "Current application"; ObjectID = "ulH-vE-QEF"; */
72 | "ulH-vE-QEF.title" = "当前应用";
73 |
--------------------------------------------------------------------------------
/Fluor/zh-Hans.lproj/Preferences.strings:
--------------------------------------------------------------------------------
1 |
2 | /* Class = "NSTextFieldCell"; title = "When do you want notifications to be sent ?"; ObjectID = "0PF-9f-i6n"; */
3 | "0PF-9f-i6n.title" = "您希望何时收到通知?";
4 |
5 | /* Class = "NSTabViewItem"; label = "Advanced"; ObjectID = "18q-Zg-Tl1"; */
6 | "18q-Zg-Tl1.label" = "高级";
7 |
8 | /* Class = "NSTextFieldCell"; title = "3."; ObjectID = "Cvg-Yl-ZC5"; */
9 | "Cvg-Yl-ZC5.title" = "3.";
10 |
11 | /* Class = "NSTextFieldCell"; title = "Default mode on launch"; ObjectID = "F4H-9X-Gkc"; */
12 | "F4H-9X-Gkc.title" = "启动时的默认模式";
13 |
14 | /* Class = "NSTabViewItem"; label = "General"; ObjectID = "Hob-Dv-Dm7"; */
15 | "Hob-Dv-Dm7.label" = "一般";
16 |
17 | /* Class = "NSTextFieldCell"; title = "Find and select Fluor in the list"; ObjectID = "IKU-zN-gyv"; */
18 | "IKU-zN-gyv.title" = "Find and select Fluor in the list";
19 |
20 | /* Class = "NSSegmentedCell"; J3t-x7-5C6.ibShadowedToolTips[0] = "Media keys mode"; ObjectID = "J3t-x7-5C6"; */
21 | "J3t-x7-5C6.ibShadowedToolTips[0]" = "媒体键模式";
22 |
23 | /* Class = "NSSegmentedCell"; J3t-x7-5C6.ibShadowedToolTips[1] = "Function keys mode"; ObjectID = "J3t-x7-5C6"; */
24 | "J3t-x7-5C6.ibShadowedToolTips[1]" = "功能键模式";
25 |
26 | /* Class = "NSTextFieldCell"; title = "Send notification "; ObjectID = "Jmi-kR-PLT"; */
27 | "Jmi-kR-PLT.title" = "发送通知 ";
28 |
29 | /* Class = "NSWindow"; title = "Preferences"; ObjectID = "N9r-FQ-Oq3"; */
30 | "N9r-FQ-Oq3.title" = "偏好设置";
31 |
32 | /* Class = "NSButtonCell"; title = "Automaticaly download updates"; ObjectID = "RZl-MW-RaS"; */
33 | "RZl-MW-RaS.title" = "自动下载更新";
34 |
35 | /* Class = "NSTextFieldCell"; title = "Last Checked:"; ObjectID = "TZA-yl-nGe"; */
36 | "TZA-yl-nGe.title" = "最后检查时间:";
37 |
38 | /* Class = "NSViewController"; title = "Advanced"; ObjectID = "UoT-kw-xfb"; */
39 | "UoT-kw-xfb.title" = "高级";
40 |
41 | /* Class = "NSButtonCell"; title = "Check now"; ObjectID = "Vtq-y9-sm5"; */
42 | "Vtq-y9-sm5.title" = "立即检查";
43 |
44 | /* Class = "NSSegmentedCell"; aHs-kY-jFz.ibShadowedToolTips[0] = "Media keys mode"; ObjectID = "aHs-kY-jFz"; */
45 | "aHs-kY-jFz.ibShadowedToolTips[0]" = "媒体键模式";
46 |
47 | /* Class = "NSSegmentedCell"; aHs-kY-jFz.ibShadowedToolTips[1] = "Function keys mode"; ObjectID = "aHs-kY-jFz"; */
48 | "aHs-kY-jFz.ibShadowedToolTips[1]" = "功能键模式";
49 |
50 | /* Class = "NSViewController"; title = "General"; ObjectID = "bdY-l4-Nw7"; */
51 | "bdY-l4-Nw7.title" = "一般";
52 |
53 | /* Class = "NSButtonCell"; title = "Restore startup mode"; ObjectID = "cXi-qe-jsD"; */
54 | "cXi-qe-jsD.title" = "恢复启动时的模式";
55 |
56 | /* Class = "NSButtonCell"; title = "Open Notifications preference pane"; ObjectID = "caw-E4-tuY"; */
57 | "caw-E4-tuY.title" = "打开通知偏好设置";
58 |
59 | /* Class = "NSTabViewItem"; label = "Updates"; ObjectID = "dHq-vD-kde"; */
60 | "dHq-vD-kde.label" = "更新";
61 |
62 | /* Class = "NSViewController"; title = "Updates"; ObjectID = "dlC-Ac-YKV"; */
63 | "dlC-Ac-YKV.title" = "更新";
64 |
65 | /* Class = "NSTextFieldCell"; title = "When the current application mode is set by pressing the fn key"; ObjectID = "ezd-7Z-VvY"; */
66 | "ezd-7Z-VvY.title" = "当按 fn 键切换当前应用模式时";
67 |
68 | /* Class = "NSTextFieldCell"; title = "When the global mode is set by pressing the fn key"; ObjectID = "fT0-a8-Fn0"; */
69 | "fT0-a8-Fn0.title" = "当按 fn 键切换全局模式时";
70 |
71 | /* Class = "NSTabViewController"; title = "Preferences"; ObjectID = "glG-bk-x2Q"; */
72 | "glG-bk-x2Q.title" = "偏好设置";
73 |
74 | /* Class = "NSTabViewItem"; label = "Notifications"; ObjectID = "hM9-Ia-nxv"; */
75 | "hM9-Ia-nxv.label" = "通知";
76 |
77 | /* Class = "NSButtonCell"; title = "Everytime"; ObjectID = "hgm-4a-jDl"; */
78 | "hgm-4a-jDl.title" = "全部通知";
79 |
80 | /* Class = "NSTextFieldCell"; title = "Activate the Allow Notification from Fluor switch"; ObjectID = "hv4-f4-B7v"; */
81 | "hv4-f4-B7v.title" = "Activate the Allow Notification from Fluor switch";
82 |
83 | /* Class = "NSButtonCell"; title = "Use light menu icon"; ObjectID = "j3E-2l-1wC"; */
84 | "j3E-2l-1wC.title" = "使用浅色菜单栏图标";
85 |
86 | /* Class = "CocoaBindingsConnection"; ibShadowedIsNilPlaceholder = "280ms"; ObjectID = "kjd-tC-eHL"; */
87 | "kjd-tC-eHL.ibShadowedIsNilPlaceholder" = "280ms";
88 |
89 | /* Class = "NSButtonCell"; title = "Start Fluor at login"; ObjectID = "kkr-ac-7zW"; */
90 | "kkr-ac-7zW.title" = "登陆时启动 Fluor";
91 |
92 | /* Class = "NSTextFieldCell"; title = "2."; ObjectID = "lXR-Ye-zzj"; */
93 | "lXR-Ye-zzj.title" = "2.";
94 |
95 | /* Class = "NSTextFieldCell"; title = "1."; ObjectID = "mjv-jW-mRK"; */
96 | "mjv-jW-mRK.title" = "1.";
97 |
98 | /* Class = "NSButtonCell"; title = "Reset mode on quit"; ObjectID = "o0g-Zi-PDV"; */
99 | "o0g-Zi-PDV.title" = "退出时将模式重置为";
100 |
101 | /* Class = "NSButtonCell"; title = "Always show all running processes"; ObjectID = "oGT-JF-Yp4"; */
102 | "oGT-JF-Yp4.title" = "总是显示所有正在运行的进程";
103 |
104 | /* Class = "NSButtonCell"; title = "Hide the trigger method selection section"; ObjectID = "qxq-5O-b7c"; */
105 | "qxq-5O-b7c.title" = "隐藏菜单中的切换方式";
106 |
107 | /* Class = "NSTextFieldCell"; title = "Fn key release maximum delay:"; ObjectID = "sJJ-c6-Cuv"; */
108 | "sJJ-c6-Cuv.title" = "Fn 键释放最大延迟:";
109 |
110 | /* Class = "NSTextFieldCell"; title = "Yesterday at 16:28"; ObjectID = "tQx-sm-17A"; */
111 | "tQx-sm-17A.title" = "昨天 16:28";
112 |
113 | /* Class = "NSTextFieldCell"; title = "When the mode changes with the active application"; ObjectID = "tcj-WZ-834"; */
114 | "tcj-WZ-834.title" = "当模式随活动应用程序而改变时";
115 |
116 | /* Class = "NSButtonCell"; title = "Automaticaly check for updates"; ObjectID = "xgt-53-WGT"; */
117 | "xgt-53-WGT.title" = "自动检查更新";
118 |
--------------------------------------------------------------------------------
/Fluor/zh-Hans.lproj/RulesEditor.strings:
--------------------------------------------------------------------------------
1 |
2 | /* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "3Tm-fC-RsQ"; */
3 | "3Tm-fC-RsQ.title" = "Text Cell";
4 |
5 | /* Class = "NSTextFieldCell"; title = "Label"; ObjectID = "Bp2-iW-iXC"; */
6 | "Bp2-iW-iXC.title" = "Label";
7 |
8 | /* Class = "CocoaBindingsConnection"; ibShadowedDisplayPattern = "%{value1}@ rules"; ObjectID = "Ddg-CJ-Ktm"; */
9 | "Ddg-CJ-Ktm.ibShadowedDisplayPattern" = "规则数量: %{value1}@";
10 |
11 | /* Class = "NSToolbarItem"; paletteLabel = "Search"; ObjectID = "Fxg-EK-kQD"; */
12 | "Fxg-EK-kQD.paletteLabel" = "搜索";
13 |
14 | /* Class = "NSSegmentedCell"; Xfv-1b-Hu4.ibShadowedToolTips[0] = "Media keys mode"; ObjectID = "Xfv-1b-Hu4"; */
15 | "Xfv-1b-Hu4.ibShadowedToolTips[0]" = "媒体键模式";
16 |
17 | /* Class = "NSSegmentedCell"; Xfv-1b-Hu4.ibShadowedToolTips[1] = "Function keys mode"; ObjectID = "Xfv-1b-Hu4"; */
18 | "Xfv-1b-Hu4.ibShadowedToolTips[1]" = "功能键模式";
19 |
20 | /* Class = "NSTextFieldCell"; title = "Label"; ObjectID = "Y1u-Fa-sgm"; */
21 | "Y1u-Fa-sgm.title" = "Label";
22 |
23 | /* Class = "NSWindow"; title = "Rules"; ObjectID = "eXk-yp-Np1"; */
24 | "eXk-yp-Np1.title" = "规则";
25 |
26 | /* Class = "NSSegmentedCell"; qsY-JB-wQQ.ibShadowedToolTips[0] = "Add rule"; ObjectID = "qsY-JB-wQQ"; */
27 | "qsY-JB-wQQ.ibShadowedToolTips[0]" = "添加规则";
28 |
29 | /* Class = "NSSegmentedCell"; qsY-JB-wQQ.ibShadowedToolTips[1] = "Delete selected rule"; ObjectID = "qsY-JB-wQQ"; */
30 | "qsY-JB-wQQ.ibShadowedToolTips[1]" = "删除选中规则";
31 |
--------------------------------------------------------------------------------
/Fluor/zh-Hans.lproj/RunningApps.strings:
--------------------------------------------------------------------------------
1 |
2 | /* Class = "CocoaBindingsConnection"; ibShadowedDisplayPattern = "%{value1}@ running"; ObjectID = "8nZ-Ag-ymF"; */
3 | "8nZ-Ag-ymF.ibShadowedDisplayPattern" = "运行中数量: %{value1}@";
4 |
5 | /* Class = "NSTextFieldCell"; title = "Label"; ObjectID = "Twm-uj-Z9c"; */
6 | "Twm-uj-Z9c.title" = "Label";
7 |
8 | /* Class = "NSWindow"; title = "Running Applications"; ObjectID = "Vdh-R9-Luc"; */
9 | "Vdh-R9-Luc.title" = "运行中的应用";
10 |
11 | /* Class = "NSButtonCell"; alternateTitle = "Hide services"; ObjectID = "Yb5-hU-zbp"; */
12 | "Yb5-hU-zbp.alternateTitle" = "隐藏服务";
13 |
14 | /* Class = "NSButtonCell"; title = "Show all"; ObjectID = "Yb5-hU-zbp"; */
15 | "Yb5-hU-zbp.title" = "显示全部";
16 |
17 | /* Class = "NSTextFieldCell"; title = "Label"; ObjectID = "b56-33-3LM"; */
18 | "b56-33-3LM.title" = "Label";
19 |
20 | /* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "bZs-z5-c1g"; */
21 | "bZs-z5-c1g.title" = "Text Cell";
22 |
23 | /* Class = "NSSegmentedCell"; q73-3D-poM.ibShadowedToolTips[0] = "Same as default"; ObjectID = "q73-3D-poM"; */
24 | "q73-3D-poM.ibShadowedToolTips[0]" = "默认模式";
25 |
26 | /* Class = "NSSegmentedCell"; q73-3D-poM.ibShadowedToolTips[1] = "Media keys mode"; ObjectID = "q73-3D-poM"; */
27 | "q73-3D-poM.ibShadowedToolTips[1]" = "媒体键模式";
28 |
29 | /* Class = "NSSegmentedCell"; q73-3D-poM.ibShadowedToolTips[2] = "Function keys mode"; ObjectID = "q73-3D-poM"; */
30 | "q73-3D-poM.ibShadowedToolTips[2]" = "功能键模式";
31 |
32 | /* Class = "NSToolbarItem"; label = "Search"; ObjectID = "u25-IX-3ln"; */
33 | "u25-IX-3ln.label" = "搜索";
34 |
35 | /* Class = "NSToolbarItem"; paletteLabel = "Search"; ObjectID = "u25-IX-3ln"; */
36 | "u25-IX-3ln.paletteLabel" = "搜索";
37 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2016 Pierre Tacchi
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # This README is out-of-date
3 |
4 | [](https://developer.apple.com/swift/)
5 | 
6 | [](https://tldrlegal.com/license/mit-license)
7 |
8 |
9 | 
10 |
11 | > Want to know how **Fluor** development is going ? [**Follow me on Twitter**](https://twitter.com/__pyroh).
12 |
13 | # What is Fluor ?
14 | **Fluor** is a tool that allows you to automatically change the behavior of the keyboard's fn keys depending on the active application. It's that simple.
15 |
16 | # Instaling Fluor
17 | There's two main ways to install **Fluor**:
18 |
19 | 1. Download the [latest release](https://github.com/Pyroh/Fluor/releases), open the DMG and drag the application to your `/Applications` folder.
20 | 2. Install via [Homebrew Cask](https://caskroom.github.io):
21 | `$ brew cask install fluor`
22 |
23 | You can also build it from source, but this is not recommended if your are only going to use **Fluor** in the regular way, and not hack it.
24 |
25 | # How does it work?
26 |
27 |
28 | **Fluor** lies in your status bar and makes you see instantaneously which mode your keyboard is on:
29 |
30 | -
means that the keyboard's fn keys act like the default Apple function keys.
31 | -
means that the keyboard's fn keys act like these good old function keys (F1, F2, F3, you got it...).
32 |
33 | ## Fluor's menu
34 | This is what you get when you click on **Fluor** in the status bar:
35 |
36 |
37 |
38 | You can choose the default mode. Whenever **Fluor** runs it will activate the default mode for your keyboard's fn keys.
39 |
40 | **Fluor** also displays the active application and its associated rule that you can change on the go.
41 |
is the default rule and means that the application will adopt default Fluor's keyboard behaviour.
42 |
43 | You can also disable **Fluor** if you need to. It will set the keyboard's behaviour as it was prior to the application's launch.
44 |
45 | ## Rules Editor
46 |
47 |
48 | This panel allows you to see all the rules you set at once. You can modify or delete any rule. Adding a rule will prompt a file selector in which you'll be able to select the application you want to set a rule for.
49 |
50 | ## Running Applications
51 |
52 |
53 | Sometimes it is not possible to select an application in the *Rules Editor*, especially for Steam games. This panel lets you set a rule for any running application. Of course the rules you set in this panel will be available directly in the *Rules Editor*. You can also remove a rule by setting the application behaviour to
, it will also disappear from the *Rules Editor* panel.
54 |
55 | # Why is it open source ?
56 | I made **Fluor** because I needed such an application. I wanted it simple, nicely designed and free and I didn't find such a thing on the internet. Once it was done I used it for a little while, cleaned up the code and decided to give it to others for free. What was a requirement for me can well be a requirement for others too.
57 | You'd argue that such a non-sandboxed app had no chance to hit the AppStore and you'd be right. But if I had the chance it would have remained free and open-source. I don't think there's many people needing such an app and I prefer seeing it used by a wider range of people.
58 |
59 | This app is also built using open-source code, that's why I think it belongs to this world. And if someone learns something looking at the code I'll be happy 😃.
60 |
61 | # Contributing
62 | All contributions are welcome. Fork it, hack it and make a pull request.
63 |
64 | # License
65 | **Fluor** is released under the MIT license. See LICENSE for details.
66 |
67 | Some of [**fntoggle**](https://github.com/nelsonjchen/fntoggle)'s code was used. As its author [wrote](https://github.com/nelsonjchen/fntoggle#license) it could be released under the GPL2 license.
68 |
69 | The code also uses [**LaunchAtLoginController**](https://github.com/Mozketo/LaunchAtLoginController) which is Copyright (c) 2010 Ben Clark-Robinson, ben.clarkrobinson@gmail.com and is released under the MIT LICENSE.
70 |
--------------------------------------------------------------------------------
/ressources/banner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/ressources/banner.png
--------------------------------------------------------------------------------
/ressources/mainmenu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/ressources/mainmenu.png
--------------------------------------------------------------------------------
/ressources/preferences.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/ressources/preferences.png
--------------------------------------------------------------------------------
/ressources/ruleseditor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/ressources/ruleseditor.png
--------------------------------------------------------------------------------
/ressources/runningapps.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/ressources/runningapps.png
--------------------------------------------------------------------------------
/ressources/statusbar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyroh/Fluor/6b5fcd11324dfe99ef0fb20d4015625a0e96f283/ressources/statusbar.png
--------------------------------------------------------------------------------