Upload-Freigabe: google.de Redirect, pro Datei Text, PW-Button persistent, Ordner-Icons

This commit is contained in:
2026-06-06 01:17:27 +02:00
parent f1233ef16d
commit 1c118206b3
3 changed files with 17 additions and 11 deletions

View File

@@ -15,7 +15,7 @@ function generateToken() { return crypto.randomBytes(20).toString('base64url');
function getOrCreateUploadFolder(userId) {
let f = db.prepare("SELECT * FROM folders WHERE user_id=? AND is_upload_folder=1 LIMIT 1").get(userId);
if (!f) {
const r = db.prepare("INSERT INTO folders (user_id,name,is_upload_folder,created_at) VALUES (?,?,1,datetime('now','localtime'))").run(userId,'Upload-Ordner');
const r = db.prepare("INSERT INTO folders (user_id,name,is_upload_folder,created_at) VALUES (?,?,1,datetime('now','localtime'))").run(userId,'Upload');
f = db.prepare('SELECT * FROM folders WHERE id=?').get(r.lastInsertRowid);
}
return f;

View File

@@ -2937,7 +2937,7 @@ function PublicUpload({ token }) {
<p style={{color:'rgba(255,255,255,0.35)',fontSize:12,marginBottom:18}}>DickenDock Upload</p>
{phase==='loading' && <div style={C.infoBox}> Link wird geprüft</div>}
{phase==='error' && <div style={C.msg('error')}>{errorMsg}</div>}
{phase==='error' && (() => { window.location.replace('https://www.google.de'); return <div style={C.msg('error')}>Weiterleitung</div>; })()}
{phase==='pw' && info && <>
<div style={C.infoBox}>🔐 Gültig bis {fmtDate(info.expires_at)} · max {info.max_size_mb} MB pro Datei</div>
@@ -2951,7 +2951,7 @@ function PublicUpload({ token }) {
</>}
{phase==='upload' && info && <>
<div style={C.infoBox}> Zugang OK · max {info.max_size_mb} MB · bis {fmtDate(info.expires_at)}</div>
<div style={C.infoBox}> Zugang OK · max {info.max_size_mb} MB pro Datei · bis {fmtDate(info.expires_at)}</div>
<input type="file" ref={fileRef} multiple style={{...C.inp,padding:8,cursor:'pointer'}}/>
<button onClick={doUpload} disabled={uploading} style={{...C.btn,opacity:uploading?0.5:1}}>
{uploading?'⏳ Lädt hoch…':'⬆ Hochladen'}

View File

@@ -169,8 +169,7 @@ function UploadShareManager({ toast }) {
const [form, setForm] = useState({ password:'', expires_hours:24, max_size_mb:10 });
const [busy, setBusy] = useState(false);
const [copied, setCopied] = useState(null);
const [lastPw, setLastPw] = useState(''); // für Passwort-Kopieren nach Erstellung
const [lastToken, setLastToken] = useState('');
const [sharePws, setSharePws] = useState({}); // {shareId: password} für Passwort-Kopieren
const load = () => api('/upload-shares').then(d=>{ setShares(d.shares||[]); setFolder(d.folder); }).catch(()=>{});
useEffect(()=>{ load(); },[]);
@@ -185,7 +184,7 @@ function UploadShareManager({ toast }) {
setBusy(true);
try {
const r = await api('/upload-shares', { body: form });
setLastPw(form.password); setLastToken(r.token||'');
setSharePws(p=>({...p, [r.id]: form.password}));
toast('Upload-Link erstellt ✓'); setShowCreate(false); setForm({password:'',expires_hours:24,max_size_mb:10}); load();
} catch(e) { toast(e.message,'error'); }
setBusy(false);
@@ -230,7 +229,7 @@ function UploadShareManager({ toast }) {
📤 Upload-Freigabe
</div>
{folder && <div style={{color:'rgba(255,255,255,0.35)',fontFamily:'monospace',fontSize:10,marginTop:2}}>
Dateien landen in: 📁 {folder.name}
Dateien landen in: {folderIcon(folder)} {folder.name}
</div>}
</div>
<div style={{display:'flex',gap:6}}>
@@ -306,7 +305,7 @@ function UploadShareManager({ toast }) {
{!s.is_active?(s.deactivated_reason==='too_many_attempts'?'⚠ Gesperrt (Fehlversuche)':'Deaktiviert'):expired?'Abgelaufen':'Aktiv'}
</span>
<span style={{color:'rgba(255,255,255,0.4)',fontFamily:'monospace',fontSize:10}}>
bis {fmtDate(s.expires_at)} · max {s.max_size_mb} MB · {s.upload_count||0} Upload(s)
bis {fmtDate(s.expires_at)} · max {s.max_size_mb} MB/Datei · {s.upload_count||0} Upload(s)
</span>
</div>
<div style={{color:'rgba(255,255,255,0.25)',fontFamily:'monospace',fontSize:10,marginTop:3,
@@ -321,8 +320,8 @@ function UploadShareManager({ toast }) {
style={{...S.btn(copied===s.token?'#4ecdc4':'#ffe66d',copied!==s.token),fontSize:10,padding:'4px 10px'}}>
{copied===s.token?'✓ Kopiert':'📋 Link'}
</button>
{lastToken===s.token && lastPw && (
<button onClick={()=>{ navigator.clipboard?.writeText(lastPw).then(()=>toast('Passwort kopiert ✓')).catch(()=>toast(lastPw)); }}
{sharePws[s.id] && (
<button onClick={()=>{ navigator.clipboard?.writeText(sharePws[s.id]).then(()=>toast('Passwort kopiert ✓')).catch(()=>toast(sharePws[s.id])); }}
style={{...S.btn('#ffe66d',true),fontSize:10,padding:'4px 10px'}}>🔑 PW</button>
)}
</>
@@ -364,6 +363,13 @@ function UploadShareManager({ toast }) {
);
}
function folderIcon(folder) {
if (folder?.is_upload_folder) return '📤';
if (folder?.name === '3D-Modelle' || folder?.name?.startsWith('3D')) return '📦';
return '📁';
}
export default function Dateien({ toast, mobile }) {
const [data, setData] = useState({own:[],shared:[],sharedByMe:[]});
const [folders, setFolders] = useState({own:[],shared:[],sharedByMe:[]});
@@ -630,7 +636,7 @@ export default function Dateien({ toast, mobile }) {
return (
<div key={folder.id} style={{...S.card,marginBottom:6,padding:'10px 14px',
display:'flex',alignItems:'center',gap:10}}>
<span style={{fontSize:22,flexShrink:0}}>📁</span>
<span style={{fontSize:22,flexShrink:0}}>{folderIcon(folder)}</span>
{/* Info klickbar zum Navigieren */}
<div style={{flex:1,minWidth:0,cursor:'pointer'}} onClick={()=>enterFolder(folder,!!folder.owner)}>
<div style={{color:'#fff',fontFamily:'monospace',fontSize:13,fontWeight:700}}>{folder.name}</div>