Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Notable changes to **pixelpets**. All art and sound are original/procedural (no
- **Report a problem.** From the tray or Settings > Tools. It shows the exact text first (versions, OS, which features are switched on by name only, and the recent redacted log), then opens GitHub's bug form in your browser, prefilled, when you click. The app itself sends nothing.

### Quick Tools
- **Snippets: save text once, get it back by name.** Copy your address, your email sign-off or a meeting link, type `save sig`, and from then on `;sig` copies it again. `;` lists what you have saved and `forget sig` deletes one. Saving reads the clipboard at that moment, so the launcher never handles the text, and the pet never says it back. Snippets are kept in `settings.json` as plain text; a private key or a token in a known format is refused. In all eight languages, and in the `?` list.
- **Type `?` to see what you can type.** Every tool in the launcher was a typed command you had to read the docs to learn. `?` (or `help`, or "What can I type?" at the bottom of the list) now shows an example of each one, and pressing Enter on an example puts its start in the box for you to finish, so `todo ` is waiting for the rest of the sentence. In all eight languages.
- **Fix the text you just copied.** `upper`, `lower`, `title`, `plain` (drops fonts, colours and links before you paste), `one line` (mends the broken lines of a paragraph copied from a PDF or an email) and `count` (words, characters, lines). Typing `text` lists all six. They work whether or not clipboard history is on, because nothing is kept: the clipboard is read only at the moment you run one, the launcher never shows what is on it, and the pet does not repeat it.
- **One box for everyday things.** Ctrl+Shift+Space (Cmd+Shift+Space on a Mac) or right-clicking the pet opens a keyboard-first launcher: pinned sites, folders and apps, a calculator and unit converter, web search, quick notes, today's to-dos (five at most, with a cheer when you finish one and one afternoon nudge), timers the pet announces, screen snip, lock screen and keep awake.
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ Right-click the pet, or press Ctrl+Shift+Space (Cmd+Shift+Space on a Mac) from a
| `10m tea`, `1h30m` | A timer the pet announces when it's up |
| `todo call the dentist`, `done 1` | Today's to-dos, five at most. The pet cheers when you tick one off |
| `note the wifi code is on the fridge` | Adds a line to your notes file |
| `save sig`, then `;sig` | Keeps the text you copied under a name, and copies it back when you type the name |
| `=12*7.5`, `5 km in mi`, `72 f to c` | Calculates or converts. Enter copies the answer |
| `plain`, `upper`, `one line`, `count` | Fixes the text you just copied, ready to paste |
| `g best pizza near me` | Searches the web |
Expand Down Expand Up @@ -140,6 +141,8 @@ pixelpets keeps a small diagnostic log on your machine (`logs/pixelpets.log` in

Clipboard history is off by default. When it's on, it keeps the last 20 things you copied in memory only, skips anything that looks like a password or key, and forgets everything when you lock the screen or quit.

Snippets you save with `save` are different from clipboard history: they are kept, as plain text, in `settings.json`. Text in a known key or token format is refused, but nothing can recognise every password, so don't save one.

Settings are saved to `settings.json` in your app-data folder: `%APPDATA%/pixelpets/` on Windows, `~/Library/Application Support/pixelpets/` on macOS.

[SECURITY.md](SECURITY.md) explains how to report a vulnerability privately.
Expand Down
9 changes: 9 additions & 0 deletions docs/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,15 @@ today's to-dos, running timers and a few one-press actions.
from clipboard history and works with it off: the clipboard is read once,
when you press Enter, nothing is stored, and neither the launcher nor the
pet shows the text. Copied text over 200,000 characters is left alone.
- **Snippets.** Text you type again and again: an address, an email sign-off,
a meeting link. Copy it once, type `save sig`, and from then on `;sig` copies
it back. `;` on its own lists them all, `save sig` again replaces it with
whatever you have copied now, and `forget sig` deletes it. A name is one
word, up to 24 letters and digits. You can keep 30, each up to 2,000
characters. Unlike clipboard history, snippets are meant to last, so they
are written to `settings.json` as plain text. Text in a known key or token
format (a private key, a GitHub or AWS token) is refused, but no check
recognises every password, so do not save one.
- **Low battery and eye rest.** The pet speaks up once when a laptop reaches
20% unplugged (on by default; it re-arms after charging). The optional 20-20-20 nudge reminds you to look away every 20
minutes, and skips meetings, quiet hours and time you are away.
Expand Down
5 changes: 5 additions & 0 deletions src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const { isSpecies, coatsFor, defaultCoatIndex } = require('./pets');
const { MAX_THEMES } = require('./themes');
const { normalizeShortcuts } = require('./tools/shortcuts');
const { normalizeTodos } = require('./tools/todos');
const { normalizeSnippets } = require('./tools/snippets');
const { isSupported: isLanguage, AUTO: AUTO_LANGUAGE } = require('./i18n');

// The settings file format. Bump it when a change needs more than normalize()
Expand Down Expand Up @@ -83,6 +84,9 @@ const DEFAULTS = {
shortcuts: [], // [{ id, label, target }] validated by tools/shortcuts.js
},
todos: { day: '', items: [], nudged: '' }, // today's list, see tools/todos.js
// Saved text, copied back with ";name" in the launcher: [{ name, text }]. Only
// the launcher writes it: settings:save drops this key (src/main/settings-ipc.js).
snippets: [],
};

// The launcher hotkeys offered in Settings. A fixed list rather than free text, so
Expand Down Expand Up @@ -212,6 +216,7 @@ function normalize(cfg) {
};
})(),
todos: normalizeTodos(c.todos),
snippets: normalizeSnippets(c.snippets),
reminders: reminders.reduce((out, r) => {
if (!r || typeof r !== 'object') return out;
const hhmm = String(r.hhmm || '');
Expand Down
1 change: 1 addition & 0 deletions src/launcher-icons.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
file: [P('M6 3h8l5 5v13H6z'), P('M14 3v5h5')],
app: [R(4, 4, 7, 7), R(13, 4, 7, 7), R(4, 13, 7, 7), R(13, 13, 7, 7)],
text: [P('M5 7V5h14v2'), P('M12 5v14'), P('M9 19h6')],
snippet: [P('M6 3h12v18l-6-4-6 4z'), P('M9.5 8h5'), P('M9.5 11.5h3')],
info: [C(12, 12, 9), P('M12 11v5'), P('M12 8h.01')],
};

Expand Down
5 changes: 3 additions & 2 deletions src/launcher.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
--kbd: rgba(255, 255, 255, .08);
--accent: #e8943c; --accent-soft: rgba(232, 148, 60, .18);
--c-link: #6aa9ff; --c-folder: #f0b54a; --c-app: #b58cff; --c-file: #9fb3c8; --c-mail: #ff8a80;
--c-calc: #7fd08a; --c-time: #d49bff; --c-todo: #e8943c; --c-note: #f2cf5b; --c-sys: #c3c8d4; --c-search: #6aa9ff; --c-text: #5fc9c0;
--c-calc: #7fd08a; --c-time: #d49bff; --c-todo: #e8943c; --c-note: #f2cf5b; --c-sys: #c3c8d4; --c-search: #6aa9ff; --c-text: #5fc9c0; --c-snippet: #f08fb0;
--shadow: 0 18px 50px rgba(0, 0, 0, .45);
}
@media (prefers-color-scheme: light) {
Expand All @@ -38,7 +38,7 @@
--kbd: rgba(0, 0, 0, .06);
--accent-soft: rgba(232, 148, 60, .22);
--c-link: #2f74e0; --c-folder: #c98a12; --c-app: #7b4fd6; --c-file: #5d7288; --c-mail: #d4473b;
--c-calc: #2f9447; --c-time: #9a4fd6; --c-todo: #c9721f; --c-note: #b08a0e; --c-sys: #5a6070; --c-search: #2f74e0; --c-text: #1f8f88;
--c-calc: #2f9447; --c-time: #9a4fd6; --c-todo: #c9721f; --c-note: #b08a0e; --c-sys: #5a6070; --c-search: #2f74e0; --c-text: #1f8f88; --c-snippet: #c2456f;
--shadow: 0 18px 50px rgba(0, 0, 0, .18);
}
}
Expand Down Expand Up @@ -89,6 +89,7 @@
.row[data-icon="timer"] { --k: var(--c-time); } .row[data-icon="todo"] { --k: var(--c-todo); }
.row[data-icon="note"], .row[data-icon="notes"] { --k: var(--c-note); }
.row[data-icon="text"] { --k: var(--c-text); }
.row[data-icon="snippet"] { --k: var(--c-snippet); }

