Skip to content

feat: improve iOS offline editor experience#366

Open
dcalhoun wants to merge 15 commits intotrunkfrom
feat/improve-ios-offline-editor
Open

feat: improve iOS offline editor experience#366
dcalhoun wants to merge 15 commits intotrunkfrom
feat/improve-ios-offline-editor

Conversation

@dcalhoun
Copy link
Member

@dcalhoun dcalhoun commented Mar 10, 2026

What?

Improve the offline editor experience by adding network fallback mode support, an offline indicator, and graceful degradation when the device is offline.

Why?

Fix CMM-1206.

When opening the iOS GutenbergKit editor while offline without a cached bundle, the editor fails to load entirely. The expected behavior is to fall back to the bundled editor and display a notice indicating that the user is offline.

How?

  • Network fallback mode: Add a NetworkFallbackMode enum and configuration property that enables automatic fallback to bundled resources when network requests fail (EditorService, EditorConfiguration).
  • Offline indicator: Create an OfflineIndicator component that displays a "Working Offline" status bar with an offline icon when the device loses connectivity, using browser online/offline events. Uses speak() from @wordpress/a11y to announce "Network connection lost, working offline" for screen readers.
  • iOS demo app improvements: Add a Network Fallback picker to the site configuration view. When the device is offline, fall back to offline defaults instead of showing an error, allowing the editor to still be opened.
  • Documentation: Add a Network Fallback Mode section to the preloading docs.

Testing Instructions

  1. Open the iOS demo app.
  2. Navigate to a configured site's Editor Configuration.
  3. Enable "Automatic" for the Network Fallback picker.
  4. Enable airplane mode.
  5. Tap "Start" to open the editor.
  6. Verify the editor loads with the bundled editor and displays a "Working Offline" indicator at the top with a wifi-off icon.
  7. Disable airplane mode.
  8. Verify the "Working Offline" indicator disappears.

Accessibility Testing Instructions

  1. Enable VoiceOver on the device.
  2. With the editor open, enable airplane mode.
  3. Verify VoiceOver announces "Network connection lost, working offline."
  4. Navigate to the offline indicator and verify it reads "Working Offline."

Screenshots or screencast

gbk-ios-network-fallback.mp4

dcalhoun and others added 9 commits March 10, 2026 14:45
Add a new `NetworkFallbackMode` enum (.disabled / .automatic) alongside
the existing `isOfflineModeEnabled` Bool. They are orthogonal:
- `isOfflineModeEnabled`: no site exists, skip all networking
- `networkFallbackMode`: site exists, but fall back to bundled editor
  on network failure instead of showing an error

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When `networkFallbackMode == .automatic`, wrap dependency fetching in a
do/catch block. Network errors (URLError codes like notConnectedToInternet,
timedOut, etc.) return empty dependencies so the bundled editor loads.
Non-network errors still propagate.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
A thin, full-width status bar displaying "Working Offline" that
auto-shows/hides based on browser online/offline events. Uses a
custom useNetworkConnectivity hook backed by navigator.onLine.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add the OfflineIndicator component inside the ErrorBoundary, before
the Editor, so it appears at the top of the editor content area.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Test that the component:
- Does not render when online
- Renders "Working Offline" when navigator.onLine is false
- Auto-hides when the online event fires
- Re-appears when the offline event fires

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Document the new networkFallbackMode configuration, how it differs
from isOfflineModeEnabled, and the OfflineIndicator JS component.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add a Picker in the Feature Configuration section of
SitePreparationView to switch between .disabled and .automatic
network fallback modes, following the same pattern as the existing
Post Type picker.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…e is offline

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@dcalhoun dcalhoun added the [Type] Enhancement A suggestion for improvement. label Mar 10, 2026
dcalhoun and others added 6 commits March 10, 2026 16:13
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add role="status" and aria-label so screen readers announce
"Network connection lost, working offline" when the indicator appears.
Also fix inverted render guard that was hiding the indicator when offline.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace role="status" and aria-label with an imperative speak() call
from @wordpress/a11y, which announces "Network connection lost" when
the device goes offline. This avoids VoiceOver's duplicate reading of
live region content and accessible name.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…cator

Keep useNetworkConnectivity as a pure data hook and let the component
own its accessibility behavior via a separate useEffect.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@dcalhoun dcalhoun marked this pull request as ready for review March 11, 2026 00:41
Comment on lines +55 to +72
function useNetworkConnectivity() {
const [ isConnected, setIsConnected ] = useState( navigator.onLine );

useEffect( () => {
const handleOnline = () => setIsConnected( true );
const handleOffline = () => setIsConnected( false );

window.addEventListener( 'online', handleOnline );
window.addEventListener( 'offline', handleOffline );

return () => {
window.removeEventListener( 'online', handleOnline );
window.removeEventListener( 'offline', handleOffline );
};
}, [] );

return { isConnected };
}
Copy link
Member Author

@dcalhoun dcalhoun Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using navigator.onLine and the online/offline events is proving highly unreliable. Namely, they don't ever report an "offline" state in Android Chrome when airplane mode is activated (and wi-fi disabled). So, this needs to be replaced.

That said, the primary target of this work is ensuring the iOS editor opens when offline. Currently, it displays a full-screen error message.

I consider this PR a quick iteration to improve the UX. I plan to follow up later, refactoring this "Working Offline" indicator to rely upon native OS capabilities that are far more capable of detecting internet—either within the GBK library or from bridge communication with the host app.

In the meantime, I suggest we merge this given it unblocks the editor on iOS while offline.

@dcalhoun dcalhoun requested a review from kean March 11, 2026 00:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Type] Enhancement A suggestion for improvement.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant