Skip to content

Commit efcc6ec

Browse files
committed
more small things
1 parent 1a99c4c commit efcc6ec

File tree

2 files changed

+74
-18
lines changed

2 files changed

+74
-18
lines changed

app/components/icons.tsx

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export function IconDownload(props: React.SVGProps<SVGSVGElement>) {
3737
export function IconLoading(props: React.SVGProps<SVGSVGElement>) {
3838
return (
3939
<svg
40-
className='animate-spin'
40+
className="animate-spin"
4141
viewBox="0 0 1024 1024"
4242
fill="currentColor"
4343
height="1em"
@@ -108,7 +108,32 @@ export function IconReload(props: React.SVGProps<SVGSVGElement>) {
108108
width="1em"
109109
{...props}
110110
>
111-
<path strokeLinecap="round" strokeLinejoin="round" d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0 3.181 3.183a8.25 8.25 0 0 0 13.803-3.7M4.031 9.865a8.25 8.25 0 0 1 13.803-3.7l3.181 3.182m0-4.991v4.99" />
111+
<path
112+
strokeLinecap="round"
113+
strokeLinejoin="round"
114+
d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0 3.181 3.183a8.25 8.25 0 0 0 13.803-3.7M4.031 9.865a8.25 8.25 0 0 1 13.803-3.7l3.181 3.182m0-4.991v4.99"
115+
/>
112116
</svg>
113117
)
114-
}
118+
}
119+
120+
export function IconFullscreen(props: React.SVGProps<SVGSVGElement>) {
121+
return (
122+
<svg
123+
xmlns="http://www.w3.org/2000/svg"
124+
fill="none"
125+
viewBox="0 0 24 24"
126+
strokeWidth={1.5}
127+
stroke="currentColor"
128+
height="1em"
129+
width="1em"
130+
{...props}
131+
>
132+
<path
133+
strokeLinecap="round"
134+
strokeLinejoin="round"
135+
d="M3.75 3.75v4.5m0-4.5h4.5m-4.5 0L9 9M3.75 20.25v-4.5m0 4.5h4.5m-4.5 0L9 15M20.25 3.75h-4.5m4.5 0v4.5m0-4.5L15 9m5.25 11.25h-4.5m4.5 0v-4.5m0 4.5L15 15"
136+
/>
137+
</svg>
138+
)
139+
}

app/routes/read.tsx

Lines changed: 46 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
import { IconDownload, IconFullscreen } from '@/components/icons'
12
import processFileParam from '@/lib/process-file-param.server'
23
import { unzipCbz } from '@/lib/unzip-cbz.server'
34
import { LoaderFunctionArgs } from '@remix-run/node'
4-
import { useLoaderData } from '@remix-run/react'
5+
import { Link, useLoaderData, useSearchParams } from '@remix-run/react'
56
import { useState, useEffect } from 'react'
67

78
export async function loader({ request }: LoaderFunctionArgs) {
@@ -16,6 +17,8 @@ export default function Read() {
1617
const [showControls, setShowControls] = useState(true)
1718
const [isFullscreen, setIsFullscreen] = useState(false)
1819
const file = files[index]
20+
const [searchParams] = useSearchParams()
21+
const fileParam = encodeURIComponent(searchParams.get('file') || '')
1922

2023
// Ocultar controles automáticamente después de 3 segundos
2124
useEffect(() => {
@@ -107,22 +110,26 @@ export default function Read() {
107110
}
108111
}
109112

113+
function handleDoubleClick(e: React.MouseEvent) {
114+
e.preventDefault()
115+
setShowControls((prev) => !prev)
116+
}
117+
118+
function handleKeyDown(e: React.KeyboardEvent<HTMLDivElement>) {
119+
if (e.key === 'Enter' || e.key === 'Space') {
120+
e.preventDefault()
121+
setShowControls((prev) => !prev)
122+
}
123+
}
124+
110125
return (
111126
<div className="relative w-screen h-screen bg-black overflow-hidden">
112127
{/* Imagen principal */}
113128
<div
114129
className="w-full h-full flex items-center justify-center cursor-pointer"
115130
onClick={handleImageClick}
116-
onDoubleClick={(ev) => {
117-
ev.preventDefault()
118-
setShowControls((prev) => !prev)
119-
}}
120-
onKeyDown={(e) => {
121-
if (e.key === 'Enter' || e.key === ' ') {
122-
e.preventDefault()
123-
setShowControls((prev) => !prev)
124-
}
125-
}}
131+
onDoubleClick={handleDoubleClick}
132+
onKeyDown={handleKeyDown}
126133
role="button"
127134
tabIndex={0}
128135
aria-label="Navegar por la imagen"
@@ -142,7 +149,14 @@ export default function Read() {
142149
}`}
143150
>
144151
{/* Barra superior */}
145-
<div className="absolute top-0 left-0 right-0 h-16 bg-gradient-to-b from-black/80 to-transparent pointer-events-auto">
152+
<div
153+
className="absolute top-0 left-0 right-0 h-16 bg-gradient-to-b from-black/80 to-transparent pointer-events-auto"
154+
aria-label="Barra superior"
155+
role="button"
156+
tabIndex={0}
157+
onClick={() => setShowControls((prev) => !prev)}
158+
onKeyDown={handleKeyDown}
159+
>
146160
<div className="flex items-center justify-between px-4 py-2">
147161
<div className="flex items-center space-x-4">
148162
<button
@@ -156,19 +170,36 @@ export default function Read() {
156170
</span>
157171
</div>
158172

159-
<div className="flex items-center space-x-2">
173+
<div className="flex items-center gap-x-2">
174+
<Link
175+
to={`/download?file=${fileParam}`}
176+
className="text-white hover:text-gray-300 transition-colors p-2"
177+
aria-label="Descargar"
178+
title="Descargar"
179+
>
180+
<IconDownload />
181+
</Link>
160182
<button
183+
title="Pantalla completa"
184+
aria-label="Pantalla completa"
161185
onClick={toggleFullscreen}
162186
className="text-white hover:text-gray-300 transition-colors p-2"
163187
>
164-
{isFullscreen ? '⛶' : '⛶'}
188+
<IconFullscreen />
165189
</button>
166190
</div>
167191
</div>
168192
</div>
169193

170194
{/* Barra inferior */}
171-
<div className="absolute bottom-0 left-0 right-0 h-16 bg-gradient-to-t from-black/80 to-transparent pointer-events-auto">
195+
<div
196+
className="absolute bottom-0 left-0 right-0 h-16 bg-gradient-to-t from-black/80 to-transparent pointer-events-auto"
197+
aria-label="Barra inferior"
198+
role="button"
199+
tabIndex={0}
200+
onClick={() => setShowControls((prev) => !prev)}
201+
onKeyDown={handleKeyDown}
202+
>
172203
<div className="flex items-center justify-between px-4 py-2">
173204
<button
174205
onClick={goToPrevious}

0 commit comments

Comments
 (0)