- Emacs Lisp 68.7%
- Python 25.2%
- JavaScript 5.2%
- Makefile 0.8%
|
Some checks failed
Repository structure / structure (push) Has been cancelled
`etaf-bili-open` was the only host: it owns a fixed buffer, mounts the shell itself and drove layout from a global window-size hook keyed to that buffer, so a desktop window or a floating panel could not show the client. Split the mount from the client: - `etaf-bili-create` returns a headless session and `etaf-bili-view` returns its View, matching the create/view pair every other ETAF application exposes. - The View adopts the buffer it is mounted into: the session, its change callback, the buffer-local session the keys and commands read, and the palette it declares on a host surface. - Layout follows the region the View is mounted into. The shell watches the committed viewport and lays out for it, so a panel or a desktop window reflows the card grid on resize; the global `window-size-change-functions` hook is gone and `etaf-bili-open` now mounts through the same path. - Unmounting stops transfers, requests and sign-in polling, makes pending replies inert and keeps the library, selection and account, so a session mounted again resumes where it was. `etaf-bili-open` still closes it fully. - The appearance is one cell shared by the gallery and the surface that frames it, so the `T` key and a panel's title-bar switch repaint both; the grid paints its own gaps so a palette change does not leave the previous surface between the cards. Validation: make check (structure, compile, 18 acceptance scenarios, API inventory) passes, including the new host-mount scenario. GUI: bili panel at 0.75x0.8 of the frame renders three cover columns, follows a resize to 150x38 (columns 58 -> 142, across 1 -> 3), switches dark/light from the title bar and by the shared cell, keeps its keys (`2` loads the ranking), clips deliberately below 64x28, and the desktop window renders the same View. |
||
|---|---|---|
| .githooks | ||
| .github/workflows | ||
| backends/bili | ||
| benchmarks | ||
| docs | ||
| examples | ||
| lisp | ||
| scripts | ||
| tests | ||
| .editorconfig | ||
| .gitignore | ||
| CHANGELOG.md | ||
| etaf-bili.el | ||
| LICENSE | ||
| Makefile | ||
| README.md | ||
ETAF Bili
Browse Bilibili inside Emacs: real cover cards, inline search, popular videos and rankings, with playback in the same buffer. Built with ETAF and its UI catalog.
What it does
- A responsive one-to-four-column cover gallery, with aspect-preserving thumbnails, readable two-line titles, creator, duration and compact counts.
- A catalog SearchField, channel Tabs and continuous wheel/trackpad scrolling. Metadata opens in a Drawer instead of reserving an empty sidebar.
- Skeleton cards during the first load, readable error/retry and empty states,
a scoped loading animation and a short selection transition. The shared
etaf-animation-enabledswitch disables motion. - Dark and light application palettes without modifying the user's frame, title bar or theme. Minimum usable window: 64 columns × 28 lines; smaller windows deliberately clip rather than compress the controls.
- Asynchronous public-feed requests and at most three concurrent cover downloads. Covers are cached locally; failure leaves a usable placeholder.
RETor a card's play button resolves its stream and opens the catalog media viewer with the CDN headers required for playback.
This is an unofficial public-video client, not the Bilibili open platform. Login, account libraries, comments, danmaku and entitlement management are not implemented. Available quality and playback depend on the server.
Install
Requires Emacs 29.1+, etaf, etaf-ui, ebox, ecss, curl, ffmpeg
(with ffprobe and ffplay for video metadata and sound) and Node.js for the
account backend bundled in backends/bili/.
(dolist (package '("ecss" "ebox" "etaf" "etaf-ui" "etaf-bili"))
(add-to-list 'load-path (expand-file-name package "/path/to/checkouts")))
(require 'etaf-bili)
(etaf-bili-open)
Use
| Key | Action |
|---|---|
/ |
Edit the in-page search field; Return submits, Escape keeps the draft |
| Arrow keys | Move through cards in two dimensions |
n / p |
Next / previous video (j / k also work in the default direction scheme) |
RET |
Activate the focused control or play the selected video |
| Wheel / trackpad | Scroll through the loaded results continuously |
1 / 2 |
Popular feed / ranking |
g |
Refresh |
i |
Open details |
T |
Switch application theme |
? / M-g |
Framework help / region navigation |
q |
Close the current modal first, then the client |
Embed in a panel or desktop
M-x etaf-bili-open is one host. A caller that already owns a window mounts
the same View instead:
(require 'etaf-bili)
(let ((buffer (get-buffer-create "*Bili*")))
(etaf-mount buffer (etaf-bili-view (etaf-bili-create)))
buffer)
The View lays out for the region it is mounted into and follows that region's
resizes, so a floating panel or a desktop window reflows the card grid instead
of clipping it. Mounting adopts the host buffer, which keeps the client's keys,
the inline search and the session-level commands working there. The first
mount loads the popular feed; unmounting stops transfers and polling but keeps
the library, selection and account, so a panel reopened with :keep-alive
resumes where it was. etaf-posframe-register-app opens it with
:create #'etaf-bili-create and :view #'etaf-bili-view.
Sign-in happens over the running client: the header's account chip reads
「登录」 until somebody signs in and then shows that account's name. Pressing it
(or M-x etaf-bili-login) paints the site's code in a centered panel while the
library stays visible underneath, dimmed; a phone confirms the scan, the panel
closes and the gallery reloads. Only the code method exists, because Bilibili
gates its SMS endpoint behind a graphical captcha. M-x etaf-bili-account
reports who is signed in and M-x etaf-bili-logout signs out and clears those
cookies.
The media viewer owns playback keys while open: Space toggles playback,
Left/Right seek, m toggles sound, . cycles speed and n/p switch videos.
Documentation and checks
- Manual: workflows, caching, failure recovery and integration.
- Architecture: data ownership, scoped UI and lifecycle.
- Entry Commentary: authoritative supported API.
make test # offline public acceptance suite, including mounted catalog controls
make check # structure, byte compilation, acceptance and API boundaries
GUI scenarios live in scripts/etaf-bili-gui-scenarios.el; the workspace
performance driver loads benchmarks/performance-scenarios.el for the
bili.appearance and bili.scroll workloads. Screenshots and batch tests are not latency
certification; use the real GUI workflow in the manual.
