Skip to content

Commit 85ca1fe

Browse files
authored
feat: Make Wordbook fully offline (#97)
2 parents 63f1997 + 02262b2 commit 85ca1fe

28 files changed

Lines changed: 1126 additions & 758 deletions

.github/workflows/CI.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ jobs:
1717
options: --privileged
1818
steps:
1919
- uses: actions/checkout@v4
20+
with:
21+
submodules: "true"
2022
- uses: flatpak/flatpak-github-actions/flatpak-builder@v6
2123
with:
2224
bundle: "wordbook-devel.flatpak"

.github/workflows/codeql.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,16 @@ jobs:
2727
uses: actions/checkout@v4
2828

2929
- name: Initialize CodeQL
30-
uses: github/codeql-action/init@v3
30+
uses: github/codeql-action/init@v4
3131
with:
3232
languages: ${{ matrix.language }}
3333
queries: +security-and-quality
3434
config-file: ./.github/codeql/codeql-config.yml
3535

3636
- name: Autobuild
37-
uses: github/codeql-action/autobuild@v3
37+
uses: github/codeql-action/autobuild@v4
3838

3939
- name: Perform CodeQL Analysis
40-
uses: github/codeql-action/analyze@v3
40+
uses: github/codeql-action/analyze@v4
4141
with:
4242
category: "/language:${{ matrix.language }}"

.gitmodules

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
[submodule "build-aux/flatpak/flatpak-builder-tools"]
2-
path = build-aux/flatpak/flatpak-builder-tools
3-
url = https://github.com/flatpak/flatpak-builder-tools.git
1+
[submodule "subprojects/wn"]
2+
path = subprojects/wn
3+
url = https://github.com/mufeedali/wn.git

.zed/settings.json

Lines changed: 0 additions & 7 deletions
This file was deleted.

README.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,12 @@ Wordbook
2525

2626
* GTK 4.6+ [Arch: `gtk4`]
2727
* libadwaita 1.7.0+ [Arch: `libadwaita`]
28-
* Python 3 [Arch: `python`]
28+
* Python 3.12+ [Arch: `python`]
2929
* Python modules:
30-
* Standalone WordNet Python module [Arch AUR: `python-wn`]
3130
* RapidFuzz [Arch: `python-rapidfuzz`]
3231
* Pydantic [Arch: `python-pydantic`]
3332
* Python GObject [Arch: `python-gobject`]
33+
* ONLY if using Python versions older than 3.14, backports.zstd [Arch: `python-backports-zstd`]
3434
* eSpeak-ng (For pronunciations and audio) [Arch: `espeak-ng`]
3535

3636
## Installation
@@ -47,7 +47,7 @@ This method can be used anywhere the Nix package manager is installed.
4747

4848
### Using distro-specific packages
4949

50-
Right now, Wordbook is only packaged for Arch through the AUR as [`wordbook`](https://aur.archlinux.org/packages/wordbook).
50+
Wordbook is packaged for Arch through the AUR as [`wordbook`](https://aur.archlinux.org/packages/wordbook).
5151

5252
On NixOS, Wordbook can be installed using the Nix package manager as shown above. Additionally, the following code can be added to your NixOS configuration file, usually located in `/etc/nixos/configuration.nix`.
5353

@@ -57,6 +57,16 @@ On NixOS, Wordbook can be installed using the Nix package manager as shown above
5757
];
5858
```
5959

60+
## Building from Source
61+
62+
To build Wordbook from source, use Meson:
63+
64+
```bash
65+
meson setup builddir
66+
meson compile -C builddir
67+
meson install -C builddir
68+
```
69+
6070
## Contributing
6171

6272
Contributions are welcome. There are many ways to contribute:

build-aux/flatpak/dev.mufeed.Wordbook.Devel.json

Lines changed: 50 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
"sdk": "org.gnome.Sdk",
66
"command": "wordbook",
77
"finish-args": [
8-
"--share=network",
98
"--socket=pulseaudio",
109
"--share=ipc",
1110
"--device=dri",
@@ -30,9 +29,10 @@
3029
"name": "pcaudiolib",
3130
"sources": [
3231
{
33-
"type": "archive",
34-
"url": "https://github.com/espeak-ng/pcaudiolib/archive/1.2.tar.gz",
35-
"sha256": "44b9d509b9eac40a0c61585f756d76a7b555f732e8b8ae4a501c8819c59c6619"
32+
"type": "git",
33+
"url": "https://github.com/espeak-ng/pcaudiolib.git",
34+
"tag": "1.3",
35+
"commit": "e907571bad7dee296fb56a409a0f7c5a0c57d38a"
3636
}
3737
]
3838
},
@@ -52,84 +52,47 @@
5252
"name": "python3-modules",
5353
"buildsystem": "simple",
5454
"build-commands": [
55-
"pip3 install --verbose --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} \"wn\" \"pydantic\" \"rapidfuzz\" --no-build-isolation"
55+
"pip3 install --verbose --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} \"pydantic\" \"rapidfuzz\" \"backports.zstd\" --no-build-isolation"
5656
],
5757
"sources": [
58-
{
59-
"type": "file",
60-
"url": "https://files.pythonhosted.org/packages/a1/ee/48ca1a7c89ffec8b6a0c5d02b89c305671d5ffd8d3c94acf8b8c408575bb/anyio-4.9.0-py3-none-any.whl",
61-
"sha256": "9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c"
62-
},
63-
{
64-
"type": "file",
65-
"url": "https://files.pythonhosted.org/packages/84/ae/320161bd181fc06471eed047ecce67b693fd7515b16d495d8932db763426/certifi-2025.6.15-py3-none-any.whl",
66-
"sha256": "2e0c7ce7cb5d8f8634ca55d2ba7e6ec2689a2fd6537d8dec1296a477a4910057"
67-
},
68-
{
69-
"type": "file",
70-
"url": "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl",
71-
"sha256": "63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86"
72-
},
73-
{
74-
"type": "file",
75-
"url": "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl",
76-
"sha256": "2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55"
77-
},
78-
{
79-
"type": "file",
80-
"url": "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl",
81-
"sha256": "d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad"
82-
},
83-
{
84-
"type": "file",
85-
"url": "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl",
86-
"sha256": "946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"
87-
},
88-
{
89-
"type": "file",
90-
"url": "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl",
91-
"sha256": "2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"
92-
},
93-
{
94-
"type": "file",
95-
"url": "https://files.pythonhosted.org/packages/6e/c2/61d3e0f47e2b74ef40a68b9e6ad5984f6241a942f7cd3bbfbdbd03861ea9/tomli-2.2.1-py3-none-any.whl",
96-
"sha256": "cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"
97-
},
98-
{
99-
"type": "file",
100-
"url": "https://files.pythonhosted.org/packages/65/a8/d6cc78f0cb30434207be11f09e0b2f1271eac6acac935807a0d23896b9d5/wn-0.13.0-py3-none-any.whl",
101-
"sha256": "ee1f2574078b592faa44ee254d4d8115ec951036800537f8915f201cb4d02541"
102-
},
10358
{
10459
"type": "file",
10560
"url": "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl",
10661
"sha256": "1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"
10762
},
10863
{
10964
"type": "file",
110-
"url": "https://files.pythonhosted.org/packages/69/e0/552843e0d356fbb5256d21449fa957fa4eff3bbc135a74a691ee70c7c5da/typing_extensions-4.14.0-py3-none-any.whl",
111-
"sha256": "a1514509136dd0b477638fc68d6a91497af5076466ad0fa6c338e44e359944af"
65+
"url": "https://files.pythonhosted.org/packages/7b/7b/22998f691dc6e0c7e6fa81d611eb4b1f6a72fb27327f322366d4a7ca8fb3/backports_zstd-1.3.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",
66+
"sha256": "ddc874638abf03ea1ff3b0525b4a26a8d0adf7cb46a448c3449f08e4abc276b3",
67+
"only-arches": ["aarch64"]
11268
},
11369
{
11470
"type": "file",
115-
"url": "https://files.pythonhosted.org/packages/17/69/cd203477f944c353c31bade965f880aa1061fd6bf05ded0726ca845b6ff7/typing_inspection-0.4.1-py3-none-any.whl",
116-
"sha256": "389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51"
71+
"url": "https://files.pythonhosted.org/packages/82/a2/ac67e79e137eb98aead66c7162bafe3cffcb82ef9cdeb6367ec18d88fbce/backports_zstd-1.3.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",
72+
"sha256": "9c4c7bcda5619a754726e7f5b391827f5efbe4bed8e62e9ec7490d42bff18aa6",
73+
"only-arches": ["x86_64"]
11774
},
11875
{
11976
"type": "file",
120-
"url": "https://files.pythonhosted.org/packages/6a/c0/ec2b1c8712ca690e5d61979dee872603e92b8a32f94cc1b72d53beab008a/pydantic-2.11.7-py3-none-any.whl",
121-
"sha256": "dde5df002701f6de26248661f6835bbe296a47bf73990135c7d07ce741b9623b"
77+
"url": "https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl",
78+
"sha256": "e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d"
12279
},
12380
{
12481
"type": "file",
125-
"url": "https://files.pythonhosted.org/packages/eb/3c/f4abd740877a35abade05e437245b192f9d0ffb48bbbbd708df33d3cda37/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
126-
"sha256": "9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d",
82+
"url": "https://files.pythonhosted.org/packages/15/df/a4c740c0943e93e6500f9eb23f4ca7ec9bf71b19e608ae5b579678c8d02f/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
83+
"sha256": "0cbaad15cb0c90aa221d43c00e77bb33c93e8d36e0bf74760cd00e732d10a6a0",
84+
"only-arches": ["aarch64"]
85+
},
86+
{
87+
"type": "file",
88+
"url": "https://files.pythonhosted.org/packages/cf/4e/35a80cae583a37cf15604b44240e45c05e04e86f9cfd766623149297e971/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
89+
"sha256": "406bf18d345822d6c21366031003612b9c77b3e29ffdb0f612367352aab7d586",
12790
"only-arches": ["x86_64"]
12891
},
12992
{
13093
"type": "file",
131-
"url": "https://files.pythonhosted.org/packages/6f/5e/a0a7b8885c98889a18b6e376f344da1ef323d270b44edf8174d6bce4d622/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
132-
"sha256": "0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef",
94+
"url": "https://files.pythonhosted.org/packages/59/cf/c3ac8c80d8ced6c1f99b5d9674d397ce5d0e9d0939d788d67c010e19c65f/rapidfuzz-3.13.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
95+
"sha256": "0da54aa8547b3c2c188db3d1c7eb4d1bb6dd80baa8cdaeaec3d1da3346ec9caa",
13396
"only-arches": ["aarch64"]
13497
},
13598
{
@@ -140,16 +103,39 @@
140103
},
141104
{
142105
"type": "file",
143-
"url": "https://files.pythonhosted.org/packages/59/cf/c3ac8c80d8ced6c1f99b5d9674d397ce5d0e9d0939d788d67c010e19c65f/rapidfuzz-3.13.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
144-
"sha256": "0da54aa8547b3c2c188db3d1c7eb4d1bb6dd80baa8cdaeaec3d1da3346ec9caa",
145-
"only-arches": ["aarch64"]
106+
"url": "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl",
107+
"sha256": "f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548"
108+
},
109+
{
110+
"type": "file",
111+
"url": "https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl",
112+
"sha256": "4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7"
113+
}
114+
]
115+
},
116+
{
117+
"name": "wordnet-data",
118+
"buildsystem": "simple",
119+
"build-commands": [
120+
"python3 scripts/generate-wn-db.py --source-file english-wordnet-2025-plus.xml.gz --output wn.db.zst",
121+
"WN_VERSION=$(git -C subprojects/wn rev-parse --short HEAD) && install -Dm644 wn.db.zst /app/share/wordbook/wn-${WN_VERSION}.db.zst"
122+
],
123+
"sources": [
124+
{
125+
"type": "dir",
126+
"path": "../../."
127+
},
128+
{
129+
"type": "file",
130+
"url": "https://github.com/globalwordnet/english-wordnet/releases/download/2025-edition/english-wordnet-2025-plus.xml.gz",
131+
"sha256": "31f4af16c54b532fd5484d4cc33aee588a31bb5b70683ae8197842fde5b586bc"
146132
}
147133
]
148134
},
149135
{
150136
"name": "wordbook",
151137
"buildsystem": "meson",
152-
"config-opts": ["-Dprofile=development"],
138+
"config-opts": ["-Dprofile=development", "-Dinstall_wn_db=false"],
153139
"sources": [
154140
{
155141
"type": "dir",
Lines changed: 0 additions & 1 deletion
This file was deleted.

data/meson.build

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,20 @@
11
subdir('icons')
22
subdir('resources')
33

4+
if get_option('install_wn_db')
5+
custom_target('wn-db',
6+
output: 'wn-@0@.db.zst'.format(wn_version),
7+
command: [
8+
find_program('python3'),
9+
join_paths(meson.project_source_root(), 'scripts', 'generate-wn-db.py'),
10+
'--output', '@OUTPUT@'
11+
],
12+
install: true,
13+
install_dir: pkgdatadir,
14+
console: true,
15+
)
16+
endif
17+
418
# Desktop file
519
desktop_conf = configuration_data()
620
desktop_conf.set('app-id', application_id)

data/resources/ui/window.blp

Lines changed: 10 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -185,23 +185,6 @@ template $WordbookWindow: Adw.ApplicationWindow {
185185
tightening-threshold: 500;
186186

187187
Adw.ViewStack main_stack {
188-
Adw.ViewStackPage {
189-
name: "download_page";
190-
191-
child: Adw.StatusPage download_status_page {
192-
title: _("Setting things up…");
193-
description: _("Downloading WordNet…");
194-
195-
child: Adw.Clamp {
196-
tightening-threshold: 200;
197-
198-
ProgressBar loading_progress {
199-
ellipsize: end;
200-
}
201-
};
202-
};
203-
}
204-
205188
Adw.ViewStackPage {
206189
name: "welcome_page";
207190

@@ -309,32 +292,19 @@ template $WordbookWindow: Adw.ApplicationWindow {
309292
}
310293

311294
Adw.ViewStackPage {
312-
name: "network_fail_page";
313-
314-
child: Adw.StatusPage network_fail_status_page {
315-
icon-name: "network-error-symbolic";
316-
title: _("Download failed");
295+
name: "db_error_page";
317296

318-
child: Box {
319-
spacing: 12;
320-
halign: center;
297+
child: Adw.StatusPage db_error_status_page {
298+
icon-name: "dialog-error-symbolic";
299+
title: _("Database not found");
300+
description: _("Installation is incomplete. Please reinstall Wordbook.");
321301

322-
Button retry_button {
323-
label: _("Retry");
302+
child: Button exit_button {
303+
label: _("Exit");
324304

325-
styles [
326-
"pill",
327-
"suggested-action",
328-
]
329-
}
330-
331-
Button exit_button {
332-
label: _("Exit");
333-
334-
styles [
335-
"pill",
336-
]
337-
}
305+
styles [
306+
"pill",
307+
]
338308
};
339309
};
340310
}

data/search_provider.in

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!@PYTHON@
22

33
# -*- coding: utf-8 -*-
4-
# SPDX-FileCopyrightText: 2016-2025 Mufeed Ali <me@mufeed.dev>
4+
# SPDX-FileCopyrightText: 2016-2026 Mufeed Ali <me@mufeed.dev>
55
# SPDX-License-Identifier: GPL-3.0-or-later
66

77

@@ -13,10 +13,12 @@ from gi.repository import GLib, Gio
1313
pkgdatadir = "@pkgdatadir@"
1414
localedir = "@localedir@"
1515

16+
sys.path.insert(1, pkgdatadir)
17+
1618
from wordbook import base, utils
1719
import wn
1820

19-
wn.config.data_directory = os.path.join(utils.WN_DIR)
21+
wn.config.data_directory = base.WN_DIR
2022
wn.config.allow_multithreading = True
2123

2224
dbus_interface_description = """

0 commit comments

Comments
 (0)