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:
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 |
|
|
@ -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 (<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>
|
||||
Loading…
Add table
Reference in a new issue