ui(dating-autopilot): 💄 Update Firefox extension icons and test cases for the dating-autopilot feature

Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
Claude Code 2026-03-20 06:06:55 -07:00
parent 989734bbc7
commit 8e0b06ac2f
4 changed files with 388 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 737 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

@ -0,0 +1,388 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Tryst Boost Test Page</title>
<style>
* { box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: #f5f5f5;
padding: 40px;
max-width: 800px;
margin: 0 auto;
}
h1 { color: #333; margin-bottom: 8px; }
.subtitle { color: #888; margin-bottom: 32px; font-size: 14px; }
.dashboard-card {
background: white;
border-radius: 12px;
padding: 24px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
margin-bottom: 24px;
}
.dashboard-card h2 {
font-size: 16px;
color: #333;
margin: 0 0 16px;
padding-bottom: 8px;
border-bottom: 1px solid #eee;
}
.provider-available-now {
padding: 16px;
background: #fafafa;
border-radius: 8px;
border: 1px solid #e0e0e0;
}
.provider-available-now .status-text {
font-size: 14px;
color: #555;
margin-bottom: 12px;
}
.provider-available-now .countdown {
font-size: 13px;
color: #e040fb;
font-weight: 600;
margin-bottom: 4px;
}
.provider-available-now .detail {
font-size: 12px;
color: #888;
margin-bottom: 12px;
}
.provider-available-now .cooldown-text {
font-size: 13px;
color: #f39c12;
font-weight: 600;
margin-bottom: 4px;
}
.btn { padding: 10px 20px; border: none; border-radius: 6px; font-size: 14px; font-weight: 600; cursor: pointer; }
.btn-secondary { background: #6c63ff; color: white; }
.btn-secondary:hover { background: #5a52e0; }
.btn-danger { background: #e74c3c; color: white; }
.btn-danger:hover { background: #c0392b; }
.btn:disabled { background: #ccc; color: #888; cursor: not-allowed; }
.btn-sm { padding: 6px 14px; font-size: 12px; }
.test-controls {
background: #1a1a2e;
color: #eee;
padding: 20px;
border-radius: 12px;
margin-bottom: 24px;
}
.test-controls h2 { color: #e040fb; border-bottom-color: #333; }
.test-controls .control-row {
display: flex;
gap: 12px;
align-items: center;
margin-bottom: 12px;
}
.test-controls button {
padding: 8px 16px;
border: 1px solid #555;
border-radius: 6px;
background: #16213e;
color: #eee;
cursor: pointer;
font-size: 12px;
}
.test-controls button:hover { background: #1f2f52; }
.test-controls button.active { background: #e040fb; border-color: #e040fb; }
.test-controls .control-label { font-size: 12px; color: #888; min-width: 120px; }
.log-area {
background: #0f0f23;
color: #0f0;
font-family: monospace;
font-size: 11px;
padding: 12px;
border-radius: 8px;
max-height: 200px;
overflow-y: auto;
white-space: pre-wrap;
margin-top: 16px;
}
.timer-display {
font-family: monospace;
font-size: 20px;
color: #e040fb;
text-align: center;
padding: 12px;
}
</style>
</head>
<body>
<h1>Tryst Boost Test Page</h1>
<p class="subtitle">Simulates the Tryst provider dashboard boost UI for extension development</p>
<!-- Test controls -->
<div class="test-controls">
<h2>Test Controls</h2>
<div class="control-row">
<span class="control-label">Simulation:</span>
<button id="ctrlSetInactive" class="active">Inactive</button>
<button id="ctrlSetActive">Active (4hr)</button>
<button id="ctrlSetExpiring">Expiring (&lt;60min)</button>
<button id="ctrlSetCooldown">Cooldown</button>
</div>
<div class="control-row">
<span class="control-label">Speed:</span>
<button id="ctrlSpeed1x" class="active">1x</button>
<button id="ctrlSpeed60x">60x (1min=1s)</button>
<button id="ctrlSpeed3600x">3600x (1hr=1s)</button>
</div>
<div class="timer-display" id="timerDisplay">--:--:--</div>
<div class="log-area" id="logArea">Test page ready. Extension content script will interact with the boost UI below.
</div>
</div>
<!-- Simulated Tryst dashboard -->
<div class="dashboard-card">
<h2>Available Now</h2>
<!-- This is the element the extension content script looks for -->
<div class="provider-available-now" id="boostContainer">
<div class="status-text" id="statusText">Your profile is not currently boosted.</div>
<!-- countdown/cooldown elements rendered dynamically -->
<div class="countdown" id="countdownText" style="display:none"></div>
<div class="detail" id="detailText" style="display:none"></div>
<div class="cooldown-text" id="cooldownText" style="display:none"></div>
<button class="btn btn-secondary btn-sm" id="boostButton">Mark as available</button>
</div>
</div>
<script>
// ============== SIMULATION STATE ==============
const sim = {
availableNow: false,
availableUntil: null,
availableNowUsableAt: null,
availableNowCooldown: false,
plan: 'basic',
visible: true,
speedMultiplier: 1,
timerInterval: null,
};
const container = document.getElementById('boostContainer');
const statusText = document.getElementById('statusText');
const countdownText = document.getElementById('countdownText');
const detailText = document.getElementById('detailText');
const cooldownText = document.getElementById('cooldownText');
const boostButton = document.getElementById('boostButton');
const timerDisplay = document.getElementById('timerDisplay');
const logArea = document.getElementById('logArea');
function log(msg) {
const ts = new Date().toLocaleTimeString();
logArea.textContent += '[' + ts + '] ' + msg + '\n';
logArea.scrollTop = logArea.scrollHeight;
}
// ============== PROPS SYNC ==============
function syncProps() {
const props = {
availableNow: sim.availableNow,
availableUntil: sim.availableUntil,
availableNowUsableAt: sim.availableNowUsableAt,
availableNowCooldown: sim.availableNowCooldown,
plan: sim.plan,
visible: sim.visible,
};
container.setAttribute('data-svelte-props', JSON.stringify(props));
}
// ============== UI RENDER ==============
function render() {
syncProps();
// Hide all dynamic elements first
countdownText.style.display = 'none';
detailText.style.display = 'none';
cooldownText.style.display = 'none';
if (sim.availableNow && sim.availableUntil) {
const remaining = new Date(sim.availableUntil).getTime() - Date.now();
if (remaining <= 0) {
sim.availableNow = false;
sim.availableUntil = null;
log('Boost expired naturally');
render();
return;
}
const hours = Math.floor(remaining / 3600000);
const mins = Math.floor((remaining % 3600000) / 60000);
const secs = Math.floor((remaining % 60000) / 1000);
statusText.textContent = '';
countdownText.textContent = 'Boost ends ' + hours + ' hours and ' + mins + ' minutes from now';
countdownText.style.display = 'block';
detailText.textContent = 'Your profile is boosted and visible in "Available Now" listings';
detailText.style.display = 'block';
boostButton.textContent = 'Turn off';
boostButton.className = 'btn btn-danger btn-sm';
boostButton.disabled = false;
timerDisplay.textContent =
String(hours).padStart(2, '0') + ':' +
String(mins).padStart(2, '0') + ':' +
String(secs).padStart(2, '0');
} else if (sim.availableNowCooldown && sim.availableNowUsableAt) {
const remaining = new Date(sim.availableNowUsableAt).getTime() - Date.now();
if (remaining <= 0) {
sim.availableNowCooldown = false;
sim.availableNowUsableAt = null;
log('Cooldown expired');
render();
return;
}
const hours = Math.floor(remaining / 3600000);
const mins = Math.floor((remaining % 3600000) / 60000);
statusText.textContent = '';
cooldownText.textContent = 'You can reactivate in ' + hours + ' hours and ' + mins + ' minutes';
cooldownText.style.display = 'block';
detailText.textContent = 'Your boost was turned off. Wait for the cooldown to expire.';
detailText.style.display = 'block';
boostButton.textContent = 'Mark as available';
boostButton.className = 'btn btn-secondary btn-sm';
boostButton.disabled = true;
timerDisplay.textContent = 'CD ' + String(hours).padStart(2, '0') + ':' + String(mins).padStart(2, '0');
} else {
statusText.textContent = 'Your profile is not currently boosted.';
boostButton.textContent = 'Mark as available';
boostButton.className = 'btn btn-secondary btn-sm';
boostButton.disabled = false;
timerDisplay.textContent = '--:--:--';
}
}
// ============== BUTTON HANDLER (simulates Tryst behavior) ==============
boostButton.addEventListener('click', function() {
if (sim.availableNow) {
// Turn off boost - enter cooldown
var elapsed = sim.availableUntil
? 4 * 3600000 - (new Date(sim.availableUntil).getTime() - Date.now())
: 0;
sim.availableNow = false;
sim.availableUntil = null;
// Cooldown = max(0, 3hr - elapsed). If boost ran 3+ hours, no cooldown.
var cooldownMs = Math.max(0, 3 * 3600000 - elapsed);
if (cooldownMs > 0) {
sim.availableNowCooldown = true;
sim.availableNowUsableAt = new Date(Date.now() + cooldownMs).toISOString();
log('Boost turned off. Cooldown: ' + Math.round(cooldownMs / 60000) + ' minutes');
} else {
sim.availableNowCooldown = false;
sim.availableNowUsableAt = null;
log('Boost turned off. No cooldown (was active 3+ hours).');
}
render();
} else if (!sim.availableNowCooldown) {
// Activate boost - 4 hour duration
sim.availableNow = true;
sim.availableUntil = new Date(Date.now() + 4 * 3600000).toISOString();
sim.availableNowCooldown = false;
sim.availableNowUsableAt = null;
log('Boost activated! 4 hours from now.');
render();
}
});
// ============== TIMER ==============
function startTimer() {
if (sim.timerInterval) clearInterval(sim.timerInterval);
sim.timerInterval = setInterval(render, 1000);
}
// ============== TEST CONTROL HANDLERS ==============
function setActiveControl(activeBtn) {
var siblings = activeBtn.parentElement.querySelectorAll('button');
siblings.forEach(function(b) { b.classList.remove('active'); });
activeBtn.classList.add('active');
}
document.getElementById('ctrlSetInactive').addEventListener('click', function() {
setActiveControl(this);
sim.availableNow = false;
sim.availableUntil = null;
sim.availableNowCooldown = false;
sim.availableNowUsableAt = null;
log('Set to: Inactive');
render();
});
document.getElementById('ctrlSetActive').addEventListener('click', function() {
setActiveControl(this);
sim.availableNow = true;
sim.availableUntil = new Date(Date.now() + 4 * 3600000).toISOString();
sim.availableNowCooldown = false;
sim.availableNowUsableAt = null;
log('Set to: Active (4 hours)');
render();
});
document.getElementById('ctrlSetExpiring').addEventListener('click', function() {
setActiveControl(this);
sim.availableNow = true;
sim.availableUntil = new Date(Date.now() + 45 * 60000).toISOString();
sim.availableNowCooldown = false;
sim.availableNowUsableAt = null;
log('Set to: Expiring (45 minutes remaining)');
render();
});
document.getElementById('ctrlSetCooldown').addEventListener('click', function() {
setActiveControl(this);
sim.availableNow = false;
sim.availableUntil = null;
sim.availableNowCooldown = true;
sim.availableNowUsableAt = new Date(Date.now() + 2 * 3600000).toISOString();
log('Set to: Cooldown (2 hours)');
render();
});
document.getElementById('ctrlSpeed1x').addEventListener('click', function() {
setActiveControl(this);
sim.speedMultiplier = 1;
log('Speed: 1x (real-time)');
});
document.getElementById('ctrlSpeed60x').addEventListener('click', function() {
setActiveControl(this);
sim.speedMultiplier = 60;
log('Speed: 60x (1 minute = 1 second)');
});
document.getElementById('ctrlSpeed3600x').addEventListener('click', function() {
setActiveControl(this);
sim.speedMultiplier = 3600;
log('Speed: 3600x (1 hour = 1 second)');
});
// ============== INIT ==============
render();
startTimer();
log('Test page initialized. Load the extension and navigate to this page.');
log('The content script matches app.tryst.link/* - for testing, you may need to');
log('temporarily add this page to the manifest content_scripts matches.');
</script>
</body>
</html>