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
172 changes: 172 additions & 0 deletions html5/css/client.css
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ body {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 2.4rem;
color: white;
font-size: 2rem;
font-weight: bold;
Expand All @@ -27,11 +29,181 @@ body {
color: rgb(134, 142, 150);
}

#background .browser-icon {
color: rgb(173, 181, 189);
margin-bottom: 1rem;
}

#background h3 {
margin: 0;
font-size: 4rem;
font-weight: 500;
text-align: center;
padding: 0 2rem;
}

#background .open-browser-text {
margin: 0;
font-size: 2.8rem;
font-weight: 400;
text-align: center;
}

#open-browser-btn {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
gap: 1rem;
padding: 1.2rem 2.4rem;
font-size: 2.4rem;
font-weight: 600;
color: #fff;
background-color: #228be6;
border: none;
border-radius: 16px;
cursor: pointer;
transition: background-color 0.15s ease;
overflow: hidden;
min-width: 320px;
}

#open-browser-btn .btn-content {
display: flex;
align-items: center;
gap: 1rem;
}

#open-browser-btn .world-icon {
flex-shrink: 0;
}

#open-browser-btn .btn-loader-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
align-items: center;
justify-content: center;
background-color: #228be6;
opacity: 0;
pointer-events: none;
transition: opacity 0.15s ease;
}

#open-browser-btn .btn-loader {
width: 41.6px;
height: 41.6px;
border: 4px solid rgba(255, 255, 255, 0.3);
border-top-color: #fff;
border-radius: 50%;
animation: spin 0.8s linear infinite;
}

#open-browser-btn.loading .btn-loader-overlay {
opacity: 1;
}

#open-browser-btn.loading {
cursor: not-allowed;
}

@keyframes spin {
to {
transform: rotate(360deg);
}
}

#open-browser-btn:hover:not(:disabled) {
background-color: #1c7ed6;
}

#open-browser-btn:hover:not(:disabled) .btn-loader-overlay {
background-color: #1c7ed6;
}

#open-browser-btn:active:not(:disabled) {
background-color: #1971c2;
}

#open-browser-btn:active:not(:disabled) .btn-loader-overlay {
background-color: #1971c2;
}

#open-browser-btn:disabled {
cursor: not-allowed;
}

/* Error toast */
.error-toast {
position: fixed;
bottom: 2rem;
left: 50%;
transform: translateX(-50%);
display: flex;
align-items: center;
gap: 1rem;
padding: 1.6rem 2rem;
background-color: #fa5252;
color: #fff;
font-size: 2.4rem;
font-weight: 500;
border-radius: 16px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
z-index: 1000;
animation: slideUp 0.3s ease;
}

@keyframes slideUp {
from {
opacity: 0;
transform: translateX(-50%) translateY(10px);
}
to {
opacity: 1;
transform: translateX(-50%) translateY(0);
}
}

#background.dark {
color: rgb(130, 130, 130);
background-color: #161d27;
}

#background.dark .browser-icon {
color: rgb(100, 110, 120);
}

#background.dark #open-browser-btn {
background-color: #1c7ed6;
}

#background.dark #open-browser-btn .btn-loader-overlay {
background-color: #1c7ed6;
}

#background.dark #open-browser-btn:hover:not(:disabled) {
background-color: #228be6;
}

#background.dark #open-browser-btn:hover:not(:disabled) .btn-loader-overlay {
background-color: #228be6;
}

#background.dark #open-browser-btn:active:not(:disabled) {
background-color: #1971c2;
}

#background.dark #open-browser-btn:active:not(:disabled) .btn-loader-overlay {
background-color: #1971c2;
}

#background.dark .error-toast {
background-color: #e03131;
}

div.window canvas {
touch-action: none;
border-radius: 0 0 3px 3px;
Expand Down
35 changes: 35 additions & 0 deletions html5/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,18 @@
</div>

<div id="background">
<svg class="browser-icon" xmlns="http://www.w3.org/2000/svg" width="320" height="320" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M4 8h16" /><path d="M4 6a2 2 0 0 1 2 -2h12a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2l0 -12" /><path d="M8 4v4" /></svg>
<h3>The AI will open the browser here automatically when needed.</h3>
<p class="open-browser-text">Or open a browser if you'd like to record</p>
<button id="open-browser-btn" onclick="requestOpenBrowser()">
<span class="btn-content">
<svg class="world-icon" xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M3 12a9 9 0 1 0 18 0a9 9 0 0 0 -18 0" /><path d="M3.6 9h16.8" /><path d="M3.6 15h16.8" /><path d="M11.5 3a17 17 0 0 0 0 18" /><path d="M12.5 3a17 17 0 0 1 0 18" /></svg>
<span class="btn-text">Open Browser</span>
</span>
<span class="btn-loader-overlay">
<span class="btn-loader"></span>
</span>
</button>
</div>

<div id="login-overlay">
Expand Down Expand Up @@ -279,6 +290,30 @@ <h2>Xpra Bug Report</h2>
<div class="simple-keyboard" style="display: block; position: fixed; bottom: 0; width: 100%"></div>

<script>
// State for the open browser button
let isOpeningBrowser = false;
let loadingTimeoutId = null;

// Send message to parent window to request browser open via MCP
function requestOpenBrowser() {
if (isOpeningBrowser) return;

isOpeningBrowser = true;
const btn = document.getElementById('open-browser-btn');
btn.classList.add('loading');
btn.disabled = true;

window.parent.postMessage({ type: 'xpra-open-browser' }, '*');

// Reset button after 10 seconds so user can retry if needed
loadingTimeoutId = setTimeout(function() {
isOpeningBrowser = false;
btn.classList.remove('loading');
btn.disabled = false;
loadingTimeoutId = null;
}, 10000);
}

const default_settings = {};
const getparam = function(prop) {
let v = Utilities.getparam(prop);
Expand Down