96 lines
3.3 KiB
TypeScript
96 lines
3.3 KiB
TypeScript
import React, { useEffect, useState } from 'react';
|
||
import type { AutostartResponse } from '@shared/types';
|
||
import { inboxApi } from '../../api.js';
|
||
|
||
export function AutostartSection(): React.ReactElement {
|
||
const [data, setData] = useState<AutostartResponse | null>(null);
|
||
const [expanded, setExpanded] = useState(false);
|
||
|
||
useEffect(() => {
|
||
void (async () => {
|
||
const r = await inboxApi.getAutostart();
|
||
setData(r);
|
||
})();
|
||
}, []);
|
||
|
||
async function onToggle(e: React.ChangeEvent<HTMLInputElement>): Promise<void> {
|
||
const r = await inboxApi.setAutostart(e.target.checked);
|
||
setData(r);
|
||
}
|
||
|
||
// Task 24 — 현재 openAtLogin 값으로 다시 setLoginItemSettings 호출 → mismatch 복구.
|
||
// (예: registry 누락된 채로 withArgs.openAtLogin=true 인 경우 등.)
|
||
async function onReregister(): Promise<void> {
|
||
if (!data) return;
|
||
const r = await inboxApi.setAutostart(data.openAtLogin);
|
||
setData(r);
|
||
}
|
||
|
||
if (data === null) {
|
||
return <div style={{ fontSize: 12, color: '#666' }}>로딩 중...</div>;
|
||
}
|
||
|
||
const d = data.diagnostic;
|
||
// v0.2.7 F12 deeper fix — withArgs vs noArgs 의 openAtLogin 불일치, 또는
|
||
// executableWillLaunchAtLogin = false 면 mismatch 로 간주 (등록은 됐지만 실제론
|
||
// 로그인 시 실행되지 않을 수 있는 상태).
|
||
const mismatch = d.withArgs.openAtLogin !== d.noArgs.openAtLogin
|
||
|| (data.openAtLogin && !d.withArgs.executableWillLaunchAtLogin);
|
||
|
||
return (
|
||
<div>
|
||
<label style={{ display: 'flex', gap: 8, alignItems: 'center', fontSize: 13 }}>
|
||
<input type="checkbox" checked={data.openAtLogin} onChange={onToggle} />
|
||
앱 시작 시 자동으로 실행
|
||
</label>
|
||
{mismatch && (
|
||
<div style={{ color: '#c33', fontSize: 12, marginTop: 4 }}>
|
||
⚠️ 등록 상태 불일치 감지 — 진단 정보 확인 후 재등록을 시도하세요.
|
||
</div>
|
||
)}
|
||
<div style={{ marginTop: 6 }}>
|
||
<button
|
||
onClick={() => { void onReregister(); }}
|
||
style={{ fontSize: 12, padding: '4px 10px' }}
|
||
>
|
||
재등록
|
||
</button>
|
||
</div>
|
||
<button
|
||
onClick={() => setExpanded(!expanded)}
|
||
style={{
|
||
background: 'none',
|
||
border: 'none',
|
||
cursor: 'pointer',
|
||
fontSize: 12,
|
||
color: '#0a4b80',
|
||
marginTop: 4,
|
||
padding: 0
|
||
}}
|
||
>
|
||
{expanded ? '▾' : '▸'} 진단 정보
|
||
</button>
|
||
{expanded && (
|
||
<div
|
||
style={{
|
||
fontSize: 11,
|
||
lineHeight: 1.6,
|
||
marginTop: 4,
|
||
fontFamily: 'monospace',
|
||
background: '#f5f5f5',
|
||
padding: 8,
|
||
borderRadius: 4,
|
||
wordBreak: 'break-all'
|
||
}}
|
||
>
|
||
<div>표준 (--hidden 인자): openAtLogin={String(d.withArgs.openAtLogin)}, willLaunch={String(d.withArgs.executableWillLaunchAtLogin)}</div>
|
||
<div>비교 (인자 없이): openAtLogin={String(d.noArgs.openAtLogin)}, willLaunch={String(d.noArgs.executableWillLaunchAtLogin)}</div>
|
||
<div>실행 파일 경로: {d.execPath}</div>
|
||
{d.registryPath !== undefined && <div>registry 경로: {d.registryPath}</div>}
|
||
{d.registryValue !== undefined && <div>registry 값: {d.registryValue ?? '(없음)'}</div>}
|
||
</div>
|
||
)}
|
||
</div>
|
||
);
|
||
}
|