htmlviewer-directediting: HTML rendering in Nextcloud iOS app

- htmlviewer: IEditor + Bridge + srcdoc iframe template + content controller
- text app: open() bridges text/html to htmlviewer template
- idempotent install.sh for re-deployment after app updates
- iPhone-tested 2026-09-11
This commit is contained in:
Hermes
2026-09-11 12:19:44 +00:00
commit 88d618b58a
20 changed files with 1245 additions and 0 deletions
Executable
+77
View File
@@ -0,0 +1,77 @@
#!/usr/bin/env bash
# htmlviewer-directediting installer
# Applies the HTML-in-iOS-App patches to a Nextcloud container.
# Usage: ./install.sh <container-name> [custom_apps-path-in-container]
# default container: nextcloud1-app-1
# Idempotent: safe to re-run after app updates.
set -euo pipefail
CONTAINER="${1:-nextcloud1-app-1}"
APP="/var/www/html/custom_apps/htmlviewer"
TEXT="/var/www/html/apps/text/lib/DirectEditing/TextDirectEditor.php"
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
echo "=== htmlviewer-directediting installer ==="
echo "Container: $CONTAINER"
# 0. Sanity
docker exec "$CONTAINER" test -d "$APP" || { echo "ERROR: htmlviewer app not found at $APP"; exit 1; }
# 1. Backup text editor (first run only)
if ! docker exec "$CONTAINER" test -f /tmp/TextDirectEditor.php.bak-htmlproject; then
docker exec "$CONTAINER" cp "$TEXT" /tmp/TextDirectEditor.php.bak-htmlproject 2>/dev/null || \
docker exec "$CONTAINER" bash -c "cp $TEXT /tmp/TextDirectEditor.php.bak-htmlproject" || true
fi
# 2. Deploy htmlviewer files (from repo to container via /tmp)
TMPDIR_ON_HOST=$(mktemp -d)
cp patches/htmlviewer/*.php "$TMPDIR_ON_HOST/"
cp patches/text/TextDirectEditor.php "$TMPDIR_ON_HOST/TextDirectEditor-patched.php"
docker cp "$TMPDIR_ON_HOST/HtmlDirectEditor.php" "$CONTAINER:$APP/lib/DirectEditing/HtmlDirectEditor.php"
docker cp "$TMPDIR_ON_HOST/HtmlDirectEditorBridge.php" "$CONTAINER:$APP/lib/DirectEditing/HtmlDirectEditorBridge.php"
docker cp "$TMPDIR_ON_HOST/DirectController.php" "$CONTAINER:$APP/lib/Controller/DirectController.php"
docker cp "$TMPDIR_ON_HOST/RegisterDirectEditorListener.php" "$CONTAINER:$APP/lib/Listeners/RegisterDirectEditorListener.php"
docker cp "$TMPDIR_ON_HOST/directEditing-template.php" "$CONTAINER:$APP/templates/directEditing.php"
docker cp "$TMPDIR_ON_HOST/TextDirectEditor-patched.php" "$CONTAINER:/var/www/html/apps/text/lib/DirectEditing/TextDirectEditor.php"
docker exec "$CONTAINER" chown www-data:www-data \
"$APP/lib/DirectEditing/HtmlDirectEditor.php" \
"$APP/lib/DirectEditing/HtmlDirectEditorBridge.php" \
"$APP/lib/Controller/DirectController.php" \
"$APP/lib/Listeners/RegisterDirectEditorListener.php" \
"$APP/templates/directEditing.php" \
/var/www/html/apps/text/lib/DirectEditing/TextDirectEditor.php
rm -rf "$TMPDIR_ON_HOST"
# 3. Register in Application.php + routes.php (idempotent)
docker cp patches/htmlviewer/patch_app.py "$CONTAINER:/tmp/patch_app.py"
docker exec "$CONTAINER" python3 /tmp/patch_app.py
# 4. Text-app mimic list: remove text/html so iOS picks... (NO — text stays owner)
# NOTE: text/html must STAY in the text editor's mimetypes list so the
# iOS app (which only knows editor id "text") opens HTML via the bridge.
# If it was removed by an older version of this installer, re-add it.
docker exec "$CONTAINER" python3 - <<'PYEOF'
p='/var/www/html/apps/text/lib/DirectEditing/TextDirectEditor.php'
c=open(p).read()
if "'text/html'" not in c:
c=c.replace("\t\t\t'text/css',", "\t\t\t'text/css',\n\t\t\t'text/html',")
open(p,'w').write(c)
print('text/html re-added to TextDirectEditor mimetypes')
else:
print('text/html present in TextDirectEditor')
PYEOF
# 5. Lint + restart
for f in "$APP/lib/DirectEditing/HtmlDirectEditor.php" \
"$APP/lib/DirectEditing/HtmlDirectEditorBridge.php" \
"$APP/lib/Controller/DirectController.php" \
"$APP/lib/Listeners/RegisterDirectEditorListener.php" \
"$APP/templates/directEditing.php" \
/var/www/html/apps/text/lib/DirectEditing/TextDirectEditor.php; do
docker exec "$CONTAINER" php -l "$f"
done
echo "=== Restarting container ==="
docker restart "$CONTAINER"
echo "=== Done. Test: open an .html file in the iOS app (kill app first). ==="