Skip to content
Open
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
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,8 @@ node_modules/

# local flatpak build
/repo
/.flatpak-builder/
/.flatpak-builder/

# local nix build
/build/
/result
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,18 @@ written in GJS and uses GTK4.

</div>

## Tray icon

Sticky Notes provides a tray icon with quick access to all your notes. It uses
the freedesktop [StatusNotifierItem][spec] specification, which KDE Plasma and
most other desktop environments support out of the box. GNOME Shell does not:
to see the tray icon on GNOME, install and enable the
[AppIndicator and KStatusNotifierItem Support][extension] extension.
Without it, the app still works normally — the tray icon just won't be shown.

[spec]: https://www.freedesktop.org/wiki/Specifications/StatusNotifierItem/
[extension]: https://extensions.gnome.org/extension/615/appindicator-support/

## Installation

### From Flathub
Expand Down
1 change: 1 addition & 0 deletions build-aux/flatpak/com.vixalien.sticky.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"--device=dri",
"--socket=wayland",
"--socket=fallback-x11",
"--talk-name=org.kde.StatusNotifierWatcher",
"--env=GJS_DISABLE_JIT=1"
],
"cleanup": [
Expand Down
7 changes: 7 additions & 0 deletions data/com.vixalien.sticky.appdata.xml.in.in
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,14 @@
<li>notes are restored if they were open when the application was closed</li>
<li>changing color of notes</li>
<li>dark theme support</li>
<li>tray icon with quick access to all notes</li>
</ul>
<p>
The tray icon requires a status notifier host: it works out of the box on
KDE Plasma and most other desktop environments, but on GNOME you need to
install and enable the "AppIndicator and KStatusNotifierItem Support"
extension to see it.
</p>
</description>
<screenshots>
<screenshot type="default">
Expand Down
27 changes: 27 additions & 0 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

96 changes: 96 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
{
description = "Sticky Notes — GNOME sticky notes app (with tray icon)";

inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
};

outputs = { self, nixpkgs }:
let
systems = [ "x86_64-linux" "aarch64-linux" ];
forAllSystems = f: nixpkgs.lib.genAttrs systems (
system: f system nixpkgs.legacyPackages.${system}
);
in
{
packages = forAllSystems (system: pkgs: {
# reuses the nixpkgs sticky-notes derivation (same version, same
# yarn.lock, so the yarn offline cache hash still applies) but builds
# from this source tree
default = pkgs.sticky-notes.overrideAttrs (old: {
version = "${old.version}-dev";
src = self;
});
});

apps = forAllSystems (system: pkgs: {
# nix run — build and launch the app
default = {
type = "app";
program = "${self.packages.${system}.default}/bin/com.vixalien.sticky";
meta.description = "Run Sticky Notes built from this source tree";
};

# nix run .#install-appindicator — link the AppIndicator GNOME Shell
# extension (a StatusNotifierWatcher host) into the user profile, so
# the tray icon can be tested with and without it
install-appindicator = {
type = "app";
program = toString (pkgs.writeShellScript "install-appindicator" ''
set -eu
uuid=appindicatorsupport@rgcjonas.gmail.com
src=${pkgs.gnomeExtensions.appindicator}/share/gnome-shell/extensions/$uuid
dest="$HOME/.local/share/gnome-shell/extensions/$uuid"
mkdir -p "$(dirname "$dest")"
ln -sfT "$src" "$dest"
echo "AppIndicator extension linked into $dest"
echo
echo "GNOME Shell only picks up new extensions on login:"
echo "log out and back in, then run:"
echo
echo " gnome-extensions enable $uuid"
echo
echo "Toggle it off/on with gnome-extensions disable/enable (or the"
echo "Extensions app) to compare behavior; remove it again with:"
echo
echo " rm '$dest'"
'');
meta.description = "Install the AppIndicator extension for the current user";
};
});

devShells = forAllSystems (system: pkgs: {
default = pkgs.mkShell {
# meson/ninja/yarn/gjs toolchain and GTK/libadwaita libraries, with
# the GI and GSettings setup hooks, exactly as the package build
inputsFrom = [ self.packages.${system}.default ];

packages = [
pkgs.gjs # on PATH for running the app uninstalled
pkgs.nodejs # yarn typecheck
pkgs.libxml2 # xmllint, silences a gresource warning

# build and run the app from the working tree:
# sticky-run [args...]
# GJS only registers the compiled-in source gresource for
# installed apps, so overlay the resource path onto the build dir
(pkgs.writeShellScriptBin "sticky-run" ''
set -eu
[ -d build ] || meson setup build
ninja -C build
cd build
export GSETTINGS_SCHEMA_DIR="$PWD/data"
export G_RESOURCE_OVERLAYS="/com/vixalien/sticky/js=$PWD/src"
exec gjs -m src/com.vixalien.sticky "$@"
'')
];

shellHook = ''
echo "Sticky Notes dev shell"
echo " sticky-run build and run from the working tree"
echo " yarn typecheck check TypeScript (needs the gi-types submodule)"
'';
};
});
};
}
1 change: 1 addition & 0 deletions po/POTFILES
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ src/card.ts
src/main.ts
src/notes.ts
src/styleselector.ts
src/trayicon.ts
src/util.ts
src/view.ts
src/window.ts
28 changes: 26 additions & 2 deletions src/application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import Gtk from "gi://Gtk?version=4.0";
import Gdk from "gi://Gdk?version=4.0";

