From 280b5697ebf4c7aa5f46eeee940e2d4e2b145e8e Mon Sep 17 00:00:00 2001 From: aliabid94 Date: Fri, 7 Jul 2023 14:39:06 -0500 Subject: [PATCH] Mobile queue fixes (#4742) * changes * changes * changes * changes * changes * Styling for error, warning and info toasts (#4603) * create abstract toast component for info/warning/error * add icons * add light mode theming * add theme mode check and dark mode styles * update theme_mode on update * clean up render of toast content * replace dynamic css vars with toast type css selectors * tweak colours * change error pill border colour to align with toasts * formatting * fix failed test * rename icon files and clean up css * changes * changes * changes * changes * changes * changes * chanegs * changes * changes * changes * changes * changes * changes * changes * changes * changes * changes * changes * changes * changes * changes * changes * changes * changes * changes * changes * changes --------- Co-authored-by: Abubakar Abid Co-authored-by: Hannah --- CHANGELOG.md | 2 +- client/js/src/client.ts | 1 + client/js/src/types.ts | 1 + js/app/src/Blocks.svelte | 42 ++++++++++++++++++++++++++++++++++++++-- 4 files changed, 43 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 80bab74d15d7..f15a8fd9efa4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ No changes to highlight. ## Other Changes: -No changes to highlight. +- Warning on mobile that if a user leaves the tab, websocket connection may break. On broken connection, tries to rejoin queue and displays error conveying connection broke. By [@aliabid94](https://github.com/aliabid94) in [PR 4742](https://github.com/gradio-app/gradio/pull/4742) ## Breaking Changes: diff --git a/client/js/src/client.ts b/client/js/src/client.ts index dc02158398e4..2395e89a8359 100644 --- a/client/js/src/client.ts +++ b/client/js/src/client.ts @@ -478,6 +478,7 @@ export function api_factory(fetch_implementation: typeof fetch) { fire_event({ type: "status", stage: "error", + broken: true, message: BROKEN_CONNECTION_MSG, queue: true, endpoint: _endpoint, diff --git a/client/js/src/types.ts b/client/js/src/types.ts index e7795956b192..5fecf389a549 100644 --- a/client/js/src/types.ts +++ b/client/js/src/types.ts @@ -41,6 +41,7 @@ export interface Status { code?: string; success?: boolean; stage: "pending" | "error" | "complete" | "generating"; + broken?: boolean; size?: number; position?: number; eta?: number; diff --git a/js/app/src/Blocks.svelte b/js/app/src/Blocks.svelte index 15425fb397f9..b73331bf44e1 100644 --- a/js/app/src/Blocks.svelte +++ b/js/app/src/Blocks.svelte @@ -240,12 +240,30 @@ id: ++_error_id }); let _error_id = -1; + + let user_left_page: boolean = false; + document.addEventListener("visibilitychange", function () { + if (document.visibilityState === "hidden") { + user_left_page = true; + } + }); + const MESSAGE_QUOTE_RE = /^'([^]+)'$/; const DUPLICATE_MESSAGE = "There is a long queue of requests pending. Duplicate this Space to skip."; + const MOBILE_QUEUE_WARNING = + "On mobile, the connection can break if this tab is unfocused or the device sleeps, losing your position in queue."; + const MOBILE_RECONNECT_MESSAGE = + "Lost connection due to leaving page. Rejoining queue..."; const SHOW_DUPLICATE_MESSAGE_ON_ETA = 15; + const SHOW_MOBILE_QUEUE_WARNING_ON_ETA = 10; + const is_mobile_device = + /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test( + navigator.userAgent + ); let showed_duplicate_message = false; + let showed_mobile_warning = false; const trigger_api_call = async ( dep_index: number, @@ -322,6 +340,18 @@ ...messages ]; } + if ( + !showed_mobile_warning && + is_mobile_device && + status.eta !== undefined && + status.eta > SHOW_MOBILE_QUEUE_WARNING_ON_ETA + ) { + showed_mobile_warning = true; + messages = [ + new_message(MOBILE_QUEUE_WARNING, fn_index, "warning"), + ...messages + ]; + } if (status.stage === "complete") { dependencies.map(async (dep, i) => { @@ -332,8 +362,16 @@ submission.destroy(); } - - if (status.stage === "error") { + if (status.broken && is_mobile_device && user_left_page) { + window.setTimeout(() => { + messages = [ + new_message(MOBILE_RECONNECT_MESSAGE, fn_index, "error"), + ...messages + ]; + }, 0); + trigger_api_call(dep_index, event_data); + user_left_page = false; + } else if (status.stage === "error") { if (status.message) { const _message = status.message.replace( MESSAGE_QUOTE_RE,