Skip to content

Commit 90af3f9

Browse files
committed
Feat:블로그 프로젝트 설명 추가
1 parent 935ee87 commit 90af3f9

File tree

8 files changed

+72
-8
lines changed

8 files changed

+72
-8
lines changed

app/projects/live-demo-modal.tsx

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,9 +246,25 @@ export default function LiveDemoModal({
246246
project.demoImages[currentImageIndex]?.muted !==
247247
false
248248
}
249+
ref={(videoEl) => {
250+
if (videoEl) {
251+
// 재생 속도 설정
252+
const currentImage = project.demoImages?.[currentImageIndex];
253+
const rate = currentImage &&
254+
'playbackRate' in currentImage &&
255+
typeof currentImage.playbackRate === 'number'
256+
? currentImage.playbackRate
257+
: undefined;
258+
if (rate) videoEl.playbackRate = rate;
259+
}
260+
}}
249261
playsInline
250262
preload="auto"
251-
controls={false}
263+
controls={Boolean(
264+
project.demoImages?.[currentImageIndex] &&
265+
'showControls' in project.demoImages[currentImageIndex] &&
266+
project.demoImages[currentImageIndex].showControls === true
267+
)}
252268
disablePictureInPicture={true}
253269
onLoadedData={() => {
254270
// 비디오가 로드되면 로딩 상태 해제

app/projects/project-detail-dialog.tsx

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,9 +189,24 @@ export default function ProjectDetailDialog({
189189
autoPlay={project.thumbnailOptions?.autoplay !== false}
190190
loop={project.thumbnailOptions?.loop !== false}
191191
muted={project.thumbnailOptions?.muted !== false}
192+
ref={(videoEl) => {
193+
if (videoEl) {
194+
// 재생 속도 설정
195+
const rate = project.thumbnailOptions &&
196+
'playbackRate' in project.thumbnailOptions &&
197+
typeof project.thumbnailOptions.playbackRate === 'number'
198+
? project.thumbnailOptions.playbackRate
199+
: undefined;
200+
if (rate) videoEl.playbackRate = rate;
201+
}
202+
}}
192203
playsInline
193204
preload="auto"
194-
controls={false}
205+
controls={Boolean(
206+
project.thumbnailOptions &&
207+
'showControls' in project.thumbnailOptions &&
208+
project.thumbnailOptions.showControls === true
209+
)}
195210
disablePictureInPicture={true}
196211
onError={(e) => console.error("비디오 로딩 오류:", e)}
197212
/>

app/projects/projects-component.tsx

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@ const ProjectCard = ({
3838
transition={{ duration: 0.3 }}
3939
className="relative h-full w-full"
4040
>
41-
{(project.thumbnailType === "video" || isVideoFile(project.thumbnail) || isGifFile(project.thumbnail)) ? (
41+
{project.thumbnailType === "video" ||
42+
isVideoFile(project.thumbnail) ||
43+
isGifFile(project.thumbnail) ? (
4244
<div className="h-full w-full">
4345
<video
4446
src={project.thumbnail}
@@ -48,9 +50,25 @@ const ProjectCard = ({
4850
autoPlay={true}
4951
loop={true}
5052
muted={true}
53+
ref={(videoEl) => {
54+
if (videoEl) {
55+
// 재생 속도 설정
56+
// 명시적으로 숫자 타입으로 변환하여 타입 오류 방지
57+
const rate = project.thumbnailOptions &&
58+
'playbackRate' in project.thumbnailOptions &&
59+
typeof project.thumbnailOptions.playbackRate === 'number'
60+
? project.thumbnailOptions.playbackRate
61+
: undefined;
62+
if (rate) videoEl.playbackRate = rate;
63+
}
64+
}}
5165
playsInline
5266
preload="auto"
53-
controls={false}
67+
controls={Boolean(
68+
project.thumbnailOptions &&
69+
'showControls' in project.thumbnailOptions &&
70+
project.thumbnailOptions.showControls === true
71+
)}
5472
disablePictureInPicture={true}
5573
onError={(e) => console.error("썸네일 비디오 로딩 오류:", e)}
5674
key={`thumbnail-video-${project.id}`}

app/projects/types.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ export interface DemoImage {
99
autoplay?: boolean; // 자동 재생 여부
1010
loop?: boolean; // 반복 여부
1111
muted?: boolean; // 음소거 여부
12+
playbackRate?: number; // 재생 속도 (기본값: 1.0)
13+
showControls?: boolean; // 비디오 컨트롤 UI 표시 여부
1214
}
1315

1416
export interface Project {
@@ -22,6 +24,8 @@ export interface Project {
2224
autoplay?: boolean;
2325
loop?: boolean;
2426
muted?: boolean;
27+
playbackRate?: number; // 재생 속도 (기본값: 1.0)
28+
showControls?: boolean; // 비디오 컨트롤 UI 표시 여부
2529
};
2630
tags: string[];
2731
technologies: string[];

public/projects.json

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
"TypeScript",
1212
"Tailwind CSS",
1313
"Framer Motion",
14-
"Shadcn UI"
14+
"Shadcn UI",
15+
"EsHangul"
1516
],
1617
"githubUrl": "https://github.com/lazy-dinosaur/lazy-dinosaur.github.io",
1718
"serviceUrl": "https://lazy-dinosaur.github.io/",
@@ -24,7 +25,8 @@
2425
"다크 모드 지원 및 테마 전환 기능",
2526
"반응형 레이아웃으로 모든 디바이스 지원",
2627
"목차 자동 생성 및 스크롤 위치 추적",
27-
"코드 구문 강조 및 복사 기능"
28+
"코드 구문 강조 및 복사 기능",
29+
"한글 검색 기능 및 하이라이팅 기능"
2830
],
2931
"lessons": "이 프로젝트를 통해 Next.js의 App Router 구조와 서버 컴포넌트 활용법을 배웠습니다. 또한 마크다운 파일 파싱과 렌더링 최적화, 그리고 애니메이션 처리에 관한 경험을 쌓을 수 있었습니다.",
3032
"challenges": [
@@ -38,8 +40,17 @@
3840
"demoType": "images",
3941
"demoImages": [
4042
{
41-
"url": "/projects/my-blog/my-blog.png",
42-
"description": "My Blog"
43+
"url": "/projects/my-blog/blog-post-example.mp4",
44+
"description": "Neovim과의 통합: Neovim 을 통해 노트를 작성하면서 커맨드를 통해 블로그를 바로 포스팅 할 수 있습니다.",
45+
"playbackRate": 2.5
46+
},
47+
{
48+
"url": "/projects/my-blog/blog-search-example.mp4",
49+
"description": "한글 검색기능: 전체 노트의 타이틀, 태그, 본문을 검색하며 한글의 자모음을 분리하여 검색해 부자연스러운 결과를 없앴습니다."
50+
},
51+
{
52+
"url": "/projects/my-blog/blog-toc-example.mp4",
53+
"description": "목차 생성: 마크다운을 읽으면서 목차를 생성하고 스크롤하여 화면에 보이는 문서상의 위치를 하이라이팅 하며 클릭시 해당 위치로 이동합니다."
4354
}
4455
],
4556
"futurePlans": [
4.92 MB
Binary file not shown.
1.69 MB
Binary file not shown.
7.08 MB
Binary file not shown.

0 commit comments

Comments
 (0)