Skip to content

Commit a0340b7

Browse files
committed
Improve playground mobile UX and error handling
- Add mobile responsive styles: enable scrolling, set min-heights for all sections - Fix header layout on mobile to stack vertically - Add share icon to Share button - Add Report Bug button with pre-filled GitHub issue template - Remove "Example loaded" toast notification - Improve compiler load error messages with specific cases (network, 404, 0 bytes) - Dynamically show actual file size instead of hardcoded "64MB" - Fix variable scope issue in error handler
1 parent 5c68a90 commit a0340b7

File tree

1 file changed

+194
-6
lines changed

1 file changed

+194
-6
lines changed

nullsafe-playground/index.html

Lines changed: 194 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -469,8 +469,41 @@
469469
}
470470

471471
@media (max-width: 768px) {
472+
body {
473+
height: auto;
474+
min-height: 100vh;
475+
overflow-y: auto;
476+
}
477+
472478
.main-container {
473479
flex-direction: column;
480+
min-height: 500px;
481+
height: auto;
482+
}
483+
484+
.pane {
485+
min-height: 300px;
486+
}
487+
488+
.pane:first-child,
489+
.pane:last-child {
490+
flex: 1 1 auto;
491+
height: auto;
492+
min-height: 300px;
493+
}
494+
495+
#editor-wrapper {
496+
min-height: 250px;
497+
}
498+
499+
.output-container {
500+
min-height: 250px;
501+
}
502+
503+
.output-section:first-child,
504+
.output-section:last-child {
505+
flex: 1 1 auto;
506+
min-height: 150px;
474507
}
475508

476509
.divider {
@@ -481,15 +514,33 @@
481514

482515
.header {
483516
padding: 16px 20px;
517+
flex-direction: column;
518+
align-items: flex-start;
519+
gap: 12px;
484520
}
485521

486522
.header h1 {
487523
font-size: 24px;
524+
margin-bottom: 4px;
525+
}
526+
527+
.header p {
528+
font-size: 14px;
529+
}
530+
531+
.header-links {
532+
align-self: flex-start;
488533
}
489534

490535
.controls {
491536
padding: 12px 20px;
492537
}
538+
539+
.status {
540+
margin-left: 0;
541+
width: 100%;
542+
justify-content: center;
543+
}
493544
}
494545
</style>
495546
</head>
@@ -502,6 +553,13 @@ <h1>Null-Safe Clang Playground</h1>
502553
<p>Flow-sensitive null safety for C - Try the experimental compiler live in your browser</p>
503554
</div>
504555
<div class="header-links">
556+
<button id="reportBugBtn" class="header-link" style="background: none; border: none; cursor: pointer;">
557+
<svg width="20" height="20" fill="currentColor" viewBox="0 0 16 16" style="vertical-align: text-bottom;">
558+
<path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z"/>
559+
<path d="M7.002 11a1 1 0 1 1 2 0 1 1 0 0 1-2 0zM7.1 4.995a.905.905 0 1 1 1.8 0l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 4.995z"/>
560+
</svg>
561+
Report Bug
562+
</button>
505563
<a href="https://github.com/cs01/llvm-project/" target="_blank" class="header-link">
506564
<svg width="20" height="20" fill="currentColor" viewBox="0 0 16 16" style="vertical-align: text-bottom;">
507565
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.012 8.012 0 0 0 16 8c0-4.42-3.58-8-8-8z"/>
@@ -530,6 +588,9 @@ <h1>Null-Safe Clang Playground</h1>
530588
</select>
531589

532590
<button id="shareBtn" class="btn btn-secondary">
591+
<svg width="16" height="16" fill="currentColor" viewBox="0 0 16 16" style="vertical-align: text-bottom;">
592+
<path d="M13.5 1a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3zM11 2.5a2.5 2.5 0 1 1 .603 1.628l-6.718 3.12a2.499 2.499 0 0 1 0 1.504l6.718 3.12a2.5 2.5 0 1 1-.488.876l-6.718-3.12a2.5 2.5 0 1 1 0-3.256l6.718-3.12A2.5 2.5 0 0 1 11 2.5zm-8.5 4a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3zm11 5.5a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3z"/>
593+
</svg>
533594
Share
534595
</button>
535596

