Merge pull request #368 from hackclub/beta-branch

update logos + better setup flow
This commit is contained in:
Echo
2025-06-26 11:20:01 -04:00
committed by GitHub
14 changed files with 358 additions and 355 deletions

View File

@@ -1,266 +1,147 @@
<h1>Hackatime Set Up</h1>
<p>Step 1 of 4</p>
<div class="min-h-screen text-white">
<div class="max-w-6xl mx-auto p-4">
<div class="text-center mb-4">
<h1 class="text-4xl font-bold text-primary mb-2">Hackatime Setup</h1>
<div class="flex items-center justify-center gap-2 mb-4">
<div class="w-8 h-8 bg-primary rounded-full flex items-center justify-center text-sm font-bold">1</div>
<div class="w-16 h-1 bg-darkless"></div>
<div class="w-8 h-8 bg-darkless rounded-full flex items-center justify-center text-sm">2</div>
<div class="w-16 h-1 bg-darkless"></div>
<div class="w-8 h-8 bg-darkless rounded-full flex items-center justify-center text-sm">3</div>
<div class="w-16 h-1 bg-darkless"></div>
<div class="w-8 h-8 bg-darkless rounded-full flex items-center justify-center text-sm">4</div>
</div>
</div>
<div class="setup-instructions">
<div id="os-detection-message" class="text-center">
<p>Detecting your operating system...</p>
<div class="progress-indicator"></div>
</div>
<div class="setup-instructions">
<div id="mac-linux" class="bg-dark rounded-lg p-6" style="display: block;">
<h3 class="text-2xl font-bold text-green mb-4">🍎 Mac/Linux/Codespaces users:</h3>
<ol class="list-decimal list-inside text-lg space-y-2 mb-6">
<li>Open your terminal (on Mac it's called <i>Terminal</i>, if you are using something like GitHub Codespaces, just open the terminal in the Codespaces environment)</li>
<li>Copy and paste the following command into your terminal</li>
<li>Press <i>Return</i> to run it</li>
</ol>
<div class="code-block bg-darkless rounded-lg p-4 mb-4">
<code class="text-cyan text-sm">export HACKATIME_API_KEY="<%= @current_user_api_key %>" && export HACKATIME_API_URL="<%= api_hackatime_v1_url %>" && export SUCCESS_URL="<%= root_url %>/success.txt" && curl -sSL <%= root_url %>hackatime/setup.sh | bash</code>
<button class="copy-button bg-primary hover:bg-red border-0 text-white px-4 py-2 rounded transition-colors cursor-pointer" onclick="copy(this)">Copy</button>
</div>
<div class="rounded-lg mb-6">
<iframe width="100%" height="300" src="https://www.youtube.com/embed/QTwhJy7nT_w?loop=1&playlist=QTwhJy7nT_w&modestbranding=1&rel=0" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen class="rounded"></iframe>
</div>
<div class="flex gap-4 flex-wrap">
<button id="show-windows-button" class="bg-blue hover:bg-cyan text-white border-0 px-4 py-2 rounded transition-colors cursor-pointer" onclick="toggleSection('windows')">Using Windows?</button>
<button id="show-advanced-button-from-mac" class="bg-purple hover:bg-darkless text-white border-0 px-4 py-2 rounded transition-colors cursor-pointer" onclick="toggleSection('advanced')">Custom Setup</button>
</div>
</div>
<div id="mac-linux-section" style="display: none;">
<h3>Mac/Linux users:</h3>
<ol>
<li>Open your terminal (on Mac it's called <i>Terminal</i>)</li>
<li>Copy and paste the following command into your terminal</li>
<li>Press <i>Return</i> to run it</li>
</ol>
<div class="code-block">
<code>export HACKATIME_API_KEY="<%= @current_user_api_key %>" && export HACKATIME_API_URL="<%= api_hackatime_v1_url %>" && export SUCCESS_URL="<%= root_url %>/success.txt" && curl -sSL <%= root_url %>hackatime/setup.sh | bash</code>
<button class="copy-button" onclick="copyCode(this)">Copy</button>
</div>
<div id="mac-linux-video-container"></div>
<div>
<button id="show-windows-button" class="copy-button" onclick="toggleSection('windows')">Using Windows? Click here</button>
<button id="show-advanced-button-from-mac" class="copy-button" onclick="toggleSection('advanced')">Advanced/Custom Setup</button>
</div>
</div>
<div id="windows" class="bg-dark rounded-lg p-6" style="display: none;">
<h3 class="text-2xl font-bold text-blue mb-4">🪟 Windows users:</h3>
<ol class="list-decimal list-inside text-lg space-y-2 mb-6">
<li>Open <i>PowerShell</i></li>
<li>Copy and paste the following command (<i>Ctrl+V</i> to paste)</li>
<li>Press <i>Enter</i> to run it</li>
</ol>
<div class="code-block bg-darkless rounded-lg p-4 mb-4">
<code class="text-cyan text-sm">$env:HACKATIME_API_KEY="<%= @current_user_api_key %>"; $env:HACKATIME_API_URL="<%= api_hackatime_v1_url %>"; powershell -ExecutionPolicy Bypass -Command "& {iwr <%= root_url %>hackatime/setup.ps1 -UseBasicParsing | iex}"</code>
<button class="copy-button bg-primary hover:bg-red border-0 text-white px-4 py-2 rounded transition-colors cursor-pointer" onclick="copy(this)">Copy</button>
</div>
<div class="rounded-lg mb-6">
<iframe width="100%" height="300" src="https://www.youtube.com/embed/fX9tsiRvzhg?loop=1&playlist=fX9tsiRvzhg&modestbranding=1&rel=0" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen class="rounded"></iframe>
</div>
<div class="flex gap-4 flex-wrap">
<button id="show-mac-linux-button" class="bg-green hover:bg-cyan text-white border-0 px-4 py-2 rounded transition-colors cursor-pointer" onclick="toggleSection('mac-linux')">Using Mac/Linux/Codespaces?</button>
<button id="show-advanced-button" class="bg-purple hover:bg-darkless text-white border-0 px-4 py-2 rounded transition-colors cursor-pointer" onclick="toggleSection('advanced')">Custom Setup</button>
</div>
</div>
<div id="windows-section" style="display: none;">
<h3>Windows users:</h3>
<ol>
<li>Open <i>PowerShell</i></li>
<li>Copy and paste the following command (<i>Ctrl+V</i> to paste)</li>
<li>Press <i>Enter</i> to run it</li>
</ol>
<div class="code-block">
<code>$env:HACKATIME_API_KEY="<%= @current_user_api_key %>"; $env:HACKATIME_API_URL="<%= api_hackatime_v1_url %>"; powershell -ExecutionPolicy Bypass -Command "& {iwr <%= root_url %>hackatime/setup.ps1 -UseBasicParsing | iex}"</code>
<button class="copy-button" onclick="copyCode(this)">Copy</button>
<div id="advanced" class="bg-dark rounded-lg p-6" style="display: none;">
<h3 class="text-2xl font-bold text-purple mb-4">⚙️ Custom Setup:</h3>
<p class="text-lg mb-4">For advanced users or custom installations, you can manually set up your Hackatime configuration.</p>
<p class="mb-6">Create or edit <code class="bg-darkless px-2 py-1 rounded text-cyan">~/.wakatime.cfg</code> with the following content:</p>
<div class="code-block bg-darkless rounded-lg p-4 mb-6">
<code class="text-cyan text-sm">[settings]&#10;api_url = <%= api_hackatime_v1_url %>&#10;api_key = <%= @current_user_api_key %>&#10;heartbeat_rate_limit_seconds = 30</code>
<button class="copy-button bg-primary hover:bg-red border-0 text-white px-4 py-2 rounded transition-colors cursor-pointer" onclick="copy(this)">Copy</button>
</div>
<div class="flex gap-4 flex-wrap">
<button id="show-mac-linux-from-advanced-button" class="bg-green hover:bg-cyan text-white border-0 px-4 py-2 rounded transition-colors cursor-pointer" onclick="toggleSection('mac-linux')">Using Mac/Linux/Codespaces?</button>
<button id="show-windows-from-advanced-button" class="bg-blue hover:bg-cyan text-white border-0 px-4 py-2 rounded transition-colors cursor-pointer" onclick="toggleSection('windows')">Using Windows?</button>
</div>
</div>
</div>
<div id="windows-video-container"></div>
<div>
<button id="show-mac-linux-button" class="copy-button" onclick="toggleSection('mac-linux')">Using Mac/Linux? Click here</button>
<button id="show-advanced-button" class="copy-button" onclick="toggleSection('advanced')">Advanced/Custom Setup</button>
</div>
</div>
<div id="advanced-section" style="display: none;">
<h3>Advanced/Custom Setup:</h3>
<p>For advanced users or custom installations, you can manually set up your Hackatime configuration.</p>
<p>Create or edit <code>~/.wakatime.cfg</code> with the following content:</p>
<div class="code-block">
<code>[settings]&#10;api_url = <%= api_hackatime_v1_url %>&#10;api_key = <%= @current_user_api_key %>&#10;heartbeat_rate_limit_seconds = 30</code>
<button class="copy-button" onclick="copyCode(this)">Copy</button>
</div>
<div>
<button id="show-mac-linux-from-advanced-button" class="copy-button" onclick="toggleSection('mac-linux')">Using Mac/Linux? Click here</button>
<button id="show-windows-from-advanced-button" class="copy-button" onclick="toggleSection('windows')">Using Windows? Click here</button>
<div class="mt-2 text-center">
<div id="heartbeat-status" class="bg-dark rounded-lg p-6 mb-6">
<p class="text-lg mb-4">Waiting for your first heartbeat...</p>
<div class="progress-indicator"></div>
</div>
<div id="next-step" class="hidden">
<%= link_to "Next Step", my_wakatime_setup_step_2_path, class: "bg-primary hover:bg-red text-white px-8 py-3 rounded-lg text-lg font-semibold transition-colors" %>
</div>
</div>
</div>
</div>
<p class="text-sm text-gray-600">This will create your Hackatime config file and send a test heartbeat to verify the set up.</p>
<div id="heartbeat-status">
<p>Waiting for your first heartbeat...</p>
<div class="progress-indicator"></div>
</div>
<p>
<%= link_to "Next Step", my_wakatime_setup_step_2_path, id: "next-step", style: "display: none;" %>
</p>
<!-- YouTube API -->
<script src="https://www.youtube.com/iframe_api"></script>
<script>
let macLinuxPlayer = null;
let windowsPlayer = null;
let playerReady = false;
// YouTube API callback
function onYouTubeIframeAPIReady() {
playerReady = true;
setupPlayers();
}
// Function to setup YouTube players
function setupPlayers() {
// Only setup if the players haven't been created
if (!macLinuxPlayer) {
macLinuxPlayer = new YT.Player('mac-linux-video-container', {
height: '315',
width: '560',
videoId: 'QTwhJy7nT_w',
playerVars: {
'loop': 1,
'playsinline': 1,
'modestbranding': 1,
'rel': 0
},
events: {
'onReady': onMacLinuxPlayerReady
}
});
}
if (!windowsPlayer) {
windowsPlayer = new YT.Player('windows-video-container', {
height: '315',
width: '560',
videoId: 'fX9tsiRvzhg',
playerVars: {
'loop': 1,
'playsinline': 1,
'modestbranding': 1,
'rel': 0
}
});
}
}
function onMacLinuxPlayerReady(event) {
// Now detect OS and show relevant section
detectOS();
}
// Detect operating system
function detectOS() {
const userAgent = window.navigator.userAgent;
const macLinuxSection = document.getElementById('mac-linux-section');
const windowsSection = document.getElementById('windows-section');
const osDetectionMessage = document.getElementById('os-detection-message');
// Hide detection message
osDetectionMessage.style.display = 'none';
// Check if Windows
if (userAgent.indexOf('Windows') !== -1) {
windowsSection.style.display = 'block';
// Play Windows video if player is ready
if (windowsPlayer && typeof windowsPlayer.playVideo === 'function') {
try {
windowsPlayer.playVideo();
} catch (e) {
console.error("Could not play Windows video:", e);
}
}
function a() {
const ua = window.navigator.userAgent;
const mac = document.getElementById('mac-linux');
const windows = document.getElementById('windows');
if (ua.indexOf('Windows') !== -1) {
windows.style.display = 'block';
} else {
// Assume Mac/Linux for all other OSes
macLinuxSection.style.display = 'block';
// Play Mac/Linux video if player is ready
if (macLinuxPlayer && typeof macLinuxPlayer.playVideo === 'function') {
try {
macLinuxPlayer.playVideo();
} catch (e) {
console.error("Could not play Mac/Linux video:", e);
}
}
mac.style.display = 'block';
}
}
document.addEventListener('turbo:load', function() {
// If the YouTube API is already loaded
if (window.YT && window.YT.Player) {
playerReady = true;
setupPlayers();
}
a();
// Function to toggle between OS sections
window.toggleSection = function(section) {
const macLinuxSection = document.getElementById('mac-linux-section');
const windowsSection = document.getElementById('windows-section');
const advancedSection = document.getElementById('advanced-section');
const mac = document.getElementById('mac-linux');
const windows = document.getElementById('windows');
const advanced = document.getElementById('advanced');
// Hide all sections first
macLinuxSection.style.display = 'none';
windowsSection.style.display = 'none';
advancedSection.style.display = 'none';
mac.style.display = 'block';
windows.style.display = 'none';
advanced.style.display = 'none';
// Pause both videos
if (macLinuxPlayer && typeof macLinuxPlayer.pauseVideo === 'function') {
try {
macLinuxPlayer.pauseVideo();
} catch (e) {
console.error("Could not pause Mac/Linux video:", e);
}
}
if (windowsPlayer && typeof windowsPlayer.pauseVideo === 'function') {
try {
windowsPlayer.pauseVideo();
} catch (e) {
console.error("Could not pause Windows video:", e);
}
}
// Show the selected section
if (section === 'windows') {
windowsSection.style.display = 'block';
// Play Windows video
if (windowsPlayer && typeof windowsPlayer.playVideo === 'function') {
try {
windowsPlayer.playVideo();
} catch (e) {
console.error("Could not play Windows video:", e);
}
}
windows.style.display = 'block';
} else if (section === 'advanced') {
advancedSection.style.display = 'block';
advanced.style.display = 'block';
} else {
// Default to Mac/Linux
macLinuxSection.style.display = 'block';
// Play Mac/Linux video
if (macLinuxPlayer && typeof macLinuxPlayer.playVideo === 'function') {
try {
macLinuxPlayer.playVideo();
} catch (e) {
console.error("Could not play Mac/Linux video:", e);
}
}
mac.style.display = 'block';
}
}
// If YouTube API isn't ready yet, we'll wait for it
if (!playerReady) {
// detectOS will be called from onMacLinuxPlayerReady
} else {
// If the API is already ready, detect OS after a short delay
setTimeout(detectOS, 500);
}
const statusDiv = document.getElementById('heartbeat-status');
const nextStepLink = document.getElementById('next-step');
let checkCount = 0;
const maxChecks = 60; // Stop checking after 5 minutes (60 * 5s = 5min)
const maxChecks = 60;
function timeAgoInWords(date) {
const diffInSeconds = Math.floor((new Date() - new Date(date)) / 1000);
const diffInMinutes = Math.floor(diffInSeconds / 60);
const diffInHours = Math.floor(diffInMinutes / 60);
const diffInDays = Math.floor(diffInHours / 24);
const diffInMonths = Math.floor(diffInDays / 30);
const diffInYears = Math.floor(diffInDays / 365);
function timeAgoInWords(d) {
const s = Math.floor((new Date() - new Date(d)) / 1000);
const m = Math.floor(s / 60);
const h = Math.floor(m / 60);
const days = Math.floor(h / 24);
if (diffInYears > 0) {
return diffInYears === 1 ? "1 year ago" : `${diffInYears} years ago`;
} else if (diffInMonths > 0) {
return diffInMonths === 1 ? "1 month ago" : `${diffInMonths} months ago`;
} else if (diffInDays > 0) {
return diffInDays === 1 ? "1 day ago" : `${diffInDays} days ago`;
} else if (diffInHours > 0) {
return diffInHours === 1 ? "1 hour ago" : `${diffInHours} hours ago`;
} else if (diffInMinutes > 0) {
return diffInMinutes === 1 ? "1 minute ago" : `${diffInMinutes} minutes ago`;
if (days > 0) {
return days === 1 ? "1 day ago" : `${days} days ago`;
} else if (h > 0) {
return h === 1 ? "1 hour ago" : `${h} hours ago`;
} else if (m > 0) {
return m === 1 ? "1 minute ago" : `${m} minutes ago`;
} else {
return diffInSeconds === 1 ? "1 second ago" : `${diffInSeconds} seconds ago`;
return s === 1 ? "1 second ago" : `${s} seconds ago`;
}
}
function checkForHeartbeats() {
function check() {
fetch('<%= api_v1_my_heartbeats_most_recent_path %>', {
headers: {
'Authorization': 'Bearer <%= @current_user_api_key %>'
@@ -269,30 +150,27 @@
.then(response => response.json())
.then(data => {
if (data.has_heartbeat) {
// show time ago in human readable format
const timeAgo = timeAgoInWords(data.heartbeat.created_at);
statusDiv.innerHTML = `<p class="success">✅ Heartbeat received ${timeAgo}! You can proceed to the next step.</p>`;
nextStepLink.style.display = 'inline-block';
return; // Stop checking once we get a heartbeat
statusDiv.innerHTML = `<p class="text-green text-xl font-bold">✅ Heartbeat received ${timeAgo}! You can proceed to the next step.</p>`;
nextStepLink.classList.remove('hidden');
return;
}
throw new Error('No heartbeats yet');
})
.catch(error => {
checkCount++;
if (checkCount >= maxChecks) {
statusDiv.innerHTML = '<p class="error">❌ No heartbeats detected after 5 minutes. Please make sure you\'ve run the command above and have the WakaTime plugin installed in your editor.</p>';
return; // Stop checking after max attempts
statusDiv.innerHTML = '<p class="text-red text-lg font-bold">❌ No heartbeats detected after 5 minutes. Please make sure you\'ve run the command above and have the WakaTime plugin installed in your editor.</p>';
return;
}
// Continue checking every 5 seconds
setTimeout(checkForHeartbeats, 5000);
setTimeout(check, 5000);
});
}
// Start checking
checkForHeartbeats();
check();
});
function copyCode(button) {
function copy(button) {
const codeBlock = button.previousElementSibling;
const text = codeBlock.textContent;
navigator.clipboard.writeText(text).then(() => {
@@ -306,13 +184,13 @@
<style>
.progress-indicator {
width: 20px;
height: 20px;
border: 3px solid #eee;
border-top: 3px solid #666;
width: 24px;
height: 24px;
border: 3px solid var(--color-darkless);
border-top: 3px solid var(--color-primary);
border-radius: 50%;
animation: spin 1s linear infinite;
margin: 10px auto;
margin: 0 auto;
}
@keyframes spin {
@@ -320,59 +198,44 @@
100% { transform: rotate(360deg); }
}
.success {
color: #2da44e;
font-weight: bold;
}
.error {
color: #cf222e;
}
.setup-instructions {
width: 100%;
max-width: 100vw;
overflow: hidden;
}
.code-block {
position: relative;
margin-bottom: 1rem;
width: fit-content;
max-width: 75vw;
display: flex;
align-items: flex-end;
gap: 0.5rem;
align-items: flex-start;
gap: 1rem;
flex-wrap: wrap;
}
.code-block code {
flex: 1;
min-width: 0;
white-space: pre-wrap;
word-break: break-all;
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
line-height: 1.4;
}
.copy-button {
position: static;
padding: 0.25rem 0.75rem;
border-radius: 4px;
font-size: 0.875rem;
cursor: pointer;
flex-shrink: 0;
background-color: #0066cc;
color: white;
border: 1px solid #0055aa;
font-weight: bold;
transition: background-color 0.2s;
cursor: pointer;
font-size: 0.875rem;
}
.copy-button:hover {
background-color: #0055aa;
}
.setup-instructions code {
display: block;
width: 75%;
white-space: pre;
overflow-x: auto;
padding-right: 1rem;
box-sizing: border-box;
}
.text-center {
text-align: center;
@media (max-width: 768px) {
.code-block {
flex-direction: column;
align-items: stretch;
}
.code-block code {
margin-bottom: 1rem;
}
iframe {
height: 200px;
}
}
</style>

View File

@@ -1,20 +1,93 @@
<h1>Hackatime Set Up</h1>
<p>Step 2 of 4</p>
<div class="min-h-screen text-white">
<div class="max-w-6xl mx-auto p-4">
<div class="text-center mb-4">
<h1 class="text-4xl font-bold text-primary mb-2">Hackatime Setup</h1>
<div class="flex items-center justify-center gap-2 mb-4">
<div class="w-8 h-8 bg-green rounded-full flex items-center justify-center text-sm font-bold">
<svg class="w-5 h-5 text-white" fill="none" stroke="currentColor" stroke-width="3" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7"/>
</svg>
</div>
<div class="w-16 h-1 bg-green"></div>
<div class="w-8 h-8 bg-primary rounded-full flex items-center justify-center text-sm font-bold">2</div>
<div class="w-16 h-1 bg-darkless"></div>
<div class="w-8 h-8 bg-darkless rounded-full flex items-center justify-center text-sm">3</div>
<div class="w-16 h-1 bg-darkless"></div>
<div class="w-8 h-8 bg-darkless rounded-full flex items-center justify-center text-sm">4</div>
</div>
</div>
<h2>Pick your coding editors</h2>
<em>You can change this later!</em>
<div class="text-center mb-8">
<h2 class="text-3xl font-bold mb-4">What editor do you use?</h2>
<p class="text-secondary text-lg"><em>Let's setup one for now, you can setup more later!</em></p>
</div>
<ul>
<li>
<%= link_to "vs-code (visual studio code)", my_wakatime_setup_step_3_path(anchor: "vs-code") %>
</li>
<li>
<%= link_to "vim", my_wakatime_setup_step_3_path(anchor: "vim") %>
</li>
<li>
<%= link_to "emacs", my_wakatime_setup_step_3_path %>
</li>
<li>
<%= link_to "other", my_wakatime_setup_step_3_path %>
</li>
</ul>
<div class="grid gap-4 max-w-2xl mx-auto">
<div class="bg-dark rounded-lg p-6 hover:bg-darkless transition-colors">
<%= link_to my_wakatime_setup_step_3_path(anchor: "vs-code"), class: "flex items-center gap-4 text-white no-underline" do %>
<div class="w-12 h-12 rounded-lg flex items-center justify-center">
<img src="/images/editor-icons/vs-code-128.png" alt="VS Code" class="w-full h-full object-contain" />
</div>
<div>
<h3 class="text-xl font-bold">Visual Studio Code</h3>
<p class="text-secondary">Most popular code editor, loved by millions</p>
</div>
<div class="ml-auto text-primary flex items-center">
<svg class="w-6 h-6" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 5l7 7-7 7"/>
</svg>
</div>
<% end %>
</div>
<div class="bg-dark rounded-lg p-6 hover:bg-darkless transition-colors">
<%= link_to my_wakatime_setup_step_3_path(anchor: "vim"), class: "flex items-center gap-4 text-white no-underline" do %>
<div class="w-12 h-12 rounded-lg flex items-center justify-center">
<img src="/images/editor-icons/vim-128.png" alt="Vim" class="w-full h-full object-contain" />
</div>
<div>
<h3 class="text-xl font-bold">Vim</h3>
<p class="text-secondary">Terminal-based editor, for the cool kids</p>
</div>
<div class="ml-auto text-primary flex items-center">
<svg class="w-6 h-6" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 5l7 7-7 7"/>
</svg>
</div>
<% end %>
</div>
<div class="bg-dark rounded-lg p-6 hover:bg-darkless transition-colors">
<%= link_to my_wakatime_setup_step_3_path, class: "flex items-center gap-4 text-white no-underline" do %>
<div class="w-12 h-12 rounded-lg flex items-center justify-center">
<img src="/images/editor-icons/emacs-128.png" alt="Emacs" class="w-full h-full object-contain" />
</div>
<div>
<h3 class="text-xl font-bold">Emacs</h3>
<p class="text-secondary">Powerful extensible editor, for the power users</p>
</div>
<div class="ml-auto text-primary flex items-center">
<svg class="w-6 h-6" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 5l7 7-7 7"/>
</svg>
</div>
<% end %>
</div>
<div class="bg-dark rounded-lg p-6 hover:bg-darkless transition-colors">
<%= link_to my_wakatime_setup_step_3_path, class: "flex items-center gap-4 text-white no-underline" do %>
<div class="w-12 h-12 bg-orange rounded-lg flex items-center justify-center text-2xl">🔧</div>
<div>
<h3 class="text-xl font-bold">Not listed here!</h3>
<p class="text-secondary">Any WakaTime-supported editor, there are hundreds!</p>
</div>
<div class="ml-auto text-primary flex items-center">
<svg class="w-6 h-6" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 5l7 7-7 7"/>
</svg>
</div>
<% end %>
</div>
</div>
</div>
</div>

View File

@@ -1,35 +1,65 @@
<h1>Hackatime Set Up</h1>
<p>Step 3 of 4</p>
<div class="min-h-screen text-white">
<div class="max-w-6xl mx-auto p-4">
<div class="text-center mb-4">
<h1 class="text-4xl font-bold text-primary mb-2">Hackatime Setup</h1>
<div class="flex items-center justify-center gap-2 mb-4">
<div class="w-8 h-8 bg-green rounded-full flex items-center justify-center text-sm font-bold">
<svg class="w-5 h-5 text-white" fill="none" stroke="currentColor" stroke-width="3" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7"/>
</svg>
</div>
<div class="w-16 h-1 bg-green"></div>
<div class="w-8 h-8 bg-green rounded-full flex items-center justify-center text-sm font-bold">
<svg class="w-5 h-5 text-white" fill="none" stroke="currentColor" stroke-width="3" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7"/>
</svg>
</div>
<div class="w-16 h-1 bg-green"></div>
<div class="w-8 h-8 bg-primary rounded-full flex items-center justify-center text-sm font-bold">3</div>
<div class="w-16 h-1 bg-darkless"></div>
<div class="w-8 h-8 bg-darkless rounded-full flex items-center justify-center text-sm">4</div>
</div>
</div>
<h2>Install!</h2>
<div class="text-center mb-8">
<h2 class="text-3xl font-bold mb-4">Install Plugin!</h2>
</div>
<section>
<h2>Other</h2>
<p>
<em>Hackatime is WakaTime-compatible, so you can use it with any editor that WakaTime supports. For other editors, please refer to the <a href="https://wakatime.com/plugins">WakaTime docs</a>.</em>
<section class="bg-dark rounded-lg p-6 mb-6">
<h3 class="text-2xl font-bold text-orange mb-4">🔧 Other Editors</h3>
<div class="bg-yellow/50 bg-opacity-10 border border-yellow rounded-lg p-4">
<p class="mb-4">
<em>Hackatime is WakaTime-compatible, so you can use it with any editor that WakaTime supports. For other editors, please refer to the <a href="https://wakatime.com/plugins" class="text-cyan hover:text-blue underline">WakaTime docs</a>.</em>
</p>
<p class="text-yellow font-bold">
⚠️ Note: skip any steps that update your ~/.wakatime.cfg file or change the api_url inside it.
</p>
</div>
</section>
<section id="vs-code" class="bg-dark rounded-lg p-6">
<h3 class="text-2xl font-bold text-blue mb-4">💻 VS Code (Visual Studio Code)</h3>
<div class="space-y-6">
<p class="text-lg">
<em>Hackatime uses the VS Code WakaTime extension. For VS Code, install the <a href="https://marketplace.visualstudio.com/items?itemName=WakaTime.vscode-wakatime" target="_blank" rel="noopener noreferrer" class="text-cyan hover:text-blue underline">WakaTime extension here</a>.</em>
</p>
<div>
<p class="text-lg mb-4">You'll know it works if you see a clock in your status bar, for example I already coded so it shows how much I have coded today</p>
<div>
<img src="https://hc-cdn.hel1.your-objectstorage.com/s/v3/95d2513ce4b0c1c147827d17ecb4c24540cd73cc_p.png" alt="WakaTime status bar in VS Code" class="max-w-full h-auto rounded-lg">
</div>
</div>
<strong>⚠️ Note: skip any steps that update your ~/.wakatime.cfg file or change the api_url inside it.</strong>
</p>
</section>
<section id="vs-code">
<h2>VS Code (Visual Studio Code)</h2>
<p>
<em>Hackatime uses the vs-code WakaTime extension. For VS Code, install the <a href="https://marketplace.visualstudio.com/items?itemName=WakaTime.vscode-wakatime" target="_blank" rel="noopener noreferrer">WakaTime extension here</a>.</em>
</p>
<p>
You'll know it works if you see this in your status bar:
</p>
<img src="https://hc-cdn.hel1.your-objectstorage.com/s/v3/bebe242cc56bcd33bbbffad54fa04d4c66b27ee4_screenshot_2025-03-13_at_11.41.27.png" alt="WakaTime status bar in VS Code">
<%= link_to my_wakatime_setup_step_2_path do %>
<button>Back to editor selection</button>
<% end %>
<%= link_to my_wakatime_setup_step_4_path do %>
<button>Next Step</button>
<% end %>
</section>
<div class="flex gap-4 flex-wrap justify-center">
<%= link_to my_wakatime_setup_step_4_path, class: "bg-primary hover:bg-red text-white px-6 py-3 rounded-lg font-semibold transition-colors" do %>
Next Step
<% end %>
</div>
</div>
</section>
</div>
</div>
<script>
function autoScroll() {

View File

@@ -1,25 +1,62 @@
<h1>Hackatime Set Up</h1>
<div class="min-h-screen text-white">
<div class="max-w-6xl mx-auto p-4">
<div class="text-center mb-4">
<h1 class="text-4xl font-bold text-primary mb-2">Hackatime Setup</h1>
<div class="flex items-center justify-center gap-2 mb-4">
<div class="w-8 h-8 bg-green rounded-full flex items-center justify-center text-sm font-bold">
<svg class="w-5 h-5 text-white" fill="none" stroke="currentColor" stroke-width="3" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7"/>
</svg>
</div>
<div class="w-16 h-1 bg-green"></div>
<div class="w-8 h-8 bg-green rounded-full flex items-center justify-center text-sm font-bold">
<svg class="w-5 h-5 text-white" fill="none" stroke="currentColor" stroke-width="3" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7"/>
</svg>
</div>
<div class="w-16 h-1 bg-green"></div>
<div class="w-8 h-8 bg-green rounded-full flex items-center justify-center text-sm font-bold">
<svg class="w-5 h-5 text-white" fill="none" stroke="currentColor" stroke-width="3" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7"/>
</svg>
</div>
<div class="w-16 h-1 bg-green"></div>
<div class="w-8 h-8 bg-green rounded-full flex items-center justify-center text-sm font-bold">
<svg class="w-5 h-5 text-white" fill="none" stroke="currentColor" stroke-width="3" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7"/>
</svg>
</div>
</div>
</div>
<p>Step 4 of 4</p>
<div class="text-center mb-8">
<h2 class="text-3xl font-bold text-green mt-4 mb-4">🎉 Setup Complete!</h2>
<p class="text-xl text-secondary">
<%= @no_instruction_wording %> You're all set!
</p>
</div>
<p>
<%= @no_instruction_wording %> You're already done!
</p>
<div class="text-center mb-8">
<div class="max-w-lg mx-auto">
<video src="<%= FlavorText.dino_meme_videos.sample %>" autoplay loop muted playsinline controls class="w-full rounded-lg">
</video>
</div>
</div>
<div>
<video src="<%= FlavorText.dino_meme_videos.sample %>" autoplay loop muted playsinline controls></video>
<div class="flex gap-4 flex-wrap justify-center">
<%= link_to my_wakatime_setup_step_2_path, class: "bg-secondary hover:bg-darkless text-white px-6 py-3 rounded-lg font-semibold transition-colors" do %>
Set up another editor
<% end %>
<% if (url = session.dig(:return_data, "url")) %>
<%= link_to url, class: "bg-primary hover:bg-red text-white px-8 py-3 rounded-lg font-semibold transition-colors text-lg" do %>
<%= session.dig(:return_data, "button_text") || "Done" %>
<% end %>
<% else %>
<%= link_to root_path, class: "bg-primary hover:bg-red text-white px-8 py-3 rounded-lg font-semibold transition-colors text-lg" do %>
Get Started
<% end %>
<% end %>
</div>
</div>
</div>
<%= link_to my_wakatime_setup_step_2_path do %>
<button>Set up another editor</button>
<% end %>
<% if (url = session.dig(:return_data, "url")) %>
<%= link_to url do %>
<button><%= session.dig(:return_data, "button_text") || "Done" %></button>
<% end %>
<% else %>
<%= link_to root_path do %>
<button>Done</button>
<% end %>
<% end %>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 920 B

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB