User Preference
Default Preference
When creating an extension class, we can provide default extension preferences, which will be used when the user installs the extension for the first time.
class PaperlibHelloworldExtension extends PLExtension {
constructor() {
super({
id: "...",
defaultPreference: {
[id: string]: {
type: "string" | "boolean" | "options" | "pathpicker" | "button" | "hidden",
name: string,
description: string,
value: string | boolean,
order?: number,
options?: { [key: string]: string }, // only for options type
},
...
},
});
}
}Each preference is a key-value pair, the key is the ID of the preference, and the value is an object that contains various information about the preference:
- The
idfield is required, it specifies the ID of the preference. This is used to access the value of the preference later. - The
typefield is required, it specifies the type of the preference. - The
namefield is required, it specifies the name of the preference displayed in the UI. - The
descriptionfield is required, it specifies the description of the preference displayed in the UI. - The
valuefield is required, it specifies the default value of the preference. - The
orderfield is optional, it specifies the display order of the preference. - The
optionsfield is optional, it is only needed when the preference type isoptions, it specifies the options of the option type preference.
Preference Type
As shown above, we provide four types of preferences:
string: String type preference, the user can enter any string.boolean: Boolean type preference, the user can choosetrueorfalse.options: Option type preference, the user can select one from the predefined options. Theoptionsfield must be provided, and each key-value pair in it is an option. Thekeyis the identical value of the option, and thevalueis the display name of the option.pathpicker: Path picker type preference, the user can select a file or folder.button: Button type preference, the user can click the button to perform some operations.hidden: Hidden type preference, will not be displayed in the preference interface.
Different types of preferences will display different components in Paperlib.
Access Preference
To access the value of a preference in an extension, we can use PLExtAPI.extensionPreferenceService.get. For example:
PLExtAPI.extensionPreferenceService.get(this.id, "lang")By doing so, we can get the value of the lang preference. Note that we need to provide the ID of the extension (this.id) so that the ExtensionPreferenceService knows which extension's preference we want to access.
Set Preference
We can set the value of a preference by using PLExtAPI.extensionPreferenceService.set. For example:
PLExtAPI.extensionPreferenceService.set(this.id, {"lang": "en"})Here we provide a patch object`` to modify the preferences. The patch object`` is a key-value pair, where each key-value pair is a modification of a preference. The key is the ID of the preference, and the value is the new value of the preference. You can pass in modifications for multiple preferences at the same time.
Listen Preference Change
We can listen to the change of a preference by using PLExtAPI.extensionPreferenceService.onPreferenceChange. For example:
PLExtAPI.extensionPreferenceService.onChanged(
`${this.id}:lang`,
(changes: {key: string, value: string}) => {
console.log(changes) // {key: "lang", value: "en"}
}
)⚠️ Please note that listening to a setting of an extension must be in the form of
extID:preferenceKeyto form the ID of the event to be listened to. BecauseextensionPreferenceServiceneed to distinguish the preferences of different extensions.
By doing so, we can listen to the modification of the lang preference. When the user modifies the value of the lang in the preferences interface, we will run the callback function passed in. The function receives an Object as an argument , where the key field is the ID of the preference, and the value field is the new value of the preference.
⚠️ Please note that all listener registrations must be cancelled in the
disposefunction of the extension to avoid memory leaks.
Cancel Preference Change Listener
When the extension is uninstalling or reloading, Paperlib will call the dispose function of the extension. In this function, we need to cancel all listener registrations to avoid memory leaks.
When you are listening for changes to a preference, PLExtAPI.extensionPreferenceService.onChanged / on will return a function. Running this function will cancel the listener.
For example:
// Listen
const disposeCallback = PLExtAPI.extensionPreferenceService.onChanged(
`${this.id}:lang`,
(changes: {key: string, value: string}) => {
console.log(changes) // {key: "lang", value: "en"}
}
)
// Cancel
disposeCallback()Storing and Accessing Passwords
Paperlib also provides storage and retrieval of password items. Regular preferences are stored in a .json files near the extension directory, while password items are stored in different keychains depending on the platform. For example, the Keychain on macOS, the Credential Manager on Windows, etc.
await PLExtAPI.extensionPreferenceService.setPassword(
this.id, "password-key", "your-password"
)
const password = await PLExtAPI.extensionPreferenceService.getPassword(
this.id, "password-key"
)Preference File
In Paperlib, the user's preferences are stored in a .json file.
- macOS:
~/Library/Application Support/paperlib/extensions/<extension-id>.json - Windows:
%APPDATA%/paperlib/extensions/<extension-id>.json - Linux:
~/.config/paperlib/extensions/<extension-id>.json