An app read the user's files with `std::fs`, which a browser does not have: there a page reaches a folder of the user's computer only through forge/web, which holds it through the File System Access API and answers asynchronously (forge/web/DESIGN.md, section 11). An app that builds for both, such as Crate, had no way to list, read or write a file in a browser, and a page's memory cannot hold a large file whole. ltk::files. Asynchronous operations on the user's files whose results reach the app as messages through its `ChannelSender`: `list`, `stat`, `read`, `read_range`, `write`, `open_write`, `create_dir`, `rename`, `remove`, `remove_all`, `copy`, `copy_all`, `mount` and `unmount`, each taking the sender and a `done` that turns the `io::Result` into a message. Results come in no set order, so an app that has moved on checks that one is still the one it waits for. Errors are the same `io::ErrorKind`s on every platform, `Interrupted` for a cancelled copy. `Entry` and `Metadata` give a file's kind, size and times, the access time natively only. `ltk::vfs` stays what reads an app's own resources. Natively. `std::fs` on one worker thread of ltk's, in the order the app asked (`files/native.rs`), and each copy on a thread of its own, so a long one holds nothing else up (`files/copy.rs`). A file written whole or through a `Writer` goes beside its target as a temporary file, synced and renamed over it on commit and removed if dropped before, so a file being written is never seen half done. `rename` never replaces what is at `to`, as in a browser. In a browser. Each operation is one of forge/web's `fs_*` requests over the app's connection (`platform/web/files.rs`), carrying a number its `fs_reply` answers with; contents travel as a `Uint8Array` beside the JSON, the second argument of the connection's `request` and of the client's event handler, so `on_event` now takes it. What is asked before the app has connected is sent once it has; on a page without a desktop, or once the connection has closed, it fails with `Unsupported`. forge/web's error codes become their `io::ErrorKind`s, and `fs_progress` reaches a copy's `progress`. Without the web backend, on wasm32 every operation fails with `Unsupported` (`files/unsupported.rs`). Chunks. Contents never travel whole unless they are small: a large file is read with `read_range` and written through a `Writer`, chunk by chunk, `files::CHUNK` (1 MiB) at a time, the next sent once the last is answered. A `Writer` dropped without `close` is aborted and the file left as it was; in a browser a new file shows empty until closed. A copy runs where the files are, its contents never passing through the app: it reports its progress every 100 ms, never replaces an existing file, and, cancelled through its `Operation` or failed, leaves nothing behind. Mounts and the desktop's notices. `mount` asks the browser for a folder of the user's computer, from the user's press, and `unmount` lets it go; natively both fail with `Unsupported`. `App::on_files_changed`, `App::on_mounts_changed` and `App::on_open_files` hear of forge/web's `fs_changed`, `fs_mounts` and `open_files`, which the web backend queues as page events; natively they are not called yet. Types. `files::mime_type( name )` gives a file's type by shared-mime-info's `globs2`, with its weights, its case-sensitive globs and fnmatch's `*`, `?` and bracket classes, from the resource directory's `mime/` first, then the user's and the system's. `scripts/android-assets.sh`, and so `web-assets.sh`, now copies shared-mime-info's `globs2` and `subclasses` into the tree's `mime/` (`MIME_DIR` overrides where from), so a page has them. ltk::web::shell_request. A shell message that waits for forge/web's reply, such as `get_window_thumbnail`: sent as `shell_send` sends one and answered at once with forge/web's reply as JSON, or `None` before the app has connected, since a request is not kept for later, and when forge/web replies nothing. A shell's requests that wait for an answer natively got none in a browser. `shell.rs` parses a message once for both, and `send` returns forge/web's reply. Tests cover writing and committing, aborting, listing, ranges, removing, copying a tree with its progress, a cancelled copy, a copy that would replace, and the globs. `CHANGELOG.md` describes the changes.
81 lines
2.3 KiB
Bash
Executable File
81 lines
2.3 KiB
Bash
Executable File
#!/bin/sh
|
|
# Build the `ltk/` tree an Android package carries under `assets/`: the
|
|
# themes, the font files their theme.json names by absolute path, the
|
|
# on-screen keyboard's layouts, and the MANIFEST that src/platform/android/assets.rs unpacks from, whose first
|
|
# line is a hash of the contents so a changed tree is unpacked again.
|
|
# web-assets.sh builds the same tree for a page through this script.
|
|
#
|
|
# Usage: scripts/android-assets.sh OUT_DIR [THEMES_DIR [THEME_ID...]]
|
|
# THEMES_DIR defaults to /usr/share/ltk/themes, THEME_ID to `default`.
|
|
# EXTRA_FONTS, space-separated paths, adds fonts the app itself reads from
|
|
# `ltk::resource_dir()/fonts`, such as a terminal's monospace face.
|
|
# KEYBOARDS_DIR defaults to the `keyboards/` next to this script's directory.
|
|
# MIME_DIR, shared-mime-info's directory, whose globs2, which
|
|
# `ltk::files::mime_type` reads from `mime/`, and subclasses are copied there,
|
|
# defaults to /usr/share/mime.
|
|
set -eu
|
|
|
|
keyboards=${KEYBOARDS_DIR:-$( cd "$( dirname "$0" )/.." && pwd )/keyboards}
|
|
|
|
if [ $# -lt 1 ]
|
|
then
|
|
echo "usage: $0 OUT_DIR [THEMES_DIR [THEME_ID...]]" >&2
|
|
exit 2
|
|
fi
|
|
out=$1
|
|
shift
|
|
themes=/usr/share/ltk/themes
|
|
if [ $# -gt 0 ]
|
|
then
|
|
themes=$1
|
|
shift
|
|
fi
|
|
[ $# -gt 0 ] || set -- default
|
|
|
|
root=$out/ltk
|
|
rm -rf "$root"
|
|
mkdir -p "$root/themes" "$root/fonts" "$root/keyboards"
|
|
cp "$keyboards"/*.json "$root/keyboards/"
|
|
|
|
for id in "$@"
|
|
do
|
|
cp -r "$themes/$id" "$root/themes/$id"
|
|
# ltk draws no cursor of its own on Android.
|
|
rm -rf "$root/themes/$id/cursors" "$root/themes/$id/cursor.theme"
|
|
grep -o '"path"[[:space:]]*:[[:space:]]*"/[^"]*"' "$themes/$id/theme.json" \
|
|
| sed 's/.*"\(\/[^"]*\)"$/\1/' \
|
|
| while read -r font
|
|
do
|
|
if [ -f "$font" ]
|
|
then
|
|
cp "$font" "$root/fonts/"
|
|
else
|
|
echo "android-assets: $font not found, skipped" >&2
|
|
fi
|
|
done
|
|
done
|
|
|
|
for font in ${EXTRA_FONTS:-}
|
|
do
|
|
cp "$font" "$root/fonts/"
|
|
done
|
|
|
|
mime=${MIME_DIR:-/usr/share/mime}
|
|
for table in globs2 subclasses
|
|
do
|
|
if [ -f "$mime/$table" ]
|
|
then
|
|
mkdir -p "$root/mime"
|
|
cp "$mime/$table" "$root/mime/$table"
|
|
else
|
|
echo "android-assets: $mime/$table not found, skipped" >&2
|
|
fi
|
|
done
|
|
|
|
cd "$root"
|
|
hash=$( find . -type f ! -name MANIFEST -print0 | LC_ALL=C sort -z | xargs -0 sha256sum | sha256sum | cut -d' ' -f1 )
|
|
{
|
|
printf '# %s\n' "$hash"
|
|
find . -type f ! -name MANIFEST | sed 's|^\./||' | LC_ALL=C sort
|
|
} > MANIFEST
|