import { StickyNotes } from "./notes.js";
import { Note, settings } from "./util.js";
import { compare_notes_newest_first, Note, settings } from "./util.js";
import {
delete_note,
load_notes,
Expand All @@ -40,10 +40,13 @@ import {
save_notes,
} from "./store.js";
import { Window } from "./window.js";
import { TrayIcon } from "./trayicon.js";

export class Application extends Adw.Application {
private window: StickyNotes | null = null;
private note_windows: Window[] = [];
private tray: TrayIcon | null = null;
private tray_holding = false;

static {
GObject.registerClass(this);
Expand Down Expand Up @@ -195,7 +198,7 @@ export class Application extends Adw.Application {

if (!has_one_open) {
const last_open_note = this.notes_array()
.sort((a, b) => b.modified.compare(a.modified))[0];
.sort(compare_notes_newest_first)[0];

if (has_one_open) {
this.show_note(last_open_note.uuid);
Expand Down Expand Up @@ -539,9 +542,30 @@ export class Application extends Adw.Application {
window.present();
}

search_notes() {
this.all_notes();
this.window?.focus_search();
}

vfunc_startup() {
super.vfunc_startup();

this.tray = new TrayIcon(this);
// keep the application running without windows while the tray icon is
// shown, so that it stays reachable from the tray
this.tray.registered_changed = (registered) => {
if (registered === this.tray_holding) return;

if (registered) {
this.hold();
} else {
this.release();
}

this.tray_holding = registered;
};
this.tray.start();

const style_manager = Adw.StyleManager.get_default();
function setColorScheme() {
const color_scheme = settings.get_int("color-scheme");
Expand Down
1 change: 1 addition & 0 deletions src/com.vixalien.sticky.src.gresource.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<file>styleselector.js</file>
<file>store.js</file>
<file>themeselector.js</file>
<file>trayicon.js</file>
<file>view.js</file>
<file>window.js</file>
<file>util.js</file>
Expand Down
1 change: 1 addition & 0 deletions src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ sources = [
'styleselector.ts',
'store.ts',
'themeselector.ts',
'trayicon.ts',
'view.ts',
'window.ts',
'util.ts'
Expand Down
14 changes: 8 additions & 6 deletions src/notes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import Adw from "gi://Adw";

import type { Application } from "./application.js";
import { StickyNoteCard } from "./card.js";
import { Note, settings } from "./util.js";
import { compare_notes_newest_first, Note, settings } from "./util.js";

import { ThemeSelector } from "./themeselector.js";

Expand Down Expand Up @@ -156,11 +156,9 @@ export class StickyNotes extends Adw.ApplicationWindow {
filter,
);

this.sorter = Gtk.CustomSorter.new((note1, note2) => {
const date1 = (note1 as Note).modified;
const date2 = (note2 as Note).modified;
return date2.compare(date1);
});
this.sorter = Gtk.CustomSorter.new((note1, note2) =>
compare_notes_newest_first(note1 as Note, note2 as Note)
);

const sorter_model = Gtk.SortListModel.new(filter_model, this.sorter);

Expand Down Expand Up @@ -199,6 +197,10 @@ export class StickyNotes extends Adw.ApplicationWindow {
popover.add_child(new ThemeSelector(), "themeswitcher");
}

focus_search() {
this._search_entry.grab_focus();
}

set_status() {
if (this.last_model.get_n_items() > 0) {
this.set_visible_child(this._notes_box);
Expand Down
Loading