.txt { min-width: 0; }
.t { font-size: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
Expand Down
24 changes: 22 additions & 2 deletions src/locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,15 @@
"cmd.help.title": "Was kann ich eingeben?",
"cmd.help.sub": "Beispiele zum Ausprobieren",
"cmd.help.keys": "hilfe beispiele befehle wie tipps",
"cmd.help.calc.sub": "Rechne etwas aus. Enter kopiert das Ergebnis",
"cmd.help.convert.sub": "Rechnet Längen, Gewichte, Temperaturen und Dateigrößen um",
"cmd.help.calc.sub": "Rechnen und umrechnen, etwa 5 km in mi. Enter kopiert das Ergebnis",
"cmd.help.timer.ex": "10m Tee",
"cmd.help.timer.sub": "Startet einen Timer. Auch 1h30m oder timer 90s",
"cmd.help.todo.ex": "todo Zahnarzt anrufen",
"cmd.help.todo.sub": "Kommt auf die Liste für heute. \"done 1\" hakt die erste ab",
"cmd.help.note.ex": "note der WLAN-Code hängt am Kühlschrank",
"cmd.help.note.sub": "Speichert eine Zeile. \"open notes\" öffnet sie",
"cmd.help.snippet.ex": "save gruss",
"cmd.help.snippet.sub": "Merkt sich den kopierten Text. Mit ;gruss holst du ihn zurück",
"cmd.help.search.ex": "g beste Pizza in der Nähe",
"cmd.help.search.sub": "Sucht im Web. Auch ddg oder b",
"cmd.help.text.sub": "Kopierten Text richten: upper, lower, title, plain, one line, count",
Expand Down Expand Up @@ -85,6 +86,7 @@
"hint.done": "Erledigen",
"hint.undo": "Rückgängig",
"hint.try": "Probieren",
"hint.forget": "Vergessen",

"calc.sub": "Enter kopiert das Ergebnis",
"calc.bad.title": "Das kann ich nicht ausrechnen",
Expand All @@ -96,6 +98,17 @@
"note.saveTitle": "Als Notiz speichern: {text}",
"note.sub": "Fügt deiner Notizdatei eine Zeile hinzu",
"clip.sub": "Erneut kopieren",
"snippet.none.title": "Noch keine Textbausteine",
"snippet.none.sub": "Kopier einen Text und tippe save und einen Namen, etwa save gruss",
"snippet.save.title": "Kopierten Text als ;{name} speichern",
"snippet.save.replace": ";{name} durch den kopierten Text ersetzen",
"snippet.save.sub": "Tippe jederzeit ;{name}, um ihn wieder zu kopieren",
"snippet.badName.title": "Der Name eines Textbausteins ist ein Wort",
"snippet.badName.sub": "Buchstaben und Ziffern, höchstens 24, etwa gruss oder adresse",
"snippet.forget.title": ";{name} vergessen",
"snippet.forget.sub": "Löscht den gespeicherten Text",
"snippet.missing.title": ";{name} gibt es nicht",
"snippet.missing.sub": "Tippe ;, um deine Textbausteine zu sehen",

"todo.item.sub": "Aufgabe {n}",
"todo.item.subDone": "Aufgabe {n}, erledigt",
Expand Down Expand Up @@ -132,6 +145,13 @@
"say.text.none": "Kopier erst etwas Text und frag mich dann noch mal.",
"say.text.tooBig": "Das ist zu viel Text für mich.",
"say.text.count": "Wörter: {words}. Zeichen: {chars}. Zeilen: {lines}.",
"say.snippet.copied": ";{name} kopiert. Füg es ein, wo du willst.",
"say.snippet.saved": "Gespeichert. Mit ;{name} holst du es zurück.",
"say.snippet.forgot": ";{name} ist vergessen.",
"say.snippet.gone": "Diesen Textbaustein gibt es nicht mehr.",
"say.snippet.secret": "Das sieht nach einem Schlüssel oder Token aus, das merke ich mir nicht.",
"say.snippet.tooBig": "Das ist zu lang für einen Textbaustein.",
"say.snippet.full": "Bei {max} Textbausteinen ist Schluss. Vergiss erst einen.",
"say.awake.on": "Ich halte den Bildschirm wach. Schalte es im Infobereich oder hier wieder aus.",
"say.awake.off": "Der Bildschirm darf wieder schlafen.",
"say.clipboard.on": "Zwischenablage-Verlauf an. Nur im Arbeitsspeicher, nie gespeichert.",
Expand Down
24 changes: 22 additions & 2 deletions src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,15 @@
"cmd.help.title": "What can I type?",
"cmd.help.sub": "Examples you can try",
"cmd.help.keys": "help examples commands how tips",
"cmd.help.calc.sub": "Do a sum. Enter copies the answer",
"cmd.help.convert.sub": "Convert length, weight, temperature and file sizes",
"cmd.help.calc.sub": "Sums and conversions, like 5 km in mi. Enter copies the answer",
"cmd.help.timer.ex": "10m tea",
"cmd.help.timer.sub": "Start a timer. Also 1h30m or timer 90s",
"cmd.help.todo.ex": "todo call the dentist",
"cmd.help.todo.sub": "Add to today's list. \"done 1\" ticks the first one",
"cmd.help.note.ex": "note the wifi code is on the fridge",
"cmd.help.note.sub": "Save a line. \"open notes\" reads them back",
"cmd.help.snippet.ex": "save sig",
"cmd.help.snippet.sub": "Keeps the text you copied. Type ;sig to get it back",
"cmd.help.search.ex": "g best pizza near me",
"cmd.help.search.sub": "Search the web. Also ddg or b",
"cmd.help.text.sub": "Fix text you copied: upper, lower, title, plain, one line, count",
Expand Down Expand Up @@ -85,6 +86,7 @@
"hint.done": "Done",
"hint.undo": "Undo",
"hint.try": "Try",
"hint.forget": "Forget",

"calc.sub": "Enter copies the answer",
"calc.bad.title": "Not a sum I can do",
Expand All @@ -96,6 +98,17 @@
"note.saveTitle": "Save as a note: {text}",
"note.sub": "Adds a line to your notes file",
"clip.sub": "Copy again",
"snippet.none.title": "No snippets yet",
"snippet.none.sub": "Copy some text, then type save and a name, like save sig",
"snippet.save.title": "Save the copied text as ;{name}",
"snippet.save.replace": "Replace ;{name} with the copied text",
"snippet.save.sub": "Type ;{name} any time to copy it again",
"snippet.badName.title": "A snippet name is one word",
"snippet.badName.sub": "Letters and numbers, up to 24, like sig or addr",
"snippet.forget.title": "Forget ;{name}",
"snippet.forget.sub": "Deletes the saved text",
"snippet.missing.title": "There is no ;{name}",
"snippet.missing.sub": "Type ; to see your snippets",

"todo.item.sub": "To-do {n}",
"todo.item.subDone": "To-do {n}, done",
Expand Down Expand Up @@ -132,6 +145,13 @@
"say.text.none": "Copy some text first, then ask me again.",
"say.text.tooBig": "That is too much text for me to handle.",
"say.text.count": "Words: {words}. Characters: {chars}. Lines: {lines}.",
"say.snippet.copied": "Copied ;{name}. Paste it where you want.",
"say.snippet.saved": "Saved. Type ;{name} to get it back.",
"say.snippet.forgot": "Forgot ;{name}.",
"say.snippet.gone": "That snippet is gone.",
"say.snippet.secret": "That looks like a key or a token, so I will not keep it.",
"say.snippet.tooBig": "That is too long for a snippet.",
"say.snippet.full": "{max} snippets is my limit. Forget one first.",
"say.awake.on": "Keeping the screen awake. Turn it off from the tray or here.",
"say.awake.off": "The screen can sleep again.",
"say.clipboard.on": "Clipboard history on. Kept in memory only, never saved.",
Expand Down
24 changes: 22 additions & 2 deletions src/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,15 @@
"cmd.help.title": "¿Qué puedo escribir?",
"cmd.help.sub": "Ejemplos para probar",
"cmd.help.keys": "ayuda ejemplos comandos cómo consejos",
"cmd.help.calc.sub": "Haz una cuenta. Intro copia el resultado",
"cmd.help.convert.sub": "Convierte longitud, peso, temperatura y tamaños de archivo",
"cmd.help.calc.sub": "Cuentas y conversiones, como 5 km in mi. Intro copia el resultado",
"cmd.help.timer.ex": "10m té",
"cmd.help.timer.sub": "Inicia un temporizador. También 1h30m o timer 90s",
"cmd.help.todo.ex": "todo llamar al dentista",
"cmd.help.todo.sub": "Añade a la lista de hoy. \"done 1\" marca la primera",
"cmd.help.note.ex": "note la clave del wifi está en la nevera",
"cmd.help.note.sub": "Guarda una línea. \"open notes\" las abre",
"cmd.help.snippet.ex": "save firma",
"cmd.help.snippet.sub": "Guarda el texto que copiaste. Escribe ;firma para recuperarlo",
"cmd.help.search.ex": "g mejor pizza cerca de mí",
"cmd.help.search.sub": "Busca en la web. También ddg o b",
"cmd.help.text.sub": "Arregla el texto copiado: upper, lower, title, plain, one line, count",
Expand Down Expand Up @@ -85,6 +86,7 @@
"hint.done": "Hecho",
"hint.undo": "Deshacer",
"hint.try": "Probar",
"hint.forget": "Olvidar",

"calc.sub": "Intro copia el resultado",
"calc.bad.title": "Esa cuenta no la sé hacer",
Expand All @@ -96,6 +98,17 @@
"note.saveTitle": "Guardar como nota: {text}",
"note.sub": "Añade una línea a tu archivo de notas",
"clip.sub": "Copiar otra vez",
"snippet.none.title": "Aún no hay fragmentos",
"snippet.none.sub": "Copia un texto y escribe save y un nombre, como save firma",
"snippet.save.title": "Guardar el texto copiado como ;{name}",
"snippet.save.replace": "Reemplazar ;{name} por el texto copiado",
"snippet.save.sub": "Escribe ;{name} cuando quieras para copiarlo otra vez",
"snippet.badName.title": "El nombre de un fragmento es una sola palabra",
"snippet.badName.sub": "Letras y números, hasta 24, como firma o casa",
"snippet.forget.title": "Olvidar ;{name}",
"snippet.forget.sub": "Borra el texto guardado",
"snippet.missing.title": "No existe ;{name}",
"snippet.missing.sub": "Escribe ; para ver tus fragmentos",

"todo.item.sub": "Tarea {n}",
"todo.item.subDone": "Tarea {n}, hecha",
Expand Down Expand Up @@ -132,6 +145,13 @@
"say.text.none": "Copia primero un texto y vuelve a pedírmelo.",
"say.text.tooBig": "Es demasiado texto para mí.",
"say.text.count": "Palabras: {words}. Caracteres: {chars}. Líneas: {lines}.",
"say.snippet.copied": "Copiado ;{name}. Pégalo donde quieras.",
"say.snippet.saved": "Guardado. Escribe ;{name} para recuperarlo.",
"say.snippet.forgot": "Olvidé ;{name}.",
"say.snippet.gone": "Ese fragmento ya no existe.",
"say.snippet.secret": "Eso parece una clave o un token, así que no lo guardo.",
"say.snippet.tooBig": "Es demasiado largo para un fragmento.",
"say.snippet.full": "Mi límite son {max} fragmentos. Olvida uno primero.",
"say.awake.on": "Mantengo la pantalla encendida. Desactívalo desde la bandeja o desde aquí.",
"say.awake.off": "La pantalla ya puede apagarse.",
"say.clipboard.on": "Historial del portapapeles activado. Solo en memoria, nunca se guarda.",
Expand Down
Loading
Loading