Menu
Public repository / master
AkurAI-Drive / desktop/ui/index.html
Latest change 2a1ed73acfbc6091a9fcdba5a28f55de9e2d75a4 - feat: native email+password sign-in (no browser) by olibuijr
<!doctype html>
<html lang="en" data-theme="akurai">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>AkurAI Drive</title>
<link href="https://fonts.googleapis.com/css2?family=Sora:wght@600;700;800&family=Inter:wght@400;450;500;600&display=swap" rel="stylesheet">
<link rel="stylesheet" href="app.css">
</head>
<body>
<!-- ===== SIGN IN ===== -->
<section id="screen-signin" class="screen center hidden">
<div class="signin-card">
<svg class="mark mark-lg" viewBox="0 0 32 32" aria-hidden="true">
<defs><linearGradient id="gsign" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#5b8cff"/><stop offset="1" stop-color="#7af0d0"/></linearGradient></defs>
<g fill="url(#gsign)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.38 3.23c1.05-2.23 4.19-2.23 5.24 0l11.05 23.62A2.91 2.91 0 0 1 27.03 31h-3.42c-1.17 0-2.22-.7-2.67-1.78l-2.05-4.93h-5.78l-2.05 4.93A2.9 2.9 0 0 1 8.39 31H4.97a2.91 2.91 0 0 1-2.64-4.15L13.38 3.23ZM16 11.17l-5.13 13.1h10.26L16 11.17Z"/>
<path d="M10.38 20.54h11.24a2.23 2.23 0 0 1 0 4.46H10.38a2.23 2.23 0 0 1 0-4.46Z"/>
</g>
</svg>
<h1>AkurAI Drive</h1>
<p class="muted">Your private cloud, hosted in Iceland. Sign in with your AkurAI account to access your files.</p>
<form id="signin-form" class="signin-form" autocomplete="on">
<div class="field">
<label for="signin-email">Email</label>
<input id="signin-email" type="email" name="email" autocomplete="username" spellcheck="false" placeholder="you@example.com" required>
</div>
<div class="field">
<label for="signin-password">Password</label>
<input id="signin-password" type="password" name="password" autocomplete="current-password" placeholder="Your password" required>
</div>
<p id="signin-error" class="signin-error hidden" role="alert"></p>
<button id="btn-signin-pw" type="submit" class="btn btn-primary btn-lg">Sign in</button>
</form>
<button id="btn-signin" class="link-btn">Sign in with browser instead</button>
<p id="signin-hint" class="muted small"></p>
</div>
</section>
<!-- ===== SETUP (pick bucket + folder) ===== -->
<section id="screen-setup" class="screen center hidden">
<div class="signin-card wide">
<svg class="mark" viewBox="0 0 32 32" aria-hidden="true">
<g fill="url(#gsign)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.38 3.23c1.05-2.23 4.19-2.23 5.24 0l11.05 23.62A2.91 2.91 0 0 1 27.03 31h-3.42c-1.17 0-2.22-.7-2.67-1.78l-2.05-4.93h-5.78l-2.05 4.93A2.9 2.9 0 0 1 8.39 31H4.97a2.91 2.91 0 0 1-2.64-4.15L13.38 3.23ZM16 11.17l-5.13 13.1h10.26L16 11.17Z"/>
<path d="M10.38 20.54h11.24a2.23 2.23 0 0 1 0 4.46H10.38a2.23 2.23 0 0 1 0-4.46Z"/>
</g>
</svg>
<h2>Choose what to sync</h2>
<p class="muted">Pick a storage bucket and the local folder it mirrors.</p>
<div class="field">
<label for="setup-bucket">Bucket</label>
<select id="setup-bucket"></select>
</div>
<div class="field">
<label for="setup-folder">Local sync folder</label>
<input id="setup-folder" type="text" spellcheck="false" placeholder="~/AkurAI Drive">
</div>
<button id="btn-setup-save" class="btn btn-primary btn-lg">Start syncing</button>
<button id="btn-setup-signout" class="btn btn-ghost btn-sm">Sign out</button>
</div>
</section>
<!-- ===== MAIN APP ===== -->
<section id="screen-app" class="screen hidden">
<!-- top bar -->
<header class="topbar">
<div class="topbar-left">
<svg class="mark" viewBox="0 0 32 32" aria-hidden="true">
<g fill="url(#gsign)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.38 3.23c1.05-2.23 4.19-2.23 5.24 0l11.05 23.62A2.91 2.91 0 0 1 27.03 31h-3.42c-1.17 0-2.22-.7-2.67-1.78l-2.05-4.93h-5.78l-2.05 4.93A2.9 2.9 0 0 1 8.39 31H4.97a2.91 2.91 0 0 1-2.64-4.15L13.38 3.23ZM16 11.17l-5.13 13.1h10.26L16 11.17Z"/>
<path d="M10.38 20.54h11.24a2.23 2.23 0 0 1 0 4.46H10.38a2.23 2.23 0 0 1 0-4.46Z"/>
</g>
</svg>
<nav id="breadcrumb" class="breadcrumb" aria-label="path"></nav>
</div>
<div class="topbar-center">
<div class="search">
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true"><circle cx="11" cy="11" r="7" stroke="currentColor" stroke-width="1.8"/><path d="m20 20-3.2-3.2" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg>
<input id="search" type="text" placeholder="Search this folder">
</div>
</div>
<div class="topbar-right">
<span id="sync-dot" class="sync-dot idle" title="idle"></span>
<div class="account">
<button id="account-btn" class="account-btn" aria-haspopup="true">
<span id="account-initial" class="avatar">A</span>
</button>
<div id="account-menu" class="menu hidden" role="menu">
<div class="menu-head">
<div id="account-email" class="menu-email">—</div>
<div id="account-sub" class="menu-sub muted small">Signed in</div>
</div>
<button class="menu-item" data-act="open-folder" role="menuitem">Open folder</button>
<button class="menu-item" data-act="copy-log" role="menuitem">Copy log path</button>
<div class="menu-sep"></div>
<button class="menu-item danger" data-act="signout" role="menuitem">Sign out</button>
</div>
</div>
</div>
</header>
<!-- toolbar -->
<div class="toolbar">
<div class="toolbar-left">
<button id="btn-upload" class="btn btn-primary btn-sm">
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true"><path d="M12 16V4m0 0L7 9m5-5 5 5" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/><path d="M4 17v2a1 1 0 0 0 1 1h14a1 1 0 0 0 1-1v-2" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg>
Upload
</button>
<button id="btn-mkdir" class="btn btn-ghost btn-sm">
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true"><path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V7Z" stroke="currentColor" stroke-width="1.7"/><path d="M12 11v4m-2-2h4" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"/></svg>
New folder
</button>
<button id="btn-sync" class="btn btn-ghost btn-sm">
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true"><path d="M4 11a8 8 0 0 1 14-5m2-2v5h-5M20 13a8 8 0 0 1-14 5m-2 2v-5h5" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"/></svg>
Sync now
</button>
</div>
<div class="toolbar-right">
<select id="sort" class="mini-select" title="Sort">
<option value="name">Name</option>
<option value="size">Size</option>
<option value="modified">Modified</option>
</select>
<div class="view-toggle">
<button id="view-grid" class="vt active" title="Grid"><svg viewBox="0 0 24 24" fill="none"><rect x="3" y="3" width="7" height="7" rx="1.5" stroke="currentColor" stroke-width="1.8"/><rect x="14" y="3" width="7" height="7" rx="1.5" stroke="currentColor" stroke-width="1.8"/><rect x="3" y="14" width="7" height="7" rx="1.5" stroke="currentColor" stroke-width="1.8"/><rect x="14" y="14" width="7" height="7" rx="1.5" stroke="currentColor" stroke-width="1.8"/></svg></button>
<button id="view-list" class="vt" title="List"><svg viewBox="0 0 24 24" fill="none"><path d="M8 6h13M8 12h13M8 18h13M3.5 6h.01M3.5 12h.01M3.5 18h.01" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg></button>
</div>
</div>
</div>
<!-- main browser -->
<main id="browser" class="browser">
<div id="state-loading" class="state hidden"><div class="spinner"></div><p>Loading…</p></div>
<div id="state-empty" class="state hidden">
<svg viewBox="0 0 24 24" fill="none" class="state-ico"><path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V7Z" stroke="currentColor" stroke-width="1.6"/></svg>
<p>This folder is empty</p>
<span class="muted small">Drag files here or use Upload</span>
</div>
<div id="state-error" class="state hidden">
<svg viewBox="0 0 24 24" fill="none" class="state-ico"><circle cx="12" cy="12" r="9" stroke="currentColor" stroke-width="1.6"/><path d="M12 7v6m0 3.5h.01" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg>
<p id="error-text">Something went wrong</p>
<button class="btn btn-ghost btn-sm" id="btn-retry">Retry</button>
</div>
<div id="grid" class="grid"></div>
</main>
<!-- drop overlay -->
<div id="drop-overlay" class="drop-overlay hidden">
<div class="drop-inner">
<svg viewBox="0 0 24 24" fill="none"><path d="M12 16V4m0 0L7 9m5-5 5 5" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg>
<p>Drop to upload to this folder</p>
</div>
</div>
</section>
<!-- context menu -->
<div id="ctx" class="ctx hidden" role="menu">
<button class="ctx-item" data-act="download" role="menuitem">Download</button>
<button class="ctx-item" data-act="rename" role="menuitem">Rename</button>
<button class="ctx-item danger" data-act="delete" role="menuitem">Delete</button>
</div>
<!-- prompt modal -->
<div id="modal" class="modal hidden" role="dialog" aria-modal="true">
<div class="sheet">
<h3 id="modal-title">Title</h3>
<input id="modal-input" type="text" spellcheck="false">
<div class="modal-actions">
<button id="modal-cancel" class="btn btn-ghost btn-sm">Cancel</button>
<button id="modal-ok" class="btn btn-primary btn-sm">OK</button>
</div>
</div>
</div>
<!-- toast host -->
<div id="toasts" class="toasts"></div>
<!-- shared gradient def for inline marks -->
<svg width="0" height="0" style="position:absolute"><defs><linearGradient id="gsign" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#5b8cff"/><stop offset="1" stop-color="#7af0d0"/></linearGradient></defs></svg>
<script src="app.js"></script>
</body>
</html>