Ollama 설치 안내 UI + 온보딩 Ollama 단계

- StatusBar: 오프라인 3초 후 넛징 버블 표시 ("설치 안내 보기→" 링크)
- OllamaGuideModal: 3단계 설치 안내 (다운로드→모델 pull→자동 연결)
- OnboardingModal: Step 3에 Ollama 설치 안내 단계 추가
- Settings 정보 탭: "초기 설정 안내 다시 보기" 버튼
- system.openExternal IPC 추가 (외부 URL 열기)
This commit is contained in:
Yun Chan 2026-04-05 13:38:26 +09:00
parent ea48168b1e
commit dc06a326b5
6 changed files with 341 additions and 35 deletions

View file

@ -0,0 +1,161 @@
// src/renderer/components/OllamaGuideModal.tsx
// Ollama 설치/설정 안내 모달
import {
Dialog,
DialogTitle,
DialogContent,
DialogActions,
Box,
Typography,
Button,
Divider,
IconButton,
} from '@mui/material'
import CloseIcon from '@mui/icons-material/Close'
import OpenInNewIcon from '@mui/icons-material/OpenInNew'
import ContentCopyIcon from '@mui/icons-material/ContentCopy'
import { d3roPalette, d3roFontMono } from '../theme'
import { Led } from './ds'
interface OllamaGuideModalProps {
open: boolean
onClose: () => void
}
function CodeBlock({ children }: { children: string }): React.ReactElement {
return (
<Box
sx={{
bgcolor: d3roPalette.bg.inset,
borderRadius: '8px',
p: 1.5,
fontFamily: d3roFontMono,
fontSize: '12px',
color: d3roPalette.accent.amber,
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
boxShadow: 'inset 0 1px 4px rgba(0,0,0,0.3)',
}}
>
<span>{children}</span>
<IconButton
size="small"
onClick={() => navigator.clipboard.writeText(children)}
sx={{ color: d3roPalette.text.inactive, '&:hover': { color: d3roPalette.accent.amber } }}
>
<ContentCopyIcon sx={{ fontSize: 14 }} />
</IconButton>
</Box>
)
}
export function OllamaGuideModal({ open, onClose }: OllamaGuideModalProps): React.ReactElement {
const handleOpenLink = (url: string) => {
window.electronAPI.system.openExternal({ url })
}
return (
<Dialog
open={open}
onClose={onClose}
maxWidth="sm"
fullWidth
PaperProps={{
sx: {
bgcolor: d3roPalette.bg.chassis,
backgroundImage: 'none',
border: `1px solid ${d3roPalette.border.subtle}`,
},
}}
>
<DialogTitle
sx={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
fontFamily: d3roFontMono,
fontWeight: 700,
fontSize: '14px',
letterSpacing: '1px',
color: d3roPalette.accent.amber,
py: 1.5,
}}
>
OLLAMA SETUP GUIDE
<IconButton onClick={onClose} size="small" sx={{ color: d3roPalette.text.inactive }}>
<CloseIcon sx={{ fontSize: 18 }} />
</IconButton>
</DialogTitle>
<Divider sx={{ borderColor: d3roPalette.border.subtle }} />
<DialogContent sx={{ bgcolor: d3roPalette.bg.app }}>
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 3, py: 1 }}>
{/* Step 1 */}
<Box>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1, mb: 1 }}>
<Led color="amber" size={8} />
<Typography sx={{ fontFamily: d3roFontMono, fontSize: '12px', fontWeight: 700 }}>
STEP 1 Ollama
</Typography>
</Box>
<Typography variant="body2" sx={{ color: d3roPalette.text.secondary, mb: 1.5 }}>
Ollama는 LLM을 .
</Typography>
<Button
variant="outlined"
size="small"
endIcon={<OpenInNewIcon sx={{ fontSize: 14 }} />}
onClick={() => handleOpenLink('https://ollama.com/download')}
sx={{ fontFamily: d3roFontMono, fontSize: '11px' }}
>
ollama.com/download
</Button>
</Box>
<Divider sx={{ borderColor: d3roPalette.border.subtle }} />
{/* Step 2 */}
<Box>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1, mb: 1 }}>
<Led color="amber" size={8} />
<Typography sx={{ fontFamily: d3roFontMono, fontSize: '12px', fontWeight: 700 }}>
STEP 2
</Typography>
</Box>
<Typography variant="body2" sx={{ color: d3roPalette.text.secondary, mb: 1.5 }}>
pull하세요. :
</Typography>
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 1 }}>
<CodeBlock>ollama pull qwen3:4b</CodeBlock>
<Typography variant="caption" sx={{ color: d3roPalette.text.inactive }}>
모델: ollama pull qwen3:8b ( , )
</Typography>
</Box>
</Box>
<Divider sx={{ borderColor: d3roPalette.border.subtle }} />
{/* Step 3 */}
<Box>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1, mb: 1 }}>
<Led color="green" size={8} />
<Typography sx={{ fontFamily: d3roFontMono, fontSize: '12px', fontWeight: 700 }}>
STEP 3
</Typography>
</Box>
<Typography variant="body2" sx={{ color: d3roPalette.text.secondary }}>
Ollama가 D3RO-VOICE가 .
LED가 !
</Typography>
</Box>
</Box>
</DialogContent>
<DialogActions sx={{ px: 3, pb: 2, bgcolor: d3roPalette.bg.app }}>
<Button onClick={onClose} variant="contained">
</Button>
</DialogActions>
</Dialog>
)
}