aboutsummaryrefslogtreecommitdiffstats
path: root/bookmarks/README.md
blob: 61efb2a98e0e5be452f78b135ca94dc087e99ce1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# bookmarks

Firefox's bookmarks as a grid of cards across DP-1, grouped by folder, over
a dimmed screen. SUPER+b opens it, Escape or a click outside closes it.

Each card shows the favicon, the title, the host and, after a link check, a
badge: red for a link that is gone (404, 410, a host that no longer
resolves, a refused connection), yellow for one that may only be refusing a
script (403, 429, a timeout, a TLS error, a 5xx).

Type to filter (every word must match title, address or folder), arrows
and PageUp/PageDown to move. Enter opens the bookmark with `xdg-open`, so it
lands in the running Firefox profile rather than a new one. Tab shows
only the dead ones; Ctrl+R checks every link again.

The icon buttons sort, and Ctrl+S cycles them: Firefox's folder order,
newest first (headed by year), title (headed by letter), site, most visited,
and link state (dead, unsure, fine, not checked). Ties keep folder order.
Outside folder order each card names its folder.

The wheel scrolls three rows of cards a notch, set in the `MouseArea` over
the grid; Flickable's own step was a few pixels.

`bookmarks.py` builds the list on every opening, so a bookmark added in
Firefox shows the next time. It reads `places.sqlite` and `favicons.sqlite`
of the profile a running Firefox holds, found by its `lock` symlink's pid,
else the one with the largest `places.sqlite` (`BOOKMARKS_PROFILE` overrides
both). Firefox holds them in exclusive lock mode, so they are copied with
their `-wal` to a temporary directory and the copy is read: the log is where
Firefox puts recent changes, a deletion included, until a checkpoint.
Nothing is ever written to them: deleting a dead bookmark is done in Firefox.

Folders keep Firefox's order, toolbar first, but a folder's own bookmarks
come before its subfolders rather than interleaved with them. Tags are left
out. Favicons are extracted to `~/.cache/keystone/bookmarks/icons/`, named by
content hash; a bookmark with no icon of its own takes any icon Firefox holds
for the same host, and one with none at all shows the host's initial.

The link check (`bookmarks.py --links`) sends one request to every http(s)
bookmark, 32 at a time, HEAD and then GET if HEAD fails, and writes
`~/.cache/keystone/bookmarks/links.json`. It took 22s over 503 links. It runs
only when asked, and a site down at that moment reads dead until the next
check.

## Running

    qs -p ./bookmarks
    qs -p ./bookmarks ipc call bookmarks toggle

## Blur

Optional, in the Hyprland config:

    hl.layer_rule({
        name         = "blur-bookmarks",
        match        = { namespace = "^(keystone-bookmarks)$" },
        blur         = true,
        xray         = false,
        ignore_alpha = 0.1,
    })

## Check

    /usr/bin/python3 bookmarks/bookmarks.py --check