Dateien nach "frontend/src/tools" hochladen

This commit is contained in:
2026-05-28 09:24:40 +02:00
parent 180ab6dee7
commit 8b6fe7dd47

View File

@@ -117,6 +117,47 @@ function ShareModal({ item, type, onClose, toast }) {
}
// ── Haupt-Komponente ──────────────────────────────────────────────────────────
// ── Passwort-Prompt Modal (ersetzt window.prompt kein 1Password-Trigger) ────
function PasswordPromptModal({ filename, onSubmit, onCancel }) {
const [pw, setPw] = useState('');
const isMobile = window.innerWidth < 768;
return (
<div style={{position:'fixed',inset:0,background:'rgba(0,0,0,0.8)',zIndex:7000,
display:'flex',alignItems:isMobile?'flex-end':'center',justifyContent:'center',padding:isMobile?0:24}}
onClick={e=>e.target===e.currentTarget&&onCancel()}>
<div style={{background:'#1a1a1e',borderRadius:isMobile?'16px 16px 0 0':16,
width:'100%',maxWidth:400,padding:'22px 20px 28px',border:'1px solid rgba(255,255,255,0.12)'}}>
{isMobile&&<div style={{width:36,height:4,background:'rgba(255,255,255,0.15)',borderRadius:2,margin:'0 auto 14px'}}/>}
<div style={{color:'#fff',fontFamily:"'Space Mono',monospace",fontSize:13,fontWeight:700,marginBottom:6}}>
🔒 Passwortgeschützte Datei
</div>
<div style={{color:'rgba(255,255,255,0.45)',fontFamily:'monospace',fontSize:11,marginBottom:14,lineHeight:1.6}}>
{filename}
</div>
<input
autoFocus
type="text"
autoComplete="off"
data-1p-ignore
data-lpignore="true"
value={pw}
onChange={e=>setPw(e.target.value)}
onKeyDown={e=>{ if(e.key==='Enter'&&pw)onSubmit(pw); if(e.key==='Escape')onCancel(); }}
placeholder="Passwort eingeben…"
style={{...S.inp,marginBottom:12,fontSize:14}}
/>
<div style={{display:'flex',gap:8}}>
<button onClick={()=>{if(pw)onSubmit(pw);}} disabled={!pw}
style={{...S.btn('#4ecdc4'),flex:1,textAlign:'center',padding:'10px 0',opacity:pw?1:0.4}}>
Herunterladen
</button>
<button onClick={onCancel} style={{...S.btn('#ff6b9d',true),padding:'0 16px'}}>Abbrechen</button>
</div>
</div>
</div>
);
}
export default function Dateien({ toast, mobile }) {
const [data, setData] = useState({own:[],shared:[],sharedByMe:[]});
const [folders, setFolders] = useState({own:[],shared:[],sharedByMe:[]});
@@ -126,6 +167,7 @@ export default function Dateien({ toast, mobile }) {
const [tab, setTab] = useState('own');
const [search, setSearch] = useState('');
const [shareItem, setShareItem] = useState(null);
const [pwPrompt, setPwPrompt] = useState(null); // {file}
const [uploading, setUploading] = useState(false);
const [dragOver, setDragOver] = useState(false);
const [newFolder, setNewFolder] = useState(false);
@@ -170,8 +212,7 @@ export default function Dateien({ toast, mobile }) {
if (!res.ok) {
const err = await res.json().catch(()=>({error:'Fehler'}));
if (err.passwordRequired) {
const entered = window.prompt(`🔑 Datei "${file.originalname}" ist passwortgeschützt.\nBitte Passwort eingeben:`);
if (entered !== null) await download(file, entered);
setPwPrompt(file);
return;
}
if (pw && res.status===403) { toast('Falsches Passwort', 'error'); return; }
@@ -236,6 +277,11 @@ export default function Dateien({ toast, mobile }) {
<div style={{padding:mobile?'14px 14px 90px':'36px 44px',maxWidth:960}}>
<ConfirmDialog/>
{shareItem && <ShareModal item={shareItem.item} type={shareItem.type} onClose={()=>{setShareItem(null);load();}} toast={toast}/>}
{pwPrompt && <PasswordPromptModal
filename={pwPrompt.originalname}
onSubmit={pw=>{ setPwPrompt(null); download(pwPrompt, pw); }}
onCancel={()=>setPwPrompt(null)}
/>}
<input ref={fileRef} type="file" onChange={onFileInput} style={{display:'none'}}/>
{/* ── Seitentitel ──────────────────────────────────────────────────── */}