):(
[Link]((file) => {
const modifiable = canModify(file);
const ownerLabel = user && [Link] &&
[Link] === [Link] ? "Me" : ([Link] ||
"Unknown");
const lastModified = [Link] ||
[Link] || null;
return (
<div key={[Link]} className={detailsRow
rows ${listVisible ? "" : "collapsed"}}
tabIndex={0}
onClick={() => openFileModal(file)}>
<p title={[Link]}>
<span className="material-symbols-
outlined">description</span>
{[Link]}
</p>
<p title={[Link]}>{ownerLabel}</
p>
<p title={String(lastModified)}
>{formatLastModifiedWithTime12h(lastModified)}</
p>
<p title={String([Link])}
>{formatSize([Link])}</p>
<p
className="fileType">{getExtension(file)}</p>
<p className="actionsCell">
{/* remove preview button — click row
opens modal with preview + actions */}
<button
className="iconBtn"
onClick={(e) => { [Link]();
setActiveFile(file); }}
title="Open"
title="Open"
aria-label={Open ${[Link]}}
>
<span className="material-symbols-
outlined">open_in_new</span>
</button>
<button
className="iconBtn"
onClick={(e) => { [Link]();
setRenameOpen(true); setRenameValue([Link]);
setActiveFile(file); }}
disabled={!modifiable || savingId ===
[Link]}
title={!modifiable ? "You can only
rename your own files" : "Rename"}
>
<span className="material-symbols-
outlined">edit</span>
</button>
<button
className="iconBtn danger"
onClick={(e) => { [Link]();
setConfirmDeleteOpen(true); setActiveFile(file); }}
disabled={!modifiable || savingId ===
[Link]}
title={!modifiable ? "You can only delete
your own files" : "Delete"}
>
<span className="material-symbols-
outlined">delete</span>
</button>
</p>
</div>
);
})
)}
</div>
</div>
{/* FILE MODAL (preview + actions) */}
{activeFile && (
<div className="modalOverlay" role="dialog"
aria-modal="true" onClick={() => setActiveFile(null)}>
<div className="fileModal" onClick={(e) =>
[Link]()}>
<div className="fileModalHeader">
<div style={{ fontWeight: 700 }}
>{[Link]}</div>
<div style={{ display: "flex", gap: 8 }}>
<button className="iconBtn" onClick={()
=> { setRenameOpen(true);
setRenameValue([Link]); }}>
<span className="material-symbols-
outlined">edit</span>
</button>
<button className="iconBtn danger"
onClick={() => setConfirmDeleteOpen(true)}>
<span className="material-symbols-
outlined">delete</span>
</button>
<button className="iconBtn" onClick={()
=> setActiveFile(null)} aria-label="Close">
<span className="material-symbols-
outlined">close</span>
</button>
</div>
</div>
<div className="fileModalBody">
{/* preview */}
{[Link] ? (
(() => {
const t = previewType(activeFile);
if (t === "image") {
return <img
src={[Link]} alt={[Link]}
style={{ maxWidth: "100%", maxHeight: "60vh",
objectFit: "contain" }} />;
}
}
if (t === "pdf") {
return <iframe title="pdf-preview"
src={[Link]} style={{ width: "100%",
height: "64vh", border: 0 }} />;
}
if (t === "video") {
return <video controls style={{
maxWidth: "100%", maxHeight: "64vh" }}
src={[Link]} />;
}
if (t === "audio") {
return <audio controls
src={[Link]} style={{ width: "100%" }}
/>;
}
// fallback: show download link
return (
<div>
<p>No inline preview available for this
file type.</p>
<a href={[Link]}
target="_blank" rel="noopener noreferrer">Open in
new tab</a>
</div>
);
})()
):(
<div>
<p>No preview available (missing
downloadURL).</p>
</div>
)}
</div>
<div className="fileModalFooter">
<div style={{ fontSize: 13, color: "#666" }}>
Owner: {[Link] ||
"Unknown"} • Size: {formatSize([Link])}
</div>
<div style={{ display: "flex", gap: 8 }}>
<a className="actionBtn"
<a className="actionBtn"
href={[Link] || "#"} target="_blank"
rel="noopener noreferrer">Download</a>
<button className="actionBtn" onClick={()
=> {
[Link]?.writeText([Link]
|| ""); alert("Download link copied."); }}>
Copy link
</button>
</div>
</div>
</div>
</div>
)}
{/* RENAME MODAL */}
{renameOpen && activeFile && (
<div className="modalOverlay" role="dialog"
aria-modal="true" onClick={() =>
setRenameOpen(false)}>
<div className="confirmModal" onClick={(e)
=> [Link]()}>
<div style={{ fontWeight: 700, marginBottom:
8 }}>Rename file</div>
<input value={renameValue} onChange={(e)
=> setRenameValue([Link])} style={{ width:
"100%", padding: 8, marginBottom: 12, borderRadius:
6, border: "1px solid #ddd" }} />
<div style={{ display: "flex", gap: 8,
justifyContent: "flex-end" }}>
<button className="smallBtn" onClick={()
=> setRenameOpen(false)}>Cancel</button>
<button className="smallBtn"
onClick={handleRenameConfirm}>Save</button>
</div>
</div>
</div>
)}
{/* DELETE CONFIRMATION */}
{confirmDeleteOpen && activeFile && (
{confirmDeleteOpen && activeFile && (
<div className="modalOverlay" role="dialog"
aria-modal="true" onClick={() =>
setConfirmDeleteOpen(false)}>
<div className="confirmModal" onClick={(e)
=> [Link]()}>
<div style={{ fontWeight: 700, marginBottom:
8 }}>Delete "{[Link]}"?</div>
<div style={{ marginBottom: 12, color: "#666"
}}>This will permanently delete the file. This action
cannot be undone.</div>
<div style={{ display: "flex", gap: 8,
justifyContent: "flex-end" }}>
<button className="smallBtn" onClick={()
=> setConfirmDeleteOpen(false)}>Cancel</button>
<button className="smallBtn danger"
onClick={handleDeleteConfirm}>Delete</button>
</div>
</div>
</div>
)}
</div>
);
}
export default Data; the sign in or sign out not
working properly when sign ini out the files apper
there
Got it — you’re saying that when you sign out, the files still appear on screen
(they don’t disappear or reload properly).
That’s a common issue with Firebase listeners and React state management. Let’s
break it down and fix it cleanly.
Why It Happens
In your code:
js Copy code
js Copy code
useEffect(() => {
startRealtimeListener();
return () => {
if ([Link]) {
try {
[Link]();
} catch (e) {}
[Link] = null;
}
};
}, [user]);
This effect starts the Firestore listener when user changes.
When you sign in, user is set → listener starts.
When you sign out, user becomes null — but you never clear the files
state.
So the UI still shows the old files that were in memory.
The Fix
You should clear the file list and stop the Firestore listener when the user signs
out.
Just modify your second useEffect like this:
js Copy code
useEffect(() => {
if (user) {
// Start listening to files when user is signed in
startRealtimeListener();
} else {
// Stop listening and clear files on sign out
if ([Link]) {
try {
[Link]();
} catch (e) {}
} (e) {}
[Link] = null;
}
setFiles([]); // clear UI
}
// Cleanup on unmount
return () => {
if ([Link]) {
try {
[Link]();
} catch (e) {}
[Link] = null;
}
};
}, [user]);
Why This Works
• When you sign in, it starts the Firestore onSnapshot listener.
• When you sign out, it:
1. Cancels the listener (so no more real-time updates).
2. Clears the files state immediately.
• The UI re-renders and correctly shows no files.
Bonus (Optional Improvement)
If you want, you can also display a message like:
js Copy code
{!user ? (
<p>Please sign in to view your files.</p>
) : [Link] === 0 ? (
<p>No files found.</p>
) : (
// render files
)}
That makes it clearer what’s happening for users.
Would you like me to show you exactly where in your current code to paste this
fixed useEffect (line by line)?
create a ready to copy paste code
Perfect — here’s your fixed and ready-to-paste code snippet.
Just replace your existing second useEffect (the one that depends on [user] )
in [Link] with this one
Fixed useEffect for real-time listener cleanup
js Copy code
// Replace your existing "useEffect(..., [user])" block with this
useEffect(() => {
if (user) {
// User signed in — start the Firestore listener
startRealtimeListener();
} else {
// User signed out — stop listener and clear data
if ([Link]) {
try {
[Link]();
} catch (e) {
[Link]("Error unsubscribing listener:", e);
}
[Link] = null;
}
// Clear the file list so files disappear immediately
setFiles([]);
}
// Cleanup on unmount (safety)
return () => {
if ([Link]) {
try {
[Link]();
} catch (e) {
[Link]("Cleanup unsubscribe failed:", e);
}
[Link] = null;
}
};
}, [user]);
What It Does
When you sign in, it starts the real-time Firestore listener.
When you sign out, it:
• Stops the Firestore listener.
• Clears the file list immediately from your UI.
When the component unmounts, it safely cleans up listeners.
After pasting this, just save your file and restart your dev server — now when you
sign out, all files will properly disappear right away.
no rewrte whole code
Got it — here’s your full, ready-to-copy version of src/components/[Link]
with the sign-in / sign-out bug fixed (files now disappear properly on sign-out).
Everything else is left intact — only the useEffect and cleanup logic were
improved for correctness and stability.
Full Fixed Code: src/components/[Link]
js Copy code
// src/components/[Link]
import React, { useEffect, useState, useRef } from "react";
import "./css/[Link]";
import { db, auth, storage } from "./firebase";
import {
collection,
doc,
updateDoc,
deleteDoc,
onSnapshot,
serverTimestamp,
query,
orderBy,
} from "firebase/firestore";
import { ref as storageRef, deleteObject } from "firebase/storage";
import {
GoogleAuthProvider,
signInWithPopup,
signOut,
onAuthStateChanged,
setPersistence,
browserLocalPersistence,
} from "firebase/auth";
function Data() {
const [gridVisible, setGridVisible] = useState(true);
const [listVisible, setListVisible] = useState(true);
const [files, setFiles] = useState([]);
const [loading, setLoading] = useState(true);
const [savingId, setSavingId] = useState(null);
const [user, setUser] = useState(null);
const unsubscribeRef = useRef(null);
const [activeFile, setActiveFile] = useState(null);
const [confirmDeleteOpen, setConfirmDeleteOpen] = useState(false);
const [renameOpen, setRenameOpen] = useState(false);
const [renameValue, setRenameValue] = useState("");
function getFilesCollectionRef() {
return collection(db, "files");
}
function mapDocToFile(docSnap) {
const data = [Link]() || {};
return {
id: [Link],
name: [Link] || [Link] || [Link] || "Untitled",
ownerId: [Link] || [Link] || null,
ownerName: [Link] || [Link] || [Link] || "Unknown"
lastModifiedRaw:
[Link] || [Link] || [Link] || null,
uploadedAtRaw: [Link] || null,
size: [Link] || [Link] || [Link] || "—",
storagePath: [Link] || [Link] || null,
mimeType: [Link] || [Link] || [Link] || "",
downloadURL: [Link] || null,
};
}
function formatLastModifiedWithTime12h(raw) {
if (!raw) return "Unknown";
let dateObj;
try {
if (raw && typeof [Link] === "function") dateObj = [Link]();
else if (typeof raw === "number") dateObj = new Date(raw);
else dateObj = new Date(raw);
if (isNaN([Link]())) return String(raw);
} catch (e) {
return String(raw);
}
options = {