-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstart.html
More file actions
62 lines (62 loc) · 7.8 KB
/
Copy pathstart.html
File metadata and controls
62 lines (62 loc) · 7.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="referrer" content="no-referrer">
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'none'; frame-src 'none'; object-src 'none'; base-uri 'none'; form-action 'none'">
<script>
const launchQuery = new URLSearchParams(window.location.search);
document.documentElement.dataset.theme = launchQuery.get('theme') === 'light' ? 'light' : 'dark';
document.documentElement.dataset.themePreference = launchQuery.get('preference') || 'system';
</script>
<title>DocPilot</title>
<style>
*{box-sizing:border-box;margin:0;padding:0}
:root{--bg:#101114;--panel:#18191c;--panel-2:#1e2024;--border:#2c2e33;--text:#f1f1f2;--muted:#a1a4ab;--faint:#71757e;--hover:#24262a;--button:#f1f1f2;--button-text:#111215;--shadow:0 28px 70px rgba(0,0,0,.42);color-scheme:dark}
:root[data-theme="light"]{--bg:#dededf;--panel:#f8f8f8;--panel-2:#f1f1f2;--border:#dedfe2;--text:#17181b;--muted:#696d75;--faint:#969aa2;--hover:#ececef;--button:#191a1d;--button-text:#fff;--shadow:0 28px 70px rgba(24,25,28,.2);color-scheme:light}
body{height:100vh;overflow:hidden;background:var(--bg);color:var(--text);font:13px/1.45 -apple-system,BlinkMacSystemFont,"Inter",sans-serif;-webkit-font-smoothing:antialiased;user-select:none;-webkit-app-region:drag}
.titlebar{height:48px}
.launch-stage{height:calc(100vh - 48px);display:grid;place-items:center;padding:28px 40px 52px}
.launch-shell{width:min(760px,100%);height:min(440px,100%);display:grid;grid-template-columns:minmax(0,.92fr) minmax(0,1.08fr);grid-template-rows:1fr auto;overflow:hidden;border:1px solid var(--border);border-radius:12px;background:var(--panel);box-shadow:var(--shadow);-webkit-app-region:no-drag}
.launch-intro{padding:34px 34px 28px;border-right:1px solid var(--border);display:flex;flex-direction:column;min-width:0;min-height:0}
.brand{display:flex;align-items:center;gap:11px}.brand img{width:31px;height:31px;border-radius:8px}.brand strong{font-size:14px;letter-spacing:-.01em}
.eyebrow{margin-top:56px;color:var(--faint);font-size:10px;font-weight:700;letter-spacing:.12em;text-transform:uppercase}
h1{margin-top:10px;font-size:22px;line-height:1.28;letter-spacing:-.018em;font-weight:560}
.intro-copy{margin-top:14px;max-width:280px;color:var(--muted);font-size:12px;line-height:1.65}
.launch-recents{min-width:0;min-height:0;padding:32px 26px 22px;display:flex;flex-direction:column}.recents-head{display:flex;align-items:end;justify-content:space-between;padding:0 8px 13px}.recents-head strong{font-size:13px}.recents-head span{color:var(--faint);font-size:10px;letter-spacing:.06em;text-transform:uppercase}
.recent-list{flex:1;min-height:0;overflow:auto;border-top:1px solid var(--border)}.recent-empty{padding:54px 12px;text-align:center;color:var(--faint);font-size:12px}
.recent-item{position:relative;display:flex;align-items:center;gap:10px;min-height:58px;padding:10px 34px 10px 9px;border-bottom:1px solid var(--border);cursor:pointer}.recent-item:hover{background:var(--hover)}.recent-info{min-width:0}.recent-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:12px;font-weight:620}.recent-path{margin-top:3px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--faint);font:10px ui-monospace,SFMono-Regular,Menlo,monospace}.recent-del{position:absolute;right:8px;top:17px;width:25px;height:25px;border:0;border-radius:5px;background:transparent;color:var(--faint);font:16px inherit;opacity:0;cursor:pointer}.recent-item:hover .recent-del,.recent-del:focus-visible{opacity:1}.recent-del:hover{background:var(--panel-2);color:var(--text)}
.launch-action{grid-column:1/-1;display:flex;align-items:center;justify-content:space-between;gap:20px;padding:18px 22px;border-top:1px solid var(--border);background:var(--panel-2)}.launch-action p{color:var(--faint);font-size:11px}.open-btn{height:36px;padding:0 22px;border:0;border-radius:6px;background:var(--button);color:var(--button-text);font:650 12px inherit;cursor:pointer}.open-btn:hover{filter:brightness(.92)}
.loading{position:fixed;inset:0;z-index:20;display:none;place-items:center;background:color-mix(in srgb,var(--bg) 80%,transparent);backdrop-filter:blur(8px);-webkit-app-region:no-drag}.loading.show{display:grid}.loading-box{display:flex;align-items:center;gap:12px;padding:16px 18px;border:1px solid var(--border);border-radius:8px;background:var(--panel);box-shadow:var(--shadow)}.spin{width:17px;height:17px;border:2px solid var(--border);border-top-color:var(--text);border-radius:50%;animation:spin .7s linear infinite}.loading-title{font-weight:650}.loading-sub{max-width:280px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--faint);font:10px ui-monospace,SFMono-Regular,Menlo,monospace}@keyframes spin{to{transform:rotate(1turn)}}
@media(max-width:720px){.launch-stage{padding:20px}.launch-shell{grid-template-columns:1fr;height:min(500px,100%)}.launch-intro{display:none}.launch-action{grid-column:1}.launch-recents{padding-top:24px}}
</style>
</head>
<body>
<div class="titlebar"></div>
<main class="launch-stage">
<section class="launch-shell" aria-label="DocPilot 시작">
<div class="launch-intro">
<div class="brand"><img src="assets/icon.png" alt=""><strong>DocPilot</strong></div>
<span class="eyebrow">Document workbench</span>
<h1>프로젝트를 선택해<br>작업을 이어가세요.</h1>
<p class="intro-copy">프로젝트의 문서와 터미널을 한 작업 공간에서 연결합니다. 마지막 테마와 최근 프로젝트를 그대로 이어갑니다.</p>
</div>
<div class="launch-recents">
<div class="recents-head"><strong>최근 프로젝트</strong><span>Local</span></div>
<div class="recent-list" id="recent-list"><div class="recent-empty">최근 열었던 프로젝트가 없습니다.</div></div>
</div>
<footer class="launch-action"><p>폴더를 선택하면 문서 인덱스를 로컬에서 준비합니다.</p><button class="open-btn" id="open-btn">프로젝트 폴더 열기</button></footer>
</section>
</main>
<div class="loading" id="loading"><div class="loading-box"><div class="spin"></div><div><div class="loading-title">문서 불러오는 중</div><div class="loading-sub" id="loading-path">workspace scan</div></div></div></div>
<script>
const dp=window.docpilot;
function esc(s){return String(s).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"')}
async function render(){const list=await dp.getRecent();const el=document.getElementById('recent-list');if(!list.length){el.innerHTML='<div class="recent-empty">최근 열었던 프로젝트가 없습니다.</div>';return}el.innerHTML='';list.forEach(p=>{const parts=p.replace(/\\/g,'/').split('/').filter(Boolean);const item=document.createElement('div');item.className='recent-item';item.tabIndex=0;item.innerHTML=`<div class="recent-info"><div class="recent-name">${esc(parts.at(-1)||p)}</div><div class="recent-path">${esc(p)}</div></div><button class="recent-del" type="button" title="최근 목록에서 제거" aria-label="최근 목록에서 제거">×</button>`;item.addEventListener('click',()=>openFolderPath(p));item.addEventListener('keydown',event=>{if(event.key==='Enter')openFolderPath(p)});item.querySelector('.recent-del').addEventListener('click',async event=>{event.stopPropagation();await dp.removeRecent(p);render()});el.appendChild(item)})}
function openFolderPath(p){document.getElementById('loading-path').textContent=p;document.getElementById('loading').classList.add('show');dp.openFolder(p).catch(()=>document.getElementById('loading').classList.remove('show'))}
document.getElementById('open-btn').onclick=async()=>{const p=await dp.openFolderDialog();if(p)openFolderPath(p)};
render();
</script>
</body>
</html>