Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
- name: Setup Pages
uses: actions/configure-pages@v5
uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5
- name: Upload site artifact
uses: actions/upload-pages-artifact@v3
uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3
with:
path: ./site
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v5
uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5
37 changes: 33 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,17 @@ on:
branches: [main]
paths:
- '.github/releases/v*.md'
# Manual re-entry. `prepare` self-aborts once VERSION already matches, so
# without this a failed publish leaves no way to finish the release except
# hand-crafted recovery commits.
workflow_dispatch:
inputs:
version:
description: 'Version to publish, e.g. 0.11.8 (must have .github/releases/v<version>.md)'
required: true

permissions:
contents: write
actions: write
contents: read

concurrency:
group: droidwebdisplay-release
Expand All @@ -17,6 +24,9 @@ concurrency:
jobs:
prepare:
runs-on: ubuntu-24.04
timeout-minutes: 15
permissions:
contents: write
outputs:
version: ${{ steps.prepare.outputs.version }}
sha: ${{ steps.prepare.outputs.sha }}
Expand All @@ -30,8 +40,21 @@ jobs:
shell: bash
run: |
set -euo pipefail
request=$(git diff --name-only HEAD^ HEAD -- '.github/releases/v*.md' | head -n 1)
test -n "$request"
if [ -n "${{ github.event.inputs.version }}" ]; then
request=".github/releases/v${{ github.event.inputs.version }}.md"
test -f "$request"
else
# head -n 1 silently published only the alphabetically-first file and
# could select an OLD request file touched by an unrelated edit,
# attempting a version downgrade. Require exactly one added file.
mapfile -t requests < <(git diff --name-only --diff-filter=A HEAD^ HEAD -- '.github/releases/v*.md')
if [ "${#requests[@]}" -ne 1 ]; then
echo "expected exactly one added release request, got ${#requests[@]}: ${requests[*]:-none}" >&2
exit 1
fi
request="${requests[0]}"
test -f "$request"
fi
file=$(basename "$request")
version=${file#v}
version=${version%.md}
Expand Down Expand Up @@ -121,6 +144,12 @@ jobs:
publish:
needs: prepare
runs-on: ubuntu-24.04
# Bounded so a hung smoke job cannot hold the droidwebdisplay-release
# concurrency slot for the six-hour default and block every later release.
timeout-minutes: 60
permissions:
contents: write
actions: write
env:
GH_TOKEN: ${{ github.token }}
RELEASE_VERSION: ${{ needs.prepare.outputs.version }}
Expand Down
30 changes: 20 additions & 10 deletions apps/web-client/dist-manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,23 +70,33 @@
},
{
"path": "assets/browser-support.js",
"bytes": 671,
"sha256": "010a0b76cbe8bb6ae9e20ff5a60836b4fcfe94010678ee09fcaf349380675529"
"bytes": 1444,
"sha256": "1a67546561cd6236156c8282187e9324d176ae7922d896a24de822647abcd37a"
},
{
"path": "assets/browser-support.js.map",
"bytes": 719,
"sha256": "412b951eb2bbf8b3614024506c288498b5033e62c07a49385cd754101f0e8d74"
},
{
"path": "assets/clipboard-status.d.ts",
"bytes": 212,
"sha256": "3098fe0bb9f107c24d91673af1024d329553fa16922caf965f92f86b93b72b6d"
},
{
"path": "assets/clipboard-status.js",
"bytes": 864,
"sha256": "509cb41e03eb47e68b55bed5f2aac9158b7a177b4d4da9209b9b7c6be8abba50"
},
{
"path": "assets/controller.d.ts",
"bytes": 4252,
"sha256": "9d4db1417756dee4ba4d7681428a0b0e0be01a042f317b67d879aeab3e6ded4a"
},
{
"path": "assets/controller.js",
"bytes": 57121,
"sha256": "35577dbe1abb009a81530d785c6243c7f79947c8b5d0bc3b81d4c0f3cc7ee230"
"bytes": 57213,
"sha256": "9e2df97ba6f1876070322b09adec3284477b9983c466fa1a791a4c469ff56d63"
},
{
"path": "assets/controller.js.map",
Expand Down Expand Up @@ -130,8 +140,8 @@
},
{
"path": "assets/main.js",
"bytes": 14522,
"sha256": "746ee71599bdc6625c5eccaecef8869ebd3b17daf434a490e7830635f7b59b3f"
"bytes": 21120,
"sha256": "a2946a8f334091a636c56410183bcb45502c66408aac59ee8ede8e3ca9139af3"
},
{
"path": "assets/main.js.map",
Expand Down Expand Up @@ -235,13 +245,13 @@
},
{
"path": "droidwebdisplay-main-drawer.css",
"bytes": 5670,
"sha256": "fdf37a0bcb9ad994d2771f5ae8c6aa8f1871f401a206d28e76e62df1fa4bc0aa"
"bytes": 5917,
"sha256": "dd8ae94da10bcd2ef6596f81cbf49da938cde5e7403b0fdb4430a0ef5bdd57f2"
},
{
"path": "droidwebdisplay-main-drawer.js",
"bytes": 26484,
"sha256": "57291e2c349f95159d731dd90010f42bf0748fc019a4c32e922d6fed72af097d"
"bytes": 26302,
"sha256": "18214ff7a6bb60fb75e5b31aaa59e178cf47d5183c170ccdff0c2ae7abc45c6e"
},
{
"path": "favicon.svg",
Expand Down
6 changes: 6 additions & 0 deletions apps/web-client/dist/assets/clipboard-status.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export declare const CLIPBOARD_STATUS: {
readonly copying: "Copying";
readonly copied: "Clipboard copied";
readonly received: "Clipboard received";
readonly notConfirmed: "Copy not confirmed";
};
19 changes: 19 additions & 0 deletions apps/web-client/dist/assets/clipboard-status.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/** Status headlines shared between the controller and the copy write-through.
*
* `bindAndroidCopyWriteThrough` in main.ts has to perform
* `navigator.clipboard.writeText` inside the click or keypress that asked for
* the copy, because that write needs transient user activation. It therefore
* watches the status line for the controller's reply instead of awaiting a
* promise across the gesture boundary.
*
* That makes these four strings a contract between the two modules, not display
* copy: rewording one at a call site silently stops the Copy button writing to
* the PC clipboard, with no test failure and no console error. Change them here
* so both sides move together.
*/
export const CLIPBOARD_STATUS = {
copying: "Copying",
copied: "Clipboard copied",
received: "Clipboard received",
notConfirmed: "Copy not confirmed",
};
9 changes: 5 additions & 4 deletions apps/web-client/dist/assets/controller.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

69 changes: 54 additions & 15 deletions apps/web-client/dist/assets/main.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion apps/web-client/dist/droidwebdisplay-main-drawer.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
@import url("./droidwebdisplay-main-drawer-core.css");
/* Versioned to match the ?v= on the entry sheet in index.html. Without it the
531 lines of drawer layout below sit outside cache-busting, and a stale
copy after an upgrade renders every drawer group stacked and visible. */
@import url("./droidwebdisplay-main-drawer-core.css?v=0.11.2-native5");

/* Header brand/status lockup v2.
Keep the brand on one header row, remove the legacy rail-style pseudo logo,
Expand Down
15 changes: 5 additions & 10 deletions apps/web-client/dist/droidwebdisplay-main-drawer.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,11 @@
const label = root().querySelector(`[data-group="${group}"] .gb-rail-label`)?.textContent || 'Tools';
const title = root().querySelector('.gb-drawer-title'); if (title) title.textContent = label;
drawer()?.classList.add('gb-open'); drawer()?.setAttribute('aria-hidden', 'false');
if (group === 'clipboard') {
// controller.ts historically focused the fallback textarea one frame after
// opening Clipboard. That makes the global Ctrl+V route treat the paste as
// page editing instead of Android input. Return focus to the mirrored screen
// after that callback has run; users can still click the textarea explicitly.
window.requestAnimationFrame(() => window.requestAnimationFrame(() => {
const screen = document.getElementById('screen');
if (screen instanceof HTMLCanvasElement) screen.focus();
}));
}
// No focus handling here on purpose. This used to force focus back to the
// mirrored screen because controller.ts focused the fallback textarea when
// the Clipboard group opened; that listener was deleted when Ctrl+V moved to
// a document-level paste handler, so the guard now only steals focus from a
// user typing into the textarea and injects their keystrokes into Android.
}
function closeDrawer() {
if (pinned || !root()) return;
Expand Down
19 changes: 19 additions & 0 deletions apps/web-client/src/clipboard-status.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/** Status headlines shared between the controller and the copy write-through.
*
* `bindAndroidCopyWriteThrough` in main.ts has to perform
* `navigator.clipboard.writeText` inside the click or keypress that asked for
* the copy, because that write needs transient user activation. It therefore
* watches the status line for the controller's reply instead of awaiting a
* promise across the gesture boundary.
*
* That makes these four strings a contract between the two modules, not display
* copy: rewording one at a call site silently stops the Copy button writing to
* the PC clipboard, with no test failure and no console error. Change them here
* so both sides move together.
*/
export const CLIPBOARD_STATUS = {
copying: "Copying",
copied: "Clipboard copied",
received: "Clipboard received",
notConfirmed: "Copy not confirmed",
} as const;
Loading
Loading