mirror of
https://github.com/ericaxu/gemmy.git
synced 2026-07-22 07:30:31 +00:00
Compare commits
10 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c6916db84b | ||
|
|
195e4df1b6 | ||
|
|
831826d071 | ||
|
|
c1d71da4f9 | ||
|
|
6e2384a001 | ||
|
|
75d05be5c8 | ||
|
|
1e80fe564f | ||
|
|
0f9a59d97e | ||
|
|
37123587c6 | ||
|
|
6303889f2e |
5 changed files with 77 additions and 45 deletions
21
LICENSE
Normal file
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.
|
||||||
20
README.md
20
README.md
|
|
@ -6,29 +6,37 @@ Not sure if an AI assistant is going to be helpful in your workflow?
|
||||||
|
|
||||||
Don't worry, we've eliminated the guesswork for you because Gemmy is 100% going to be unhelpful.
|
Don't worry, we've eliminated the guesswork for you because Gemmy is 100% going to be unhelpful.
|
||||||
|
|
||||||
Introducing Obsidian's first assistant - Gemmy, the Obsidian Unhelper. It has two major features:
|
Introducing Obsidian's first assistant — Gemmy, the Obsidian Unhelper. It has two major features:
|
||||||
|
|
||||||
## Randomly saying things
|
## Randomly saying things
|
||||||
|
|
||||||
Gemmy seeks validation by saying randomly things every now and then.
|
Gemmy seeks validation by randomly saying things every now and then.
|
||||||
|
|
||||||
You can customize how often this happens. Or just don't summon Gemmy.
|
You can customize how often this happens. Or just don't summon Gemmy.
|
||||||
|
|
||||||
## Writing mode
|
## Writing mode
|
||||||
|
|
||||||
Gemmy pops out to [motivate you](https://user-images.githubusercontent.com/1171143/229297494-8a0cae3f-4c8e-47a9-801b-dd1c52dfc917.png) when you have stop typing for long enough. Again you can customize how long that would be.
|
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.
|
||||||
|
|
||||||
Risk: Gemmy might actually be helpful with writing if you use this mode. We're not responsibility for any extra productivity Gemmy brings.
|
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
|
## How to use
|
||||||
|
|
||||||
Install Gemmy. There are four commands in command palette when you type "Gemmy". You can figure out the rest on your own.
|
Install Gemmy. There are four commands in the command palette when you type "Gemmy". You can figure out the rest on your own.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
Special thanks: [Rigmarole](https://rigmarolestudio.com/) for creating and animating Gemmy
|
Special thanks: [Rigmarole](https://rigmarolestudio.com/) for creating and animating Gemmy
|
||||||
|
|
||||||
Credit: the talented Obsidian mods team, including argentum, CawlinTeffid, cotmax, Eleanor Koink, koala, Leah, rigmarole, ryanjamurphy & WhiteNoise
|
Credit: the talented Obsidian mods team, including argentum, CawlinTeffid, cotmax, Eleanor Konik, koala, Leah, rigmarole, ryanjamurphy & WhiteNoise
|
||||||
|
|
||||||
|
The code is under MIT license, whereas the Gemmy character is under CC BY 3.0 license.
|
||||||
|
|
||||||
|
Obsidian logo is adapted from:
|
||||||
|
|
||||||
|
[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)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
68
main.ts
68
main.ts
|
|
@ -7,18 +7,16 @@ import LOOK_MOTION from './animations/gemmy_lookAround.gif'
|
||||||
import IDLE_MOTION from './animations/gemmy_idle.gif'
|
import IDLE_MOTION from './animations/gemmy_idle.gif'
|
||||||
import DISAPPOINT_IMG from './animations/gemmy_disappoint.gif'
|
import DISAPPOINT_IMG from './animations/gemmy_disappoint.gif'
|
||||||
|
|
||||||
// Remember to rename these classes and interfaces!
|
|
||||||
|
|
||||||
interface GemmySettings {
|
interface GemmySettings {
|
||||||
// how often does Gemmy talk in idle mode, in minutes
|
// how often does Gemmy talk in idle mode, in minutes
|
||||||
idleTalkFrequency: number;
|
idleTalkFrequency: number;
|
||||||
// the number of minutes you must write before Gemmy appears to mock you
|
// the number of minutes you must write before Gemmy appears to mock you
|
||||||
writingModeDeadline: number;
|
writingModeGracePeriod: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DEFAULT_SETTINGS: GemmySettings = {
|
const DEFAULT_SETTINGS: GemmySettings = {
|
||||||
idleTalkFrequency: 5,
|
idleTalkFrequency: 5,
|
||||||
writingModeDeadline: 5
|
writingModeGracePeriod: 5
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -28,27 +26,29 @@ const GEMMY_IDLE_QUOTES = [
|
||||||
"You have plugins that you can update!",
|
"You have plugins that you can update!",
|
||||||
"Hi I'm Gemmy! Like Clippy but shinier!",
|
"Hi I'm Gemmy! Like Clippy but shinier!",
|
||||||
"Everything is connected. Everything.",
|
"Everything is connected. Everything.",
|
||||||
`It looks like you’re writing a note.,
|
"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?",
|
||||||
Would you like help?
|
"How tall would all your notes be if you stacked them up?",
|
||||||
- Get help with writing the note
|
"Wanna teach me to say things? Find me on GitHub and open a pull request!",
|
||||||
- Just type the note without help
|
"Have you considered using Comic Sans?",
|
||||||
- [ ] Don’t show me this tip again`,
|
"A blank page is just a masterpiece in waiting"
|
||||||
'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?'
|
|
||||||
];
|
];
|
||||||
|
|
||||||
const WRITING_MODE_QUOTES = [
|
const WRITING_MODE_QUOTES = [
|
||||||
`Is that the best you can do? Keep writing!`,
|
"Is that the best you can do? Keep writing!",
|
||||||
`Write first, editor later.`,
|
"Write first, edit later.",
|
||||||
`I love hearing your keyboard. Don't stop.`,
|
"I love hearing your keyboard. Don't stop.",
|
||||||
`How about we review some old notes today?`,
|
"How about we review some old notes today?",
|
||||||
`Stuck? Try journaling what happened today and see if that gives you inspiration.`,
|
"Stuck? Try journaling what happened today and see if that gives you inspiration.",
|
||||||
`Maybe it's time to go get some water or coffee.`,
|
"Maybe it's time to go get some water or coffee.",
|
||||||
`Anything is better than a blank page, even me. Write something!`
|
"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."
|
||||||
];
|
];
|
||||||
|
|
||||||
const BUBBLE_DURATION = 5000;
|
const BUBBLE_DURATION = 5000;
|
||||||
|
|
@ -70,7 +70,7 @@ export default class Gemmy extends Plugin {
|
||||||
gemmyEl.setAttribute('aria-label-delay', '0');
|
gemmyEl.setAttribute('aria-label-delay', '0');
|
||||||
gemmyEl.setAttribute('aria-label-classes', 'gemmy-tooltip');
|
gemmyEl.setAttribute('aria-label-classes', 'gemmy-tooltip');
|
||||||
|
|
||||||
let gemmyImageEl = this.imageEl = gemmyEl.createEl('img', {});
|
this.imageEl = gemmyEl.createEl('img', {});
|
||||||
|
|
||||||
this.addCommand({
|
this.addCommand({
|
||||||
id: 'show',
|
id: 'show',
|
||||||
|
|
@ -136,6 +136,8 @@ export default class Gemmy extends Plugin {
|
||||||
this.disappear();
|
this.disappear();
|
||||||
this.setWritingModeTimeout();
|
this.setWritingModeTimeout();
|
||||||
}, 500)));
|
}, 500)));
|
||||||
|
|
||||||
|
app.workspace.onLayoutReady(this.appear.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
appear() {
|
appear() {
|
||||||
|
|
@ -143,18 +145,14 @@ export default class Gemmy extends Plugin {
|
||||||
|
|
||||||
imageEl.setAttribute('src', EMERGE_MOTION);
|
imageEl.setAttribute('src', EMERGE_MOTION);
|
||||||
|
|
||||||
// Quick if we're in writing mode
|
// Quicker if we're in writing mode
|
||||||
if (this.inWritingMode) {
|
if (this.inWritingMode) {
|
||||||
imageEl.setAttribute('src', POP_MOTION);
|
imageEl.setAttribute('src', POP_MOTION);
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
// imageEl.setAttribute('src', DISAPPOINT_IMG);
|
|
||||||
// setTimeout(() => {
|
|
||||||
// imageEl.setAttribute('src', DISAPPOINT_IMG);
|
|
||||||
this.appeared = true;
|
this.appeared = true;
|
||||||
|
|
||||||
this.saySomething(WRITING_MODE_QUOTES, true);
|
this.saySomething(WRITING_MODE_QUOTES, true);
|
||||||
// }, 1000);
|
|
||||||
}, 1800);
|
}, 1800);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
@ -185,7 +183,6 @@ export default class Gemmy extends Plugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
enterWritingMode() {
|
enterWritingMode() {
|
||||||
let { gemmyEl } = this;
|
|
||||||
this.inWritingMode = true;
|
this.inWritingMode = true;
|
||||||
|
|
||||||
this.disappear();
|
this.disappear();
|
||||||
|
|
@ -211,7 +208,7 @@ export default class Gemmy extends Plugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.appear();
|
this.appear();
|
||||||
}, this.settings.writingModeDeadline * 60000);
|
}, this.settings.writingModeGracePeriod * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
startNextIdleTimeout() {
|
startNextIdleTimeout() {
|
||||||
|
|
@ -264,7 +261,7 @@ export default class Gemmy extends Plugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
onunload() {
|
onunload() {
|
||||||
|
this.disappear();
|
||||||
}
|
}
|
||||||
|
|
||||||
async loadSettings() {
|
async loadSettings() {
|
||||||
|
|
@ -276,7 +273,6 @@ export default class Gemmy extends Plugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: proper setting tab
|
|
||||||
class GemmySettingTab extends PluginSettingTab {
|
class GemmySettingTab extends PluginSettingTab {
|
||||||
plugin: Gemmy;
|
plugin: Gemmy;
|
||||||
|
|
||||||
|
|
@ -304,13 +300,13 @@ class GemmySettingTab extends PluginSettingTab {
|
||||||
|
|
||||||
new Setting(containerEl)
|
new Setting(containerEl)
|
||||||
.setName('Writing mode grace period')
|
.setName('Writing mode grace period')
|
||||||
.setDesc('How soon Gemmy starts to get disappointed after you stop tying in writing mode, in minutes.')
|
.setDesc('How soon Gemmy starts to get disappointed after you stop tying in writing mode, in seconds.')
|
||||||
.addSlider(slider => slider
|
.addSlider(slider => slider
|
||||||
.setLimits(5, 60, 5)
|
.setLimits(5, 180, 5)
|
||||||
.setDynamicTooltip()
|
.setDynamicTooltip()
|
||||||
.setValue(this.plugin.settings.writingModeDeadline)
|
.setValue(this.plugin.settings.writingModeGracePeriod)
|
||||||
.onChange(async (value) => {
|
.onChange(async (value) => {
|
||||||
this.plugin.settings.writingModeDeadline = value;
|
this.plugin.settings.writingModeGracePeriod = value;
|
||||||
await this.plugin.saveSettings();
|
await this.plugin.saveSettings();
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"id": "gemmy",
|
"id": "gemmy",
|
||||||
"name": "Gemmy",
|
"name": "Gemmy",
|
||||||
"version": "0.0.2",
|
"version": "1.0.1",
|
||||||
"minAppVersion": "0.15.0",
|
"minAppVersion": "0.15.0",
|
||||||
"description": "2023 April Fool's plugin brought to you by Obsidian",
|
"description": "2023 April Fool's plugin brought to you by Obsidian",
|
||||||
"author": "Obsidian",
|
"author": "Obsidian",
|
||||||
|
|
|
||||||
11
styles.css
11
styles.css
|
|
@ -15,6 +15,9 @@ If your plugin does not need CSS, delete this file.
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 30px;
|
bottom: 30px;
|
||||||
right: 30px;
|
right: 30px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-end;
|
||||||
}
|
}
|
||||||
|
|
||||||
.gemmy-container img {
|
.gemmy-container img {
|
||||||
|
|
@ -23,10 +26,14 @@ If your plugin does not need CSS, delete this file.
|
||||||
border-radius: var(--gemmy-size);
|
border-radius: var(--gemmy-size);
|
||||||
}
|
}
|
||||||
|
|
||||||
.gemmy-tooltip {
|
.gemmy-container[aria-label]::before {
|
||||||
--background-modifier-message: #FFFFCB;
|
--background-modifier-message: #FFFFCB;
|
||||||
|
content: attr(aria-label);
|
||||||
color: #202020;
|
color: #202020;
|
||||||
font-size: var(--font-ui-medium);
|
font-size: var(--font-ui-medium);
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
padding: var(--size-4-3) var(--size-4-6);
|
padding: var(--size-4-3) var(--size-4-6);
|
||||||
}
|
width: 150px;
|
||||||
|
background: var(--background-modifier-message);
|
||||||
|
}
|
||||||
|
|
||||||
Loading…
Reference in a new issue