@@ -903,7 +964,6 @@ <h1>Null-Safe Clang Playground</h1>
903964
const example = e.target.value;
904965
if (example && examples[example]) {
905966
setEditorValue(examples[example]);
906-
showToast('Example loaded!');
907967
}
908968
});
909969

@@ -923,6 +983,104 @@ <h1>Null-Safe Clang Playground</h1>
923983
}
924984
});
925985

986+
// Report bug button - create GitHub issue with context
987+
const reportBugBtn = document.getElementById('reportBugBtn');
988+
reportBugBtn.addEventListener('click', () => {
989+
// Check if compiler is loaded and code has been compiled
990+
if (!clangVersion || outputNullsafe.textContent === '' || outputNullsafe.textContent === '(no output yet)') {
991+
if (!confirm('You haven\'t compiled any code yet. The bug report will be incomplete. Continue anyway?')) {
992+
return;
993+
}
994+
}
995+
996+
const code = getEditorValue();
997+
const nullsafeOutput = outputNullsafe.textContent || '(no output yet)';
998+
const mainlineOutput = outputMainline.textContent || '(no output yet)';
999+
1000+
// Get browser info - parse user agent for readability
1001+
const ua = navigator.userAgent;
1002+
let browserInfo = ua;
1003+
1004+
// Try to parse browser name and version
1005+
let browserName = 'Unknown';
1006+
let browserVersion = '';
1007+
if (ua.includes('Chrome/') && !ua.includes('Edg/')) {
1008+
browserName = 'Chrome';
1009+
browserVersion = ua.match(/Chrome\/([0-9.]+)/)?.[1] || '';
1010+
} else if (ua.includes('Edg/')) {
1011+
browserName = 'Edge';
1012+
browserVersion = ua.match(/Edg\/([0-9.]+)/)?.[1] || '';
1013+
} else if (ua.includes('Firefox/')) {
1014+
browserName = 'Firefox';
1015+
browserVersion = ua.match(/Firefox\/([0-9.]+)/)?.[1] || '';
1016+
} else if (ua.includes('Safari/') && !ua.includes('Chrome/')) {
1017+
browserName = 'Safari';
1018+
browserVersion = ua.match(/Version\/([0-9.]+)/)?.[1] || '';
1019+
}
1020+
1021+
// Get OS info
1022+
let osInfo = 'Unknown';
1023+
if (ua.includes('Mac OS X')) {
1024+
const osVersion = ua.match(/Mac OS X ([0-9_]+)/)?.[1]?.replace(/_/g, '.') || '';
1025+
osInfo = `macOS ${osVersion}`;
1026+
} else if (ua.includes('Windows')) {
1027+
osInfo = 'Windows';
1028+
} else if (ua.includes('Linux')) {
1029+
osInfo = 'Linux';
1030+
}
1031+
1032+
const formattedBrowser = `${browserName} ${browserVersion} on ${osInfo}`;
1033+
1034+
// Build the issue body
1035+
const issueBody = `## Bug Report from Playground
1036+
1037+
### Environment
1038+
- **Compiler Version:** ${clangVersion || 'not loaded'}
1039+
- **Browser:** ${formattedBrowser}
1040+
- **User Agent:** ${ua}
1041+
- **Playground URL:** ${window.location.href}
1042+
1043+
### Code
1044+
\`\`\`c
1045+
${code}
1046+
\`\`\`
1047+
1048+
### Compiler Output
1049+
1050+
#### With Null Warnings
1051+
\`\`\`
1052+
${nullsafeOutput}
1053+
\`\`\`
1054+
1055+
#### Without Null Warnings
1056+
\`\`\`
1057+
${mainlineOutput}
1058+
\`\`\`
1059+
1060+
### Expected Behavior
1061+
<!-- Please describe what you expected to happen -->
1062+
1063+
1064+
### Actual Behavior
1065+
<!-- Please describe what actually happened -->
1066+
1067+
1068+
### Additional Context
1069+
<!-- Add any other context about the problem here -->
1070+
`;
1071+
1072+
// Create GitHub issue URL with pre-filled content
1073+
const repoUrl = 'https://github.com/cs01/llvm-project';
1074+
const issueUrl = new URL(`${repoUrl}/issues/new`);
1075+
issueUrl.searchParams.set('title', '[Playground Bug] ');
1076+
issueUrl.searchParams.set('body', issueBody);
1077+
issueUrl.searchParams.set('labels', 'bug,playground');
1078+
1079+
// Open in new tab
1080+
window.open(issueUrl.toString(), '_blank');
1081+
showToast('Opening bug report in GitHub...');
1082+
});
1083+
9261084
// Load code from URL on page load
9271085
function loadCodeFromURL() {
9281086
const urlParams = new URLSearchParams(window.location.search);
@@ -940,10 +1098,12 @@ <h1>Null-Safe Clang Playground</h1>
9401098
}
9411099

