Compare commits
13 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c6916db84b | ||
|
|
195e4df1b6 | ||
|
|
831826d071 | ||
|
|
c1d71da4f9 | ||
|
|
6e2384a001 | ||
|
|
75d05be5c8 | ||
|
|
1e80fe564f | ||
|
|
0f9a59d97e | ||
|
|
37123587c6 | ||
|
|
6303889f2e | ||
|
|
f4f5958f11 | ||
|
|
a50e64b8bf | ||
|
|
61d9ec11e6 |
21
LICENSE
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2023 Erica Xu
|
||||
|
||||
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:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
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.
|
||||
97
README.md
|
|
@ -1,96 +1,45 @@
|
|||
# Obsidian Sample Plugin
|
||||
# Gemmy - Obsidian Unhelper
|
||||
|
||||
This is a sample plugin for Obsidian (https://obsidian.md).
|
||||
<img src="https://user-images.githubusercontent.com/1171143/229297707-5efa8761-ef55-4d01-a105-88a347bc6cf0.png" width="300">
|
||||
|
||||
This project uses Typescript to provide type checking and documentation.
|
||||
The repo depends on the latest plugin API (obsidian.d.ts) in Typescript Definition format, which contains TSDoc comments describing what it does.
|
||||
Not sure if an AI assistant is going to be helpful in your workflow?
|
||||
|
||||
**Note:** The Obsidian API is still in early alpha and is subject to change at any time!
|
||||
Don't worry, we've eliminated the guesswork for you because Gemmy is 100% going to be unhelpful.
|
||||
|
||||
This sample plugin demonstrates some of the basic functionality the plugin API can do.
|
||||
- Changes the default font color to red using `styles.css`.
|
||||
- Adds a ribbon icon, which shows a Notice when clicked.
|
||||
- Adds a command "Open Sample Modal" which opens a Modal.
|
||||
- Adds a plugin setting tab to the settings page.
|
||||
- Registers a global click event and output 'click' to the console.
|
||||
- Registers a global interval which logs 'setInterval' to the console.
|
||||
Introducing Obsidian's first assistant — Gemmy, the Obsidian Unhelper. It has two major features:
|
||||
|
||||
## First time developing plugins?
|
||||
## Randomly saying things
|
||||
|
||||
Quick starting guide for new plugin devs:
|
||||
Gemmy seeks validation by randomly saying things every now and then.
|
||||
|
||||
- Check if [someone already developed a plugin for what you want](https://obsidian.md/plugins)! There might be an existing plugin similar enough that you can partner up with.
|
||||
- Make a copy of this repo as a template with the "Use this template" button (login to GitHub if you don't see it).
|
||||
- Clone your repo to a local development folder. For convenience, you can place this folder in your `.obsidian/plugins/your-plugin-name` folder.
|
||||
- Install NodeJS, then run `npm i` in the command line under your repo folder.
|
||||
- Run `npm run dev` to compile your plugin from `main.ts` to `main.js`.
|
||||
- Make changes to `main.ts` (or create new `.ts` files). Those changes should be automatically compiled into `main.js`.
|
||||
- Reload Obsidian to load the new version of your plugin.
|
||||
- Enable plugin in settings window.
|
||||
- For updates to the Obsidian API run `npm update` in the command line under your repo folder.
|
||||
You can customize how often this happens. Or just don't summon Gemmy.
|
||||
|
||||
## Releasing new releases
|
||||
## Writing mode
|
||||
|
||||
- Update your `manifest.json` with your new version number, such as `1.0.1`, and the minimum Obsidian version required for your latest release.
|
||||
- Update your `versions.json` file with `"new-plugin-version": "minimum-obsidian-version"` so older versions of Obsidian can download an older version of your plugin that's compatible.
|
||||
- Create new GitHub release using your new version number as the "Tag version". Use the exact version number, don't include a prefix `v`. See here for an example: https://github.com/obsidianmd/obsidian-sample-plugin/releases
|
||||
- Upload the files `manifest.json`, `main.js`, `styles.css` as binary attachments. Note: The manifest.json file must be in two places, first the root path of your repository and also in the release.
|
||||
- Publish the release.
|
||||
Gemmy pops out to [motivate you](https://user-images.githubusercontent.com/1171143/229297494-8a0cae3f-4c8e-47a9-801b-dd1c52dfc917.png) when you have stopped typing for long enough. Again, you can customize how long that should be.
|
||||
|
||||
> You can simplify the version bump process by running `npm version patch`, `npm version minor` or `npm version major` after updating `minAppVersion` manually in `manifest.json`.
|
||||
> The command will bump version in `manifest.json` and `package.json`, and add the entry for the new version to `versions.json`
|
||||
|
||||
## Adding your plugin to the community plugin list
|
||||
|
||||
- Check https://github.com/obsidianmd/obsidian-releases/blob/master/plugin-review.md
|
||||
- Publish an initial version.
|
||||
- Make sure you have a `README.md` file in the root of your repo.
|
||||
- Make a pull request at https://github.com/obsidianmd/obsidian-releases to add your plugin.
|
||||
Risk: Gemmy might actually be helpful with writing if you use this mode. We're not responsible for any extra productivity Gemmy might bring.
|
||||
|
||||
## How to use
|
||||
|
||||
- Clone this repo.
|
||||
- `npm i` or `yarn` to install dependencies
|
||||
- `npm run dev` to start compilation in watch mode.
|
||||
Install Gemmy. There are four commands in the command palette when you type "Gemmy". You can figure out the rest on your own.
|
||||
|
||||
## Manually installing the plugin
|
||||
---
|
||||
|
||||
- Copy over `main.js`, `styles.css`, `manifest.json` to your vault `VaultFolder/.obsidian/plugins/your-plugin-id/`.
|
||||
Special thanks: [Rigmarole](https://rigmarolestudio.com/) for creating and animating Gemmy
|
||||
|
||||
## Improve code quality with eslint (optional)
|
||||
- [ESLint](https://eslint.org/) is a tool that analyzes your code to quickly find problems. You can run ESLint against your plugin to find common bugs and ways to improve your code.
|
||||
- To use eslint with this project, make sure to install eslint from terminal:
|
||||
- `npm install -g eslint`
|
||||
- To use eslint to analyze this project use this command:
|
||||
- `eslint main.ts`
|
||||
- eslint will then create a report with suggestions for code improvement by file and line number.
|
||||
- If your source code is in a folder, such as `src`, you can use eslint with this command to analyze all files in that folder:
|
||||
- `eslint .\src\`
|
||||
Credit: the talented Obsidian mods team, including argentum, CawlinTeffid, cotmax, Eleanor Konik, koala, Leah, rigmarole, ryanjamurphy & WhiteNoise
|
||||
|
||||
## Funding URL
|
||||
The code is under MIT license, whereas the Gemmy character is under CC BY 3.0 license.
|
||||
|
||||
You can include funding URLs where people who use your plugin can financially support it.
|
||||
Obsidian logo is adapted from:
|
||||
|
||||
The simple way is to set the `fundingUrl` field to your link in your `manifest.json` file:
|
||||
[Crystal shard icon](https://icon-icons.com/icon/Crystal-Shard/88819)
|
||||
By [Chanut is Industries](https://icon-icons.com/users/W52nHhY3W1VlvwyJTwS4d/icon-sets/)
|
||||
License: Attribution 3.0 Unported (CC BY 3.0)
|
||||
|
||||
```json
|
||||
{
|
||||
"fundingUrl": "https://buymeacoffee.com"
|
||||
}
|
||||
```
|
||||
---
|
||||
|
||||
If you have multiple URLs, you can also do:
|
||||
## Happy April Fools'
|
||||
|
||||
```json
|
||||
{
|
||||
"fundingUrl": {
|
||||
"Buy Me a Coffee": "https://buymeacoffee.com",
|
||||
"GitHub Sponsor": "https://github.com/sponsors",
|
||||
"Patreon": "https://www.patreon.com/"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## API Documentation
|
||||
|
||||
See https://github.com/obsidianmd/obsidian-api
|
||||
Gemmy was proudly released on April 1, 2023.
|
||||
|
|
|
|||
BIN
animations/gemmy_angry.gif
Normal file
|
After Width: | Height: | Size: 61 KiB |
BIN
animations/gemmy_disappear.gif
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
animations/gemmy_disappoint.gif
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
animations/gemmy_emerge.gif
Normal file
|
After Width: | Height: | Size: 103 KiB |
BIN
animations/gemmy_idle.gif
Normal file
|
After Width: | Height: | Size: 237 KiB |
BIN
animations/gemmy_lookAround.gif
Normal file
|
After Width: | Height: | Size: 195 KiB |
BIN
animations/gemmy_pop.gif
Normal file
|
After Width: | Height: | Size: 56 KiB |
BIN
gemmy_emerge.gif
|
Before Width: | Height: | Size: 467 KiB |
197
main.ts
|
|
@ -1,21 +1,22 @@
|
|||
import { App, debounce, Plugin, PluginSettingTab, Setting } from 'obsidian';
|
||||
import { NORMAL_BASE64, SPEAKING_BASE64 } from 'resources';
|
||||
import EMERGE_MOTION_BASE64 from './gemmy_emerge.gif';
|
||||
|
||||
// Remember to rename these classes and interfaces!
|
||||
import EMERGE_MOTION from './animations/gemmy_emerge.gif';
|
||||
import POP_MOTION from './animations/gemmy_pop.gif';
|
||||
import DISAPPEAR_MOTION from './animations/gemmy_disappear.gif';
|
||||
import ANGRY_MOTION from './animations/gemmy_angry.gif';
|
||||
import LOOK_MOTION from './animations/gemmy_lookAround.gif'
|
||||
import IDLE_MOTION from './animations/gemmy_idle.gif'
|
||||
import DISAPPOINT_IMG from './animations/gemmy_disappoint.gif'
|
||||
|
||||
interface GemmySettings {
|
||||
show: boolean;
|
||||
// in minutes
|
||||
talkFrequency: number;
|
||||
// how often does Gemmy talk in idle mode, in minutes
|
||||
idleTalkFrequency: number;
|
||||
// the number of minutes you must write before Gemmy appears to mock you
|
||||
writingModeDeadline: number;
|
||||
writingModeGracePeriod: number;
|
||||
}
|
||||
|
||||
const DEFAULT_SETTINGS: GemmySettings = {
|
||||
show: true,
|
||||
talkFrequency: 5,
|
||||
writingModeDeadline: 0.1
|
||||
idleTalkFrequency: 5,
|
||||
writingModeGracePeriod: 5
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -25,56 +26,54 @@ const GEMMY_IDLE_QUOTES = [
|
|||
"You have plugins that you can update!",
|
||||
"Hi I'm Gemmy! Like Clippy but shinier!",
|
||||
"Everything is connected. Everything.",
|
||||
`It looks like you’re writing a note.
|
||||
|
||||
Would you like help?
|
||||
- Get help with writing the note
|
||||
- Just type the note without help
|
||||
- [ ] Don’t show me this tip again`,
|
||||
'Can’t decide which note to work on? Try the Random Note core plugin!',
|
||||
'Are you sure you don’t want to upload all your notes so you can talk',
|
||||
'How tall would all your notes be if you stacked them up?'
|
||||
"Can’t decide which note to work on? Try the Random Note core plugin!",
|
||||
"Are you sure you don’t want to upload all your notes just so we can chat?",
|
||||
"How tall would all your notes be if you stacked them up?",
|
||||
"Wanna teach me to say things? Find me on GitHub and open a pull request!",
|
||||
"Have you considered using Comic Sans?",
|
||||
"A blank page is just a masterpiece in waiting"
|
||||
];
|
||||
|
||||
const WRITING_MODE_QUOTES = [
|
||||
`Is that the best you can do? Keep writing!`,
|
||||
`Write first, editor later.`,
|
||||
`I love hearing your keyboard. Don't stop.`,
|
||||
`How about we review some old notes today?`,
|
||||
`Stuck? Try journaling what happened today and see if that gives you inspiration.`,
|
||||
`Maybe it's time to go get some water or coffee.`,
|
||||
`Anything is better than a blank page, even me. Write something!`
|
||||
"Is that the best you can do? Keep writing!",
|
||||
"Write first, edit later.",
|
||||
"I love hearing your keyboard. Don't stop.",
|
||||
"How about we review some old notes today?",
|
||||
"Stuck? Try journaling what happened today and see if that gives you inspiration.",
|
||||
"Maybe it's time to go get some water or coffee.",
|
||||
"Anything is better than a blank page, even me. Write something!",
|
||||
"Oh, taking a break? Don’t let the ideas get cold!",
|
||||
"What’s this? Writer’s block already?",
|
||||
"You’ve got this! Every keystroke is a step closer to brilliance.",
|
||||
"You’re doing amazing! Keep the momentum going.",
|
||||
"Bold choice to open Obsidian and then do absolutely nothing.",
|
||||
"Is this a journal or a staring contest with the cursor?",
|
||||
"Hmm, I didn’t realize staring at the screen was a new note-taking strategy."
|
||||
];
|
||||
|
||||
// TODO: use settings for these
|
||||
const TALK_FREQUENCY = 5000;
|
||||
const BUBBLE_DURATION = 1000;
|
||||
const BUBBLE_DURATION = 5000;
|
||||
|
||||
export default class Gemmy extends Plugin {
|
||||
settings: GemmySettings;
|
||||
gemmyEl: HTMLElement;
|
||||
imageEl: HTMLElement;
|
||||
intervalId: number;
|
||||
inWritingMode: boolean = false;
|
||||
idleTimeout: number;
|
||||
writingModeTimeout: number;
|
||||
appeared: boolean = false;
|
||||
|
||||
async onload() {
|
||||
await this.loadSettings();
|
||||
|
||||
// TOOD: prettier speech bubbles
|
||||
let gemmyEl = this.gemmyEl = document.body.createDiv('gemmy-container');
|
||||
let gemmyEl = this.gemmyEl = createDiv('gemmy-container');
|
||||
gemmyEl.setAttribute('aria-label-position', 'top');
|
||||
gemmyEl.setAttribute('aria-label-delay', '0');
|
||||
gemmyEl.setAttribute('aria-label-classes', 'gemmy-tooltip');
|
||||
|
||||
let gemmyImageEl = this.imageEl = gemmyEl.createEl('img', {});
|
||||
gemmyImageEl.setAttribute('src', NORMAL_BASE64);
|
||||
|
||||
gemmyEl.hide();
|
||||
this.imageEl = gemmyEl.createEl('img', {});
|
||||
|
||||
this.addCommand({
|
||||
id: 'gemmy:show',
|
||||
id: 'show',
|
||||
name: 'Show Gemmy',
|
||||
callback: () => {
|
||||
this.appear();
|
||||
|
|
@ -82,7 +81,7 @@ export default class Gemmy extends Plugin {
|
|||
});
|
||||
|
||||
this.addCommand({
|
||||
id: 'gemmy:hide',
|
||||
id: 'hide',
|
||||
name: 'Hide Gemmy',
|
||||
callback: () => {
|
||||
this.disappear();
|
||||
|
|
@ -90,7 +89,7 @@ export default class Gemmy extends Plugin {
|
|||
});
|
||||
|
||||
this.addCommand({
|
||||
id: 'gemmy:enter-writing-mode',
|
||||
id: 'enter-writing-mode',
|
||||
name: 'Enter writing mode',
|
||||
callback: () => {
|
||||
this.enterWritingMode();
|
||||
|
|
@ -98,10 +97,10 @@ export default class Gemmy extends Plugin {
|
|||
});
|
||||
|
||||
this.addCommand({
|
||||
id: 'gemmy:exit-writing-mode',
|
||||
name: 'Exit writing mode',
|
||||
id: 'leave-writing-mode',
|
||||
name: 'Leave writing mode',
|
||||
callback: () => {
|
||||
this.exitWritingMode();
|
||||
this.leaveWritingMode();
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -114,7 +113,7 @@ export default class Gemmy extends Plugin {
|
|||
}
|
||||
|
||||
this.saySomething(GEMMY_IDLE_QUOTES, true);
|
||||
this.intervalId && clearInterval(this.intervalId);
|
||||
this.idleTimeout && clearTimeout(this.idleTimeout);
|
||||
|
||||
});
|
||||
this.gemmyEl.addEventListener('mouseleave', () => {
|
||||
|
|
@ -122,11 +121,11 @@ export default class Gemmy extends Plugin {
|
|||
return;
|
||||
}
|
||||
|
||||
this.imageEl.setAttribute('src', NORMAL_BASE64);
|
||||
this.restartIdleInterval();
|
||||
this.imageEl.setAttribute('src', IDLE_MOTION);
|
||||
this.startNextIdleTimeout();
|
||||
});
|
||||
|
||||
this.restartIdleInterval();
|
||||
this.startNextIdleTimeout();
|
||||
|
||||
// debounce editor-change event on workspace
|
||||
this.registerEvent(this.app.workspace.on('editor-change', debounce(() => {
|
||||
|
|
@ -137,31 +136,53 @@ export default class Gemmy extends Plugin {
|
|||
this.disappear();
|
||||
this.setWritingModeTimeout();
|
||||
}, 500)));
|
||||
|
||||
app.workspace.onLayoutReady(this.appear.bind(this));
|
||||
}
|
||||
|
||||
appear() {
|
||||
let { gemmyEl, imageEl } = this;
|
||||
|
||||
imageEl.setAttribute('src', EMERGE_MOTION_BASE64);
|
||||
imageEl.setAttribute('src', EMERGE_MOTION);
|
||||
|
||||
// Quicker if we're in writing mode
|
||||
if (this.inWritingMode) {
|
||||
imageEl.setAttribute('src', POP_MOTION);
|
||||
|
||||
setTimeout(() => {
|
||||
imageEl.setAttribute('src', NORMAL_BASE64);
|
||||
this.appeared = true;
|
||||
|
||||
if (this.inWritingMode) {
|
||||
this.saySomething(WRITING_MODE_QUOTES, true);
|
||||
}, 1800);
|
||||
}
|
||||
}, 4800);
|
||||
else {
|
||||
imageEl.setAttribute('src', EMERGE_MOTION);
|
||||
|
||||
setTimeout(() => {
|
||||
imageEl.setAttribute('src', IDLE_MOTION);
|
||||
this.appeared = true;
|
||||
}, 3800);
|
||||
}
|
||||
|
||||
document.body.appendChild(gemmyEl);
|
||||
gemmyEl.show();
|
||||
}
|
||||
|
||||
disappear() {
|
||||
this.idleTimeout && window.clearTimeout(this.idleTimeout);
|
||||
this.writingModeTimeout && window.clearTimeout(this.writingModeTimeout);
|
||||
|
||||
this.imageEl.setAttribute('src', DISAPPEAR_MOTION);
|
||||
// remote tooltip
|
||||
this.gemmyEl.dispatchEvent(new MouseEvent('mouseout', { bubbles: true, clientX: 10, clientY: 10 }));
|
||||
setTimeout(() => {
|
||||
this.gemmyEl.hide();
|
||||
this.appeared = false;
|
||||
}, 1300);
|
||||
|
||||
}
|
||||
|
||||
enterWritingMode() {
|
||||
let { gemmyEl } = this;
|
||||
this.inWritingMode = true;
|
||||
|
||||
this.disappear();
|
||||
|
|
@ -169,9 +190,9 @@ export default class Gemmy extends Plugin {
|
|||
this.setWritingModeTimeout();
|
||||
}
|
||||
|
||||
exitWritingMode() {
|
||||
leaveWritingMode() {
|
||||
this.inWritingMode = false;
|
||||
this.appear();
|
||||
this.disappear();
|
||||
|
||||
window.clearTimeout(this.writingModeTimeout);
|
||||
}
|
||||
|
|
@ -187,17 +208,27 @@ export default class Gemmy extends Plugin {
|
|||
}
|
||||
|
||||
this.appear();
|
||||
}, this.settings.writingModeDeadline * 60000);
|
||||
}, this.settings.writingModeGracePeriod * 1000);
|
||||
}
|
||||
|
||||
restartIdleInterval() {
|
||||
this.intervalId = this.registerInterval(window.setInterval(() => {
|
||||
startNextIdleTimeout() {
|
||||
// if the set time is 5 minutes, this will set timeout to be a random time between 4-6 minutes
|
||||
// the range will be 80% - 120%
|
||||
let randomFactor = 0.8 + 0.4 * Math.random();
|
||||
let randomizedTimeout = randomFactor * this.settings.idleTalkFrequency * 60000;
|
||||
|
||||
if (this.idleTimeout) {
|
||||
window.clearTimeout(this.idleTimeout);
|
||||
}
|
||||
|
||||
this.idleTimeout = window.setTimeout(() => {
|
||||
if (this.inWritingMode) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.saySomething(GEMMY_IDLE_QUOTES, false);
|
||||
}, TALK_FREQUENCY));
|
||||
this.startNextIdleTimeout();
|
||||
}, randomizedTimeout);
|
||||
}
|
||||
|
||||
saySomething(quotes: string[], persistent: boolean) {
|
||||
|
|
@ -210,18 +241,27 @@ export default class Gemmy extends Plugin {
|
|||
this.gemmyEl.setAttr('aria-label', randomThing);
|
||||
this.gemmyEl.setAttr('aria-label-position', 'top');
|
||||
this.gemmyEl.dispatchEvent(new MouseEvent('mouseover', { bubbles: true, clientX: 10, clientY: 10 }))
|
||||
this.imageEl.setAttribute('src', SPEAKING_BASE64);
|
||||
|
||||
if (this.inWritingMode) {
|
||||
this.imageEl.setAttribute('src', ANGRY_MOTION);
|
||||
setTimeout(() => {
|
||||
this.imageEl.setAttribute('src', DISAPPOINT_IMG);
|
||||
}, 1000);
|
||||
}
|
||||
else {
|
||||
this.imageEl.setAttribute('src', LOOK_MOTION);
|
||||
}
|
||||
|
||||
if (!persistent) {
|
||||
setTimeout(() => {
|
||||
this.gemmyEl.dispatchEvent(new MouseEvent('mouseout', { bubbles: true, clientX: 10, clientY: 10 }));
|
||||
this.imageEl.setAttribute('src', NORMAL_BASE64);
|
||||
this.imageEl.setAttribute('src', IDLE_MOTION);
|
||||
}, BUBBLE_DURATION);
|
||||
}
|
||||
}
|
||||
|
||||
onunload() {
|
||||
|
||||
this.disappear();
|
||||
}
|
||||
|
||||
async loadSettings() {
|
||||
|
|
@ -233,7 +273,6 @@ export default class Gemmy extends Plugin {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: proper setting tab
|
||||
class GemmySettingTab extends PluginSettingTab {
|
||||
plugin: Gemmy;
|
||||
|
||||
|
|
@ -247,18 +286,28 @@ class GemmySettingTab extends PluginSettingTab {
|
|||
|
||||
containerEl.empty();
|
||||
|
||||
containerEl.createEl('h2', { text: 'Settings for my awesome plugin.' });
|
||||
new Setting(containerEl)
|
||||
.setName('Idle talk frequency')
|
||||
.setDesc('How often does Gemmy speak when idle, in minutes.')
|
||||
.addSlider(slider => slider
|
||||
.setLimits(5, 60, 5)
|
||||
.setValue(this.plugin.settings.idleTalkFrequency)
|
||||
.setDynamicTooltip()
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.idleTalkFrequency = value;
|
||||
await this.plugin.saveSettings();
|
||||
}));
|
||||
|
||||
// new Setting(containerEl)
|
||||
// .setName('Setting #1')
|
||||
// .setDesc('It\'s a secret')
|
||||
// .addText(text => text
|
||||
// .setPlaceholder('Enter your secret')
|
||||
// .setValue(this.plugin.settings.mySetting)
|
||||
// .onChange(async (value) => {
|
||||
// console.log('Secret: ' + value);
|
||||
// this.plugin.settings.mySetting = value;
|
||||
// await this.plugin.saveSettings();
|
||||
// }));
|
||||
new Setting(containerEl)
|
||||
.setName('Writing mode grace period')
|
||||
.setDesc('How soon Gemmy starts to get disappointed after you stop tying in writing mode, in seconds.')
|
||||
.addSlider(slider => slider
|
||||
.setLimits(5, 180, 5)
|
||||
.setDynamicTooltip()
|
||||
.setValue(this.plugin.settings.writingModeGracePeriod)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.writingModeGracePeriod = value;
|
||||
await this.plugin.saveSettings();
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "gemmy",
|
||||
"name": "Gemmy",
|
||||
"version": "0.0.1",
|
||||
"version": "1.0.1",
|
||||
"minAppVersion": "0.15.0",
|
||||
"description": "2023 April Fool's plugin brought to you by Obsidian",
|
||||
"author": "Obsidian",
|
||||
|
|
|
|||
15
styles.css
|
|
@ -15,6 +15,9 @@ If your plugin does not need CSS, delete this file.
|
|||
position: fixed;
|
||||
bottom: 30px;
|
||||
right: 30px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.gemmy-container img {
|
||||
|
|
@ -23,6 +26,14 @@ If your plugin does not need CSS, delete this file.
|
|||
border-radius: var(--gemmy-size);
|
||||
}
|
||||
|
||||
.gemmy-tooltip {
|
||||
.gemmy-container[aria-label]::before {
|
||||
--background-modifier-message: #FFFFCB;
|
||||
content: attr(aria-label);
|
||||
color: #202020;
|
||||
font-size: var(--font-ui-medium);
|
||||
}
|
||||
border-radius: 20px;
|
||||
padding: var(--size-4-3) var(--size-4-6);
|
||||
width: 150px;
|
||||
background: var(--background-modifier-message);
|
||||
}
|
||||
|
||||