DevTools: Datei laden Button, Zeilennummern in Diff+Textarea, eigene Dateigröße in Geschwindigkeit
This commit is contained in:
@@ -1001,14 +1001,25 @@ function TextDiff({ mobile }) {
|
||||
<div style={{display:'flex', alignItems:'center', gap:8, marginBottom:6}}>
|
||||
<span style={{color:'rgba(255,255,255,0.55)', fontFamily:'monospace', fontSize:10, flex:1}}>{label}</span>
|
||||
<label style={{...S.btn('#4ecdc4',false), fontSize:10, padding:'3px 10px', cursor:'pointer'}}>
|
||||
📂 .txt laden
|
||||
📂 Datei laden
|
||||
<input type="file" accept=".txt,.md,.log,.csv,.json,.xml,.yaml,.yml,.js,.ts,.jsx,.tsx,.py,.php,.sh,.env"
|
||||
style={{display:'none'}} onChange={e=>loadFile(e,setter)}/>
|
||||
</label>
|
||||
</div>
|
||||
<textarea style={ta} value={val} placeholder="Text hier einfügen…"
|
||||
{/* Textarea mit Zeilennummern */}
|
||||
<div style={{display:'flex', borderRadius:6, overflow:'hidden', border:'1px solid rgba(255,255,255,0.1)', background:'rgba(255,255,255,0.04)'}}>
|
||||
<div style={{
|
||||
padding:'7px 6px', minWidth:36, textAlign:'right', userSelect:'none',
|
||||
fontFamily:"'Courier New',monospace", fontSize:12, lineHeight:'1.6',
|
||||
color:'rgba(255,255,255,0.25)', background:'rgba(0,0,0,0.2)',
|
||||
borderRight:'1px solid rgba(255,255,255,0.07)', whiteSpace:'pre'}}>
|
||||
{(val||' ').split('\n').map((_,i)=>i+1).join('\n')}
|
||||
</div>
|
||||
<textarea style={{...ta, border:'none', borderRadius:0, background:'transparent', flex:1, resize:'vertical'}}
|
||||
value={val} placeholder="Text hier einfügen…"
|
||||
onChange={e=>{ setter(e.target.value); setDiff(null); }}/>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -1036,21 +1047,35 @@ function TextDiff({ mobile }) {
|
||||
overflow:'auto', maxHeight:480, background:'rgba(0,0,0,0.2)'}}>
|
||||
<table style={{width:'100%', borderCollapse:'collapse', fontFamily:"'Courier New',monospace", fontSize:12}}>
|
||||
<tbody>
|
||||
{diff.map((d, i) => (
|
||||
{(()=>{
|
||||
let lnA=0, lnB=0;
|
||||
return diff.map((d,i)=>{
|
||||
if (d.type==='del') lnA++;
|
||||
else if (d.type==='add') lnB++;
|
||||
else { lnA++; lnB++; }
|
||||
const ln = d.type==='add' ? lnB : lnA;
|
||||
return (
|
||||
<tr key={i} style={{
|
||||
background: d.type==='add' ? 'rgba(78,205,196,0.1)' : d.type==='del' ? 'rgba(255,107,157,0.1)' : 'transparent',
|
||||
borderBottom: '1px solid rgba(255,255,255,0.03)'}}>
|
||||
<td style={{width:24, textAlign:'center', padding:'2px 6px', userSelect:'none',
|
||||
color: d.type==='add'?'#4ecdc4': d.type==='del'?'#ff6b9d':'rgba(255,255,255,0.2)',
|
||||
fontWeight:700, fontSize:14, borderRight:'1px solid rgba(255,255,255,0.05)'}}>
|
||||
{d.type==='add'?'+': d.type==='del'?'−':''}
|
||||
background: d.type==='add'?'rgba(78,205,196,0.1)':d.type==='del'?'rgba(255,107,157,0.1)':'transparent',
|
||||
borderBottom:'1px solid rgba(255,255,255,0.03)'}}>
|
||||
<td style={{width:36,textAlign:'right',padding:'2px 8px',userSelect:'none',
|
||||
color:'rgba(255,255,255,0.2)',fontFamily:"'Courier New',monospace",fontSize:11,
|
||||
borderRight:'1px solid rgba(255,255,255,0.05)'}}>
|
||||
{ln}
|
||||
</td>
|
||||
<td style={{padding:'3px 10px', whiteSpace:'pre-wrap', wordBreak:'break-all',
|
||||
color: d.type==='add'?'#a8f0eb': d.type==='del'?'#ffb3cc':'rgba(255,255,255,0.65)'}}>
|
||||
{d.text || ' '}
|
||||
<td style={{width:24,textAlign:'center',padding:'2px 6px',userSelect:'none',
|
||||
color:d.type==='add'?'#4ecdc4':d.type==='del'?'#ff6b9d':'rgba(255,255,255,0.2)',
|
||||
fontWeight:700,fontSize:14,borderRight:'1px solid rgba(255,255,255,0.05)'}}>
|
||||
{d.type==='add'?'+':d.type==='del'?'−':''}
|
||||
</td>
|
||||
<td style={{padding:'3px 10px',whiteSpace:'pre-wrap',wordBreak:'break-all',
|
||||
color:d.type==='add'?'#a8f0eb':d.type==='del'?'#ffb3cc':'rgba(255,255,255,0.65)'}}>
|
||||
{d.text||' '}
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
);
|
||||
});
|
||||
})()}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@@ -1073,6 +1098,8 @@ function NetzwerkRechner({ mobile }) {
|
||||
// ── Geschwindigkeit ──
|
||||
const [speedVal, setSpeedVal] = useState('');
|
||||
const [speedUnit, setSpeedUnit] = useState('mbps');
|
||||
const [customSize, setCustomSize] = useState('');
|
||||
const [customSizeUnit, setCustomSizeUnit] = useState('mb');
|
||||
|
||||
const SPEED_UNITS = [
|
||||
{ id:'bps', label:'bit/s', toBps: 1 },
|
||||
@@ -1239,6 +1266,22 @@ function NetzwerkRechner({ mobile }) {
|
||||
{[['700 MB CD',700e6],['4,7 GB DVD',4.7e9],['25 GB Blu-ray',25e9],['50 GB Spiel',50e9],['100 GB',100e9]].map(([lbl,b])=>(
|
||||
<NRow key={lbl} label={lbl} value={dlTime(speedBps,b)} muted/>
|
||||
))}
|
||||
<div style={{borderTop:'1px solid rgba(255,255,255,0.07)',marginTop:8,paddingTop:8}}>
|
||||
<div style={{display:'flex',gap:8,alignItems:'center',flexWrap:'wrap',marginBottom:6}}>
|
||||
<span style={{color:'rgba(255,255,255,0.5)',fontFamily:'monospace',fontSize:11,minWidth:80}}>Eigene Größe</span>
|
||||
<input style={{...inp,width:90,flex:'none'}} type="number" min="0" placeholder="z.B. 8"
|
||||
value={customSize} onChange={e=>setCustomSize(e.target.value)}/>
|
||||
<select style={{...inp,width:70,flex:'none',cursor:'pointer'}} value={customSizeUnit} onChange={e=>setCustomSizeUnit(e.target.value)}>
|
||||
<option value="kb">kB</option>
|
||||
<option value="mb">MB</option>
|
||||
<option value="gb">GB</option>
|
||||
<option value="tb">TB</option>
|
||||
</select>
|
||||
{!!customSize && <span style={{color:'#4ecdc4',fontFamily:"'Courier New',monospace",fontSize:13,fontWeight:700}}>
|
||||
{dlTime(speedBps, parseFloat(customSize) * ({kb:1e3,mb:1e6,gb:1e9,tb:1e12}[customSizeUnit]||1e6))}
|
||||
</span>}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{marginTop:10,padding:'8px 12px',borderRadius:7,
|
||||
background:'rgba(255,255,255,0.02)',border:'1px solid rgba(255,255,255,0.06)'}}>
|
||||
|
||||
Reference in New Issue
Block a user