Flipswitch | |
---|---|
Cydia Package | |
Package ID | com.a3tweaks.flipswitch |
Latest Version | 1.0.15 |
libflipswitch is a library used to implement a centralized toggle system. Flipswitch switches (or toggles) can be used as extensions of existing tweaks to provide an interface to enable/disable them.
How to use this library
Headers are available from Flipswitch's GitHub project and the library can be found at /usr/lib/libflipswitch.dylib
on a device where Flipswitch is installed. If using Theos, place the headers in $THEOS/include/Flipswitch
, the library in $THEOS/lib/
.
Include directive
#import <Flipswitch/Flipswitch.h>
Makefile
Add to your Makefile:
flipswitch
to theXXX_LIBRARIES
variable.
Packaging
Add to your package's control file:
, com.a3tweaks.flipswitch
to theDepends
field.
How to make a new switch
To make a switch there are two methods, with or without code. It is recommended to add a glyph so your switch has a visual representation.
Preferred method
Save this NIC template to the $THEOS/templates/iphone
directory and call $THEOS/bin/nic.pl
to get a premade switch. Once built, it will be installed to /Library/Switches/
.
There will be 2 methods already written in Switch.x
. Here's a sample of a basic switch implementation template:
// Return the current state of the switch.
- (FSSwitchState)stateForSwitchIdentifier:(NSString *)switchIdentifier {
return (getSwitchState())?FSSwitchStateOn:FSSwitchStateOff;
}
// Set a new state for the switch.
- (void)applyState:(FSSwitchState)newState forSwitchIdentifier:(NSString *)switchIdentifier {
switch (newState) {
case FSSwitchStateIndeterminate:
break;
case FSSwitchStateOn:
// Enable your tweak
break;
case FSSwitchStateOff:
// Disable your tweak
break;
}
return;
}
// Provide a proper title instead of its bundle ID:
- (NSString *)titleForSwitchIdentifier:(NSString *)switchIdentifier {
return @"my switch";
}
// Do something different when holding the switch
- (void)applyAlternateActionForSwitchIdentifier:(NSString *)switchIdentifier {
// ...
return;
}
If - (void)applyAlternateActionForSwitchIdentifier:(NSString *)switchIdentifier;
is not implemented, Flipswitch will try to open a URL specified in the "alternate-action-url" key inside the Resources/Info.plist
file
You will find the protocol with the list of methods to implement in FSSwitchDataSource.h
located in your switch folder.
Note: all of the default implementations of the FSSwitchDataSource methods read data out of the bundle specified by bundleForSwitchIdentifier: (which defaults to the bundle that implements [self class]). You can either override the methods to return your own custom images or image paths or return a bundle and let all of the standard methods do their thing (this includes reading the title from CFBundleDisplayName, detecting if the switch is supported on the device using required-capabilities, and automatically installing an alternate/hold action by reading from alternate-action-url).
Plist method
This only requires an Info.plist
added in your switch folder. This plist file should contain the basic keys for describing a bundle plus the following keys:
key | type | description |
---|---|---|
NSPrincipalClass | string | Class name to be used for the switch. |
defaults | string | User defaults associated with this switch. |
key | string | Key to be modified on the switch's defaults. |
default | string | Default value of the switch. |
negate | array | Save the opposite value. |
PostNotification | string | Darwin notification string to be posted when a change happens. |
alternate-action-url | string | URL to be opened when holding the switch. |
lazy-load | BOOL | The bundle for the switch will only be loaded when querying the state or invoking the switch. |
Uses FSLazySwitch as NSPrincipalClass when lazy-load set to true. The bundle will not be loaded when querying the title or the list of switches.
Set NSPrincipalClass
to FSPreferenceSwitchDataSource
for your switch to get the preference switch implementation.
See AirplaneMode and other switches for reference.
Glyphs
Glyphs are the visual part of the switch that should represent your switch's state. You should create black vector images with transparent background and save them as PDFs in your Resources
folder, where an Info.plist
file resides. Name them as follows:
Name | Description |
---|---|
glyph.pdf | Will be used when no glyph exists for the current state |
glyph-on.pdf | Used on iOS < 7 for FSSwitchStateOn state |
glyph-off.pdf | Used on iOS < 7 for FSSwitchStateOff state |
glyph-indeterminate.pdf | Used on iOS < 7 for FSSwitchStateIndeterminatestate |
glyph-modern.pdf | Will be used when no glyph exists for the current state on iOS ≥ 7 |
glyph-modern-on.pdf | Used on iOS ≥ 7 for FSSwitchStateOn state |
glyph-modern-off.pdf | Used on iOS ≥ 7 for FSSwitchStateOff state |
glyph-modern-indeterminate.pdf | Used on iOS ≥ 7 for FSSwitchStateIndeterminatestate |
For common switches, you should make at least two icons, one for on
state and one for off
state. For button-like switches, glyph.pdf should suffice.
How to provide preferences
Simple Approach
Add the following dictionary to your PreferenceLoader plist to make use of the Flipswitch preference bundle:
<dict>
<key>cell</key>
<string>PSLinkCell</string>
<key>label</key>
<string>Active Switches</string>
<key>isController</key>
<true/>
<key>bundle</key>
<string>FlipswitchSettings</string>
</dict>
Extra keys for optimal usage:
key | type | description |
---|---|---|
flipswitchTemplateBundle | string | Absolute path to a flipswitch template bundle. |
flipswitchSettingsFile | string | Absolute file path to a settings file. |
flipswitchPostNotification | string | Darwin notification string to be posted when a change happens. |
flipswitchEnabledKey | string | Key for array of enabled switches. |
flipswitchDisabledKey | string | Key for array of disabled switches. |
flipswitchDefaultEnabled | array | Array of switch identifiers that are in the enabled section by default. |
flipswitchDefaultDisabled | array | Array of switch identifiers that are in the disabled section by default. |
flipswitchSettingsMode | string | Set to "enabling" for checkable cells or "reordering" for draggable cells between enabled and disabled sections. |
flipswitchNewAreDisabled | BOOL | Switches not present previously in the settings file are added to the disabled switches array, if false, they are added to the enabled switches array. |
How to make a template bundle
These bundles contain information about how a switch glyph (the image that the user sees for a given switch) is rendered when it is used in a button returned by the appropriate method of the FlipSwitch panel. Bundles contain an Info.plist
file and optionally image files. Here is an example of an Info.plist
, taken from SwitchIcons:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleIdentifier</key>
<string>com.rpetrich.switchicon.icon-template</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>DTPlatformName</key>
<string>iphoneos</string>
<key>MinimumOSVersion</key>
<string>2.0</string>
<key>width</key>
<integer>59</integer>
<key>height</key>
<integer>60</integer>
<key>layers</key>
<array>
<...>
</array>
</dict>
</plist>
Keys not specified in the following table can use the same values as the example given.
key | type | meaning | |
---|---|---|---|
CFBundleIdentifier | string | Template bundle identifier. | |
width | integer | Width of the icon. | |
height | integer | Height of the icon. | |
layers | array | ... of dictionaries | Change visuals of switch glyph. |
layers
array can contain dictionaries with the following keys:
key | type | meaning | range of values | default value | depends |
---|---|---|---|---|---|
type | string | Layer type. | "image", "glyph" | - | - |
opacity | float | Alpha value for current layer. | 0.0 to 1.0 | 1.0 | - |
x | float | X value for offset position. | - | 0.0 | - |
y | float | Y value for offset position. | - | 0.0 | - |
fileName | string | Image filename without extension. | - | - | - |
blur | float | Blur value for current layer. | 0.0 to 1.0 | 0.0 | type = "glyph" |
size | float | Glyph size. | - | 0 | type = "glyph" |
state | string | Switch state filter. | "on", "off", "indeterminate" | - | type = "glyph" |
cutout | BOOL | Cutout mask flag. | - | NO | type = "glyph" |
cutoutX | float | X offset for cutout mask. | - | 0.0 | type = "glyph" && cutout = YES |
cutoutY | float | Y offset for cutout mask. | - | 0.0 | type = "glyph" && cutout = YES |
cutoutBlur | float | Blur for cutout mask. | 0.0 to 1.0 | 0.0 | type = "glyph" && cutout = YES |
color | string | Hex color for current layer. | "#000000" to "#FFFFFF" | "#000000" | type = "glyph" && filename = nil |
blendMode | string | Blend mode for compositing layers. | CGBlendMode | kCGBlendModeNormal | type = "image" |
layers
are applied to the button one over the other.
If type
is "image", the current layer will draw the image found in filename
. Best use of this layer could be as a background.
If type
is "glyph", the current layer will use the switch glyph as a mask. When state
is present, the layer
will select the glyph for said state. If cutout
is true, the layer will be composed of only the glyph's borders.
It is possible to use a layer
for each state by creating new layers
arrays named layers-on
, layers-off
or layers-indeterminate
.
The hex string in color
is formatted #RRGGBB.
For more information on existing blend modes and their effects, see Apple's documentation.
How to show switches
The following code can be used to retrieve the full list of switches that FlipSwitch knows about:
NSBundle *templateBundle = [NSBundle bundleWithPath:@"/path/to/bundle.bundle"];
FSSwitchPanel *fsp = [FSSwitchPanel sharedPanel];
for (NSString *identifier in fsp.switchIdentifiers) {
UIButton *button = [fsp buttonForSwitchIdentifier:identifier usingTemplate:templateBundle];
// ... now you have a button with the style described by the template bundle that you can add to any view
}
To show the list of switches that the user set in the settings of your tweak, from your defaults plist in /var/mobile/Library/Preferences
via creating an NSDictionary, using NSUserDefaults or CFPreferences... family functions, get the object for the key name set for flipswitchEnabledKey
and use the code above replacing fsp.switchIdentifiers
with the array you just got.
How to flip switches
To flip switches programmatically, you can use the shared instance of FSSwitchPanel.
NSString *switchIdentifier = @"com.a3tweaks.switch.flashlight";
FSSwitchPanel *fsp = [FSSwitchPanel sharedPanel];
// Returns the current state of a particular switch
FSSwitchState state = [fsp stateForSwitchIdentifier:switchIdentifier];
// Updates the state of a particular switch. If the switch accepts the change it will send a state change
[fsp setState:FSSwitchStateOn forSwitchIdentifier:switchIdentifier];
// Applies the default action of a particular switch
[fsp applyActionForSwitchIdentifier:switchIdentifier];
// Queries whether a switch supports an alternate action. This is often triggered by a hold gesture
BOOL b = [fsp hasAlternateActionForSwitchIdentifier:switchIdentifier];
if (b) {
// Apply the alternate action of a particular switch
[fsp applyAlternateActionForSwitchIdentifier:switchIdentifier];
}