9421100
async function initCompiler() {
943-
setStatus('Loading compiler (64MB)...', true, 0);
1101+
setStatus('Loading compiler...', true, 0);
9441102
status.className = 'status';
9451103
loadingBar.classList.add('active');
9461104

1105+
let loaded = 0;
1106+
9471107
try {
9481108
// Determine script URL
9491109
const isDev = window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1';
@@ -958,10 +1118,20 @@ <h1>Null-Safe Clang Playground</h1>
9581118
// Pre-load the WASM binary ONCE with progress tracking
9591119
console.log('Downloading WASM binary...');
9601120
const wasmResponse = await fetch(wasmUrl);
1121+
1122+
if (!wasmResponse.ok) {
1123+
throw new Error(`Failed to fetch WASM: ${wasmResponse.status} ${wasmResponse.statusText}`);
1124+
}
1125+
9611126
const contentLength = wasmResponse.headers.get('content-length');
9621127
const total = parseInt(contentLength, 10);
9631128

964-
let loaded = 0;
1129+
// Update status with actual size if known
1130+
if (total) {
1131+
const sizeMB = (total / (1024 * 1024)).toFixed(0);
1132+
setStatus(`Loading compiler (${sizeMB}MB)...`, true, 0);
1133+
}
1134+
9651135
const reader = wasmResponse.body.getReader();
9661136
const chunks = [];
9671137

@@ -1008,12 +1178,30 @@ <h1>Null-Safe Clang Playground</h1>
10081178
setTimeout(() => compile(), 500);
10091179

10101180
} catch (error) {
1011-
status.textContent = 'Failed to load compiler';
1181+
console.error('Failed to load Clang WASM:', error);
1182+
1183+
// Provide a helpful error message
1184+
let errorMessage = 'Failed to load compiler';
1185+
let toastMessage = 'Failed to load compiler';
1186+
1187+
if (error.message && error.message.includes('Failed to fetch')) {
1188+
errorMessage = 'Network error - Cannot download compiler';
1189+
toastMessage = 'Network error: Unable to download the compiler. Please check your internet connection.';
1190+
} else if (error.message && (error.message.includes('404') || error.message.includes('File not found'))) {
1191+
errorMessage = 'Compiler files not found';
1192+
toastMessage = 'Compiler files not found. The WASM binaries are missing from the server.';
1193+
} else if (loaded === 0 || (wasmBinary && wasmBinary.byteLength === 0)) {
1194+
errorMessage = 'Download failed - 0 bytes received';
1195+
toastMessage = 'Failed to download compiler: Received 0 bytes. Please check your internet connection and try refreshing the page.';
1196+
} else {
1197+
toastMessage = `Failed to load compiler: ${error.message}`;
1198+
}
1199+
1200+
status.textContent = errorMessage;
10121201
status.className = 'status error';
10131202
status.title = '';
10141203
loadingBar.classList.remove('active');
1015-
showToast('Failed to load compiler: ' + error.message, 4000);
1016-
console.error('Failed to load Clang WASM:', error);
1204+
showToast(toastMessage, 6000);
10171205
}
10181206
}
10191207

0 commit comments

Comments
 (0)