zero-knowledge file sharing
13
fork

Configure Feed

Select the types of activity you want to include in your feed.

upload view tweaks

Juliet 85947c5f 73455de0

+71 -76
+71 -76
web/src/pages/Upload.tsx
··· 12 12 import { formatBytes } from "../lib/utils"; 13 13 14 14 const ghostClass = 15 - "text-muted hover:text-accent-hover border-none bg-transparent min-w-16 py-1.5 -my-1.5 text-[10px] sm:text-xs"; 15 + "text-muted hover:text-accent-hover border-none bg-transparent min-w-16 py-1.5 -my-1.5 text-xs"; 16 16 17 17 const DURATION_UNITS: Record<string, number> = { 18 18 s: 1, ··· 191 191 192 192 const formData = new FormData(); 193 193 formData.append("file", new Blob([ciphertext])); 194 - formData.append("expiresIn", expiryValue().trim()); 194 + formData.append("expiresIn", expiryValue().trim() || maxTtl()); 195 195 formData.append("burnAfterRead", burn() ? "true" : "false"); 196 196 197 197 setStatus("uploading"); ··· 276 276 ? "var(--color-accent)" 277 277 : "var(--color-border)" 278 278 } 279 - stroke-width="7" 279 + stroke-width="5" 280 280 pathLength={dragging() ? "100" : undefined} 281 281 stroke-dasharray={dragging() ? "3 2" : "none"} 282 282 class="transition-all duration-200" ··· 312 312 <button class={btnClass} style={btnStyle} onClick={copyLink}> 313 313 {copied() ? "copied!" : "copy link"} 314 314 </button> 315 - <button 316 - class={ghostClass} 317 - onClick={(e) => { 318 - e.stopPropagation(); 319 - setResultUrl(""); 320 - removeFile(); 321 - }} 322 - > 323 - new drop 324 - </button> 325 315 </div> 326 316 </Show> 327 317 ··· 353 343 </Show> 354 344 355 345 <Show when={view() === "file"}> 356 - <div class="flex flex-col items-center gap-3" style={fadeIn}> 357 - <span 358 - class="text-text flex gap-1.5 truncate" 359 - style={{ "max-width": "clamp(120px, 40vw, 300px)" }} 360 - > 346 + <div class="flex flex-col items-center gap-4" style={fadeIn}> 347 + <div class="flex flex-col items-center gap-2"> 361 348 <span 362 - class="truncate" 363 - style={{ "font-size": "clamp(0.75rem, 2vw, 1rem)" }} 349 + class="text-text flex gap-1.5 truncate" 350 + style={{ "max-width": "clamp(120px, 40vw, 300px)" }} 364 351 > 365 - {file()!.name} 352 + <span 353 + class="truncate" 354 + style={{ "font-size": "clamp(0.75rem, 2vw, 1rem)" }} 355 + > 356 + {file()!.name} 357 + </span> 358 + <span 359 + class={`shrink-0 font-medium ${tooLarge() ? "text-danger" : "text-muted"}`} 360 + style={{ "font-size": "clamp(0.75rem, 2vw, 1rem)" }} 361 + > 362 + {tooLarge() 363 + ? `${formatBytes(file()!.size)} / ${formatBytes(maxFileSize())}` 364 + : formatBytes(file()!.size)} 365 + </span> 366 366 </span> 367 - <span 368 - class={`shrink-0 font-medium ${tooLarge() ? "text-danger" : "text-muted"}`} 369 - style={{ "font-size": "clamp(0.75rem, 2vw, 1rem)" }} 370 - > 371 - {tooLarge() 372 - ? `${formatBytes(file()!.size)} / ${formatBytes(maxFileSize())}` 373 - : formatBytes(file()!.size)} 374 - </span> 375 - </span> 367 + <div class="flex items-center gap-4 text-xs sm:text-sm"> 368 + <input 369 + type="text" 370 + value={expiryValue()} 371 + placeholder={maxTtl() || "7d"} 372 + onInput={(e) => setExpiryValue(e.currentTarget.value)} 373 + onClick={(e) => e.stopPropagation()} 374 + class={`text-accent w-14 border-b bg-transparent text-center font-medium transition-colors outline-none ${expiryTooLong() ? "border-danger" : "border-border focus:border-accent"}`} 375 + /> 376 + <button 377 + class={`flex items-center gap-1.5 transition-colors select-none ${burn() ? "text-accent" : "text-muted hover:text-accent-hover"}`} 378 + onClick={(e) => { 379 + e.stopPropagation(); 380 + setBurn((b) => !b); 381 + }} 382 + > 383 + <div 384 + class={`flex size-4 items-center justify-center rounded border transition-colors ${burn() ? "bg-accent border-accent" : "bg-surface border-border"}`} 385 + > 386 + <Show when={burn()}> 387 + <svg 388 + class="text-bg h-3 w-3" 389 + viewBox="0 0 12 12" 390 + fill="none" 391 + > 392 + <path 393 + d="M2 6l3 3 5-5" 394 + stroke="currentColor" 395 + stroke-width="1.5" 396 + stroke-linecap="round" 397 + stroke-linejoin="round" 398 + /> 399 + </svg> 400 + </Show> 401 + </div> 402 + burn 403 + </button> 404 + </div> 405 + </div> 376 406 <button 377 407 class={`${btnClass} disabled:cursor-not-allowed disabled:opacity-40`} 378 408 style={btnStyle} 379 - disabled={tooLarge()} 409 + disabled={tooLarge() || expiryTooLong()} 380 410 onClick={(e) => { 381 411 e.stopPropagation(); 382 412 handleUpload(); 383 413 }} 384 414 > 385 415 upload 386 - </button> 387 - <button 388 - class={ghostClass} 389 - onClick={(e) => { 390 - e.stopPropagation(); 391 - removeFile(); 392 - }} 393 - > 394 - remove 395 416 </button> 396 417 </div> 397 418 </Show> ··· 434 455 /> 435 456 </div> 436 457 437 - <Show when={!loading() && view() !== "result"}> 438 - <div class="mx-auto mt-6 flex w-fit flex-col gap-4 text-sm"> 439 - <label class="text-muted flex items-center gap-3 select-none"> 440 - lifetime 441 - <input 442 - type="text" 443 - value={expiryValue()} 444 - placeholder="30m, 24h, 7d" 445 - onInput={(e) => setExpiryValue(e.currentTarget.value)} 446 - class={`bg-surface text-accent w-28 rounded-md border px-2 py-1 text-center font-medium transition-colors outline-none ${expiryTooLong() ? "border-danger" : "border-border focus:border-accent"}`} 447 - /> 448 - </label> 449 - <label 450 - class="text-muted flex items-center gap-3 select-none" 451 - onClick={() => setBurn((b) => !b)} 458 + <Show when={view() === "file" || view() === "result"}> 459 + <div class="mt-4 flex justify-center" style={fadeIn}> 460 + <button 461 + class={ghostClass} 462 + onClick={() => { 463 + setResultUrl(""); 464 + removeFile(); 465 + }} 452 466 > 453 - burn after read 454 - <div 455 - class={`flex size-5 items-center justify-center rounded border transition-colors ${burn() ? "bg-accent border-accent" : "bg-surface border-border"}`} 456 - > 457 - <Show when={burn()}> 458 - <svg 459 - class="text-bg h-3.5 w-3.5" 460 - viewBox="0 0 12 12" 461 - fill="none" 462 - > 463 - <path 464 - d="M2 6l3 3 5-5" 465 - stroke="currentColor" 466 - stroke-width="1.5" 467 - stroke-linecap="round" 468 - stroke-linejoin="round" 469 - /> 470 - </svg> 471 - </Show> 472 - </div> 473 - </label> 467 + new drop 468 + </button> 474 469 </div> 475 470 </Show> 476 471