Let go of old message bodies and of exported files
Every message opened kept its full copy for as long as the tab was open. The store now holds bodies for the 40 messages most recently wanted; older ones go back to the list properties and are fetched in full again if opened. The open conversation is never released. Contact, settings and calendar exports go through downloadFile, which releases the object URL once the download has started; three of them never released it.
This commit is contained in:
@@ -15,6 +15,7 @@ import { useSettings } from "@/store/settings";
|
||||
import { ContactEditor } from "./ContactEditor";
|
||||
import { avatarColor } from "@/lib/address";
|
||||
import { plural, t as translate } from "@/lib/i18n";
|
||||
import { downloadFile } from "@/lib/download";
|
||||
|
||||
export function ContactsView({ id }: { id?: string }) {
|
||||
const [, navigate] = useLocation();
|
||||
@@ -149,10 +150,7 @@ export function ContactsView({ id }: { id?: string }) {
|
||||
toast.error(translate("There is nothing in it to export"));
|
||||
return;
|
||||
}
|
||||
const a = document.createElement("a");
|
||||
a.href = URL.createObjectURL(new Blob([cards.map(toVCard).join("")], { type: "text/vcard" }));
|
||||
a.download = "contacts.vcf";
|
||||
a.click();
|
||||
downloadFile(cards.map(toVCard).join(""), "text/vcard", "contacts.vcf");
|
||||
};
|
||||
|
||||
const importFile = async (f: File, intoBookId?: string) => {
|
||||
@@ -359,7 +357,7 @@ function ContactDetail({ card: c, onBack, onEdit, narrow, onEmail }: { card: Con
|
||||
{narrow && <button className="icon-btn" onClick={onBack} aria-label={translate("Back")}><ArrowLeft size={20} /></button>}
|
||||
<span className="spacer" />
|
||||
<button className="btn btn-sm" onClick={onEdit}><Pencil size={14} /> {translate("Edit")}</button>
|
||||
<button className="btn btn-sm" onClick={() => { const a = document.createElement("a"); a.href = URL.createObjectURL(new Blob([toVCard(c)], { type: "text/vcard" })); a.download = `${name.replace(/[^\w.-]+/g, "_")}.vcf`; a.click(); }}><Download size={14} /> {translate("vCard")}</button>
|
||||
<button className="btn btn-sm" onClick={() => downloadFile(toVCard(c), "text/vcard", `${name.replace(/[^\w.-]+/g, "_")}.vcf`)}><Download size={14} /> {translate("vCard")}</button>
|
||||
<button className="btn btn-sm btn-ghost" style={{ color: "var(--danger)" }} onClick={async () => { if (await confirmDialog({ title: translate("Delete {name}?", { name }), confirmLabel: translate("Delete"), danger: true })) { try { const { destroyed, refused } = await contacts.destroyCards([c.id]); if (!destroyed) { toast.error(refused ? setErrorMessage(refused) : translate("It was not deleted")); return; } toast.success(translate("Contact deleted")); navigate("/contacts"); } catch (err) { toast.error((err as Error).message); } } }}><Trash2 size={14} /></button>
|
||||
</div>
|
||||
<div className="contact-hero">
|
||||
|
||||
Reference in New Issue
Block a user