613 lines
29 KiB
JavaScript
613 lines
29 KiB
JavaScript
import server from "/@server/server.js"
|
||
import calendarUtil from "../calendarUtil.js"
|
||
import "./EventForm.js"
|
||
import "../../components/BottomSheet.js"
|
||
import "../../components/BackButton.js"
|
||
import "../../components/Avatar.js"
|
||
|
||
css(`
|
||
eventdetails- {
|
||
display: flex;
|
||
flex-direction: column;
|
||
height: 100%;
|
||
scrollbar-width: none;
|
||
-ms-overflow-style: none;
|
||
}
|
||
eventdetails- ::-webkit-scrollbar { display: none; width: 0; height: 0; }
|
||
eventdetails- ::-webkit-scrollbar-thumb { background: transparent; }
|
||
eventdetails- ::-webkit-scrollbar-track { background: transparent; }
|
||
#eventdetails-toast-wrap {
|
||
transition: max-height 0.25s ease, opacity 0.22s ease, padding-top 0.25s ease;
|
||
}
|
||
`)
|
||
|
||
class EventDetails extends Shadow {
|
||
attachmentsOpen = false;
|
||
selectedCalendars = [];
|
||
_pendingCalendars = null;
|
||
_prevCalendars = null;
|
||
|
||
constructor(calendars, event = null, onEventEdited = null, onEventDeleted = null) {
|
||
super()
|
||
this.calendars = calendars;
|
||
this.event = event;
|
||
this.onEventEdited = onEventEdited;
|
||
this.onEventDeleted = onEventDeleted;
|
||
this.selectedCalendars = calendars.filter(c => event?.calendars?.includes(c.id));
|
||
}
|
||
|
||
render() {
|
||
this.editSheet = BottomSheet(100) // separate sheet for the edit form, layered above this one
|
||
|
||
const isOwner = this.event?.creator_id === global.profile?.id;
|
||
|
||
VStack(() => {
|
||
this.renderHeader(isOwner)
|
||
|
||
// ── Error toast ───────────────────────────────────────
|
||
VStack(() => {
|
||
p("")
|
||
.attr({ id: "eventdetails-toast" })
|
||
.margin(0)
|
||
.padding("0.55em 1.1em")
|
||
.background("var(--quillred)")
|
||
.color("white")
|
||
.fontSize(0.85, em)
|
||
.fontWeight("500")
|
||
.fontFamily("Arial")
|
||
.borderRadius("0.5em")
|
||
.boxShadow("0 2px 10px rgba(0,0,0,0.15)")
|
||
.whiteSpace("nowrap")
|
||
})
|
||
.attr({ id: "eventdetails-toast-wrap" })
|
||
.alignItems("center")
|
||
.overflow("hidden")
|
||
.maxHeight(0)
|
||
.opacity(0)
|
||
.flexShrink(0)
|
||
|
||
// ── Scrollable body ───────────────────────────────────
|
||
VStack(() => {
|
||
if (!this.event) return
|
||
|
||
// VStack(() => {}).height(0.85, em).flexShrink(0)
|
||
|
||
// ── Calendar / Location / Notes card ──────────────
|
||
VStack(() => {
|
||
|
||
// Calendar row — tappable to expand
|
||
HStack(() => {
|
||
p("Calendar")
|
||
.margin(0).fontSize(0.92, em).color("var(--headertext)").flexShrink(0)
|
||
|
||
HStack(() => {
|
||
this.selectedCalendars.forEach(cal => {
|
||
HStack(() => {
|
||
p("").width(0.6, em).height(0.6, em)
|
||
.background(cal.color)
|
||
.borderRadius(50, pct)
|
||
.flexShrink(0)
|
||
p(cal.name)
|
||
.margin(0)
|
||
.fontSize(0.82, em)
|
||
.fontWeight("600")
|
||
.color("var(--text)")
|
||
.whiteSpace("nowrap")
|
||
})
|
||
.gap(0.3, em)
|
||
.alignItems("center")
|
||
})
|
||
})
|
||
.attr({ id: "calendar-display" })
|
||
.flex(1)
|
||
.justifyContent("flex-end")
|
||
.flexWrap("wrap")
|
||
.gap(0.5, em)
|
||
|
||
let chevron = p("›")
|
||
chevron
|
||
.attr({ id: "cal-chevron" })
|
||
.margin(0).opacity(0.3).fontSize(1.1, em).flexShrink(0)
|
||
.transition("transform 0.25s ease")
|
||
.state(chevron.parentElement, "open", function (value) {
|
||
if(value === "true") {
|
||
this.style.transform = "rotate(90deg)"
|
||
} else {
|
||
console.log("no trans")
|
||
this.style.transform = ""
|
||
}
|
||
})
|
||
})
|
||
.attr({id: "calendar-row"})
|
||
.paddingHorizontal(1, em).paddingVertical(0.78, em)
|
||
.alignItems("center").gap(0.5, em)
|
||
.borderBottom("1px solid var(--divider)").cursor("pointer")
|
||
.onTap(function () {
|
||
const isOpen = this.getAttribute("open") === "true"
|
||
if (isOpen) {
|
||
this.setAttribute("open", "false")
|
||
} else {
|
||
this.setAttribute("open", "true")
|
||
}
|
||
})
|
||
|
||
// Calendar Expandable List
|
||
VStack(() => {
|
||
this.calendars.forEach(cal => {
|
||
const isSelected = this.selectedCalendars.some(c => c.id === cal.id)
|
||
HStack(() => {
|
||
HStack(() => {
|
||
p("").width(0.65, em).height(0.65, em)
|
||
.background(cal.color).borderRadius(50, pct).flexShrink(0)
|
||
p(cal.name)
|
||
.margin(0).fontSize(0.9, em).color("var(--text)").fontFamily("Arial")
|
||
})
|
||
.gap(0.45, em).alignItems("center").flex(1)
|
||
|
||
p("✓")
|
||
.attr({ id: `cal-check-${cal.id}` })
|
||
.margin(0).fontSize(0.88, em)
|
||
.color("var(--quillred)").fontWeight("700")
|
||
.display(isSelected ? "" : "none")
|
||
})
|
||
.paddingHorizontal(1.25, em).paddingVertical(0.72, em)
|
||
.alignItems("center")
|
||
.borderBottom("1px solid var(--divider)")
|
||
.cursor("pointer")
|
||
.onTap(() => {
|
||
const prevCalendars = [...this.selectedCalendars]
|
||
const i = this.selectedCalendars.findIndex(c => c.id === cal.id)
|
||
if (i >= 0) {
|
||
if (this.selectedCalendars.length > 1) {
|
||
this.selectedCalendars.splice(i, 1)
|
||
const check = this.$(`#cal-check-${cal.id}`)
|
||
if (check) check.style.display = "none"
|
||
}
|
||
} else {
|
||
this.selectedCalendars.push(cal)
|
||
const check = this.$(`#cal-check-${cal.id}`)
|
||
if (check) check.style.display = ""
|
||
}
|
||
this.updateCalendarDisplay()
|
||
this.saveCalendars(prevCalendars)
|
||
})
|
||
})
|
||
})
|
||
.state(this.$("#calendar-row"), "open", function (value) {
|
||
if(value === "false") {
|
||
this.style.maxHeight = "0"
|
||
} else {
|
||
this.style.maxHeight = this.scrollHeight + "px"
|
||
}
|
||
})
|
||
.attr({ id: "cal-picker"})
|
||
.overflow("hidden").maxHeight(0)
|
||
.transition("max-height 0.3s ease")
|
||
|
||
// Location row
|
||
if (this.event.location) {
|
||
HStack(() => {
|
||
p("📍").margin(0).fontSize(0.85, em).flexShrink(0)
|
||
p(this.event.location)
|
||
.margin(0).fontSize(0.9, em).color("var(--text)").fontFamily("Arial")
|
||
})
|
||
.paddingHorizontal(1, em).paddingVertical(0.78, em)
|
||
.alignItems("center").gap(0.65, em)
|
||
.borderBottom("1px solid var(--divider)")
|
||
}
|
||
|
||
// Notes row
|
||
if (this.event.description) {
|
||
HStack(() => {
|
||
p("📝").margin(0).fontSize(0.85, em).flexShrink(0).alignSelf("flex-start").paddingTop(0.1, em)
|
||
p(this.event.description)
|
||
.margin(0).fontSize(0.9, em).color("var(--text)").fontFamily("Arial")
|
||
.whiteSpace("pre-wrap").lineHeight("1.45")
|
||
})
|
||
.paddingHorizontal(1, em).paddingVertical(0.78, em)
|
||
.alignItems("flex-start").gap(0.65, em)
|
||
}
|
||
})
|
||
.background("var(--darkaccent)").border("1px solid var(--divider)")
|
||
.borderRadius(12, px).marginHorizontal(1, em).overflow("hidden").flexShrink(0)
|
||
|
||
// ── Attachments card ──────────────────────────────
|
||
if (this.event.attachments?.length > 0) {
|
||
// VStack(() => {}).height(0.85, em).flexShrink(0)
|
||
VStack(() => {
|
||
HStack(() => {
|
||
p("📎").margin(0).fontSize(0.85, em).flexShrink(0)
|
||
p("Attachments")
|
||
.margin(0).fontSize(0.92, em).color("var(--headertext)").flex(1)
|
||
p("▼")
|
||
.attr({ id: "attachments-chevron" })
|
||
.margin(0).fontSize(0.7, em).color("var(--text)").opacity(0.5)
|
||
.display("inline-block")
|
||
.transition("transform 0.3s ease")
|
||
.transform(this.attachmentsOpen ? "rotate(180deg)" : "rotate(0deg)")
|
||
})
|
||
.paddingHorizontal(1, em).paddingVertical(0.78, em)
|
||
.alignItems("center").gap(0.65, em).cursor("pointer")
|
||
.onTap(() => this.toggleAttachments())
|
||
|
||
VStack(() => {
|
||
VStack(() => {
|
||
this.event.attachments.forEach(file => this.renderFile(file))
|
||
})
|
||
.gap(0.75, em).width(100, pct)
|
||
.padding("0 1em 0.75em").boxSizing("border-box")
|
||
})
|
||
.attr({ id: "attachments-content" })
|
||
.overflow("hidden").maxHeight("0")
|
||
.transition("max-height 0.5s ease")
|
||
})
|
||
.background("var(--darkaccent)").border("1px solid var(--divider)")
|
||
.borderRadius(12, px).marginHorizontal(1, em).overflow("hidden").flexShrink(0)
|
||
}
|
||
})
|
||
.overflowY("scroll").flex(1).minHeight(0).paddingTop(0.85, em).paddingBottom(1.5, em).gap(0.85, em)
|
||
|
||
// ── Footer: creator avatar + timestamps ───────────────
|
||
if (this.event) {
|
||
const members = global.currentNetwork.data?.members || []
|
||
const creator = members.find(m => m.id === this.event.creator_id)
|
||
if (creator) {
|
||
HStack(() => {
|
||
Avatar(creator, 2)
|
||
VStack(() => {
|
||
p(`Created ${calendarUtil.timeAgo(this.event.created)} by ${creator.first_name}`)
|
||
.margin(0).fontSize(0.9, em).color("var(--headertext)").opacity(0.5)
|
||
if (this.event.updated_at && this.event.updated_at !== this.event.created) {
|
||
p(`Last updated ${calendarUtil.timeAgo(this.event.updated_at)}`)
|
||
.margin(0).fontSize(0.9, em).color("var(--headertext)").opacity(0.4)
|
||
}
|
||
})
|
||
.gap(0.15, em)
|
||
})
|
||
.paddingHorizontal(1, em)
|
||
.paddingVertical(0.65, em)
|
||
.alignItems("center")
|
||
.gap(0.5, em)
|
||
.flexShrink(0)
|
||
}
|
||
}
|
||
|
||
})
|
||
.height(100, pct)
|
||
}
|
||
|
||
renderHeader(isOwner) {
|
||
VStack(() => {
|
||
HStack(() => {
|
||
BackButton(false, true, () => $("bottomsheet-").toggle())
|
||
if (isOwner) {
|
||
HStack(() => {
|
||
// ── Delete button ─────────────────────────────────
|
||
button("Delete")
|
||
.attr({ type: "button" })
|
||
.padding(0.4, rem)
|
||
.fontSize(1.25, em)
|
||
.boxSizing("border-box")
|
||
.outline("none")
|
||
.border("none")
|
||
.background("transparent")
|
||
.color("var(--quillred)")
|
||
.onTap(() => this.handleDelete())
|
||
|
||
button("Edit")
|
||
.padding(0.4, rem)
|
||
.fontSize(1.25, em)
|
||
.color("var(--darkaccent)")
|
||
.boxSizing("border-box")
|
||
.outline("none")
|
||
.border("none")
|
||
.zIndex(3)
|
||
.onTap((e) => {
|
||
e.preventDefault()
|
||
let formEl
|
||
const closeForm = () => {
|
||
this.editSheet._closeOverride = null
|
||
this.editSheet.setSheet(false)
|
||
}
|
||
const onSaveError = () => {
|
||
this.editSheet._closeOverride = () => this.editSheet.forceClose()
|
||
}
|
||
this.editSheet.show(() => {
|
||
// For override rows, attach template dates so scope='all' anchors correctly
|
||
let eventForForm = this.event;
|
||
if (this.event.recurrence_parent_id && !this.event._templateStart) {
|
||
const template = global.currentNetwork.data.events.find(e => e.id === this.event.recurrence_parent_id);
|
||
if (template) {
|
||
eventForForm = {
|
||
...this.event,
|
||
_templateStart: new Date(template.time_start),
|
||
_templateEnd: new Date(template.time_end)
|
||
};
|
||
}
|
||
}
|
||
formEl = EventForm(
|
||
this.calendars,
|
||
(updateResult) => {
|
||
closeForm()
|
||
const updatedEvent = updateResult?.scope ? updateResult.event : updateResult;
|
||
this.event = { ...updatedEvent, time_start: new Date(updatedEvent.time_start), time_end: new Date(updatedEvent.time_end) }
|
||
this.selectedCalendars = this.calendars.filter(c => updatedEvent.calendars?.includes(c.id))
|
||
setTimeout(() => {
|
||
this.onEventEdited(updateResult)
|
||
this.rerender()
|
||
}, 300)
|
||
},
|
||
eventForForm,
|
||
closeForm,
|
||
(deleteResult) => {
|
||
closeForm()
|
||
$("bottomsheet-").toggle()
|
||
this.onEventDeleted(deleteResult)
|
||
},
|
||
null,
|
||
onSaveError
|
||
)
|
||
})
|
||
this.editSheet._closeOverride = () => {
|
||
this.editSheet.setSheet(true)
|
||
formEl?.handleBack()
|
||
}
|
||
})
|
||
})
|
||
.fontFamily("Arial")
|
||
.cursor("pointer")
|
||
.paddingHorizontal(0.8, rem)
|
||
.gap(0.4, rem)
|
||
}
|
||
})
|
||
.width(100, pct)
|
||
.justifyContent("space-between")
|
||
.alignItems("center")
|
||
|
||
VStack(() => {
|
||
h2(this.event?.title ?? "")
|
||
.color("var(--headertext)")
|
||
.fontFamily("Arial")
|
||
.margin(0)
|
||
.fontSize(1.4, em)
|
||
p(this.event ? calendarUtil.formatEventTime(this.event) : "")
|
||
.margin(0)
|
||
.color("var(--headertext)")
|
||
.opacity(0.7)
|
||
.fontSize(0.85, em)
|
||
})
|
||
.paddingHorizontal(1, em)
|
||
.paddingBottom(1, em)
|
||
.gap(0.3, em)
|
||
.alignItems("flex-start")
|
||
})
|
||
.width(100, pct)
|
||
.background(util.darkMode() ? "var(--darkred)" : "var(--sidebottombars)")
|
||
.borderTopLeftRadius("10px").borderTopRightRadius("10px")
|
||
.border("1px solid var(--divider)")
|
||
.boxSizing("border-box").flexShrink(0)
|
||
.alignItems("flex-start")
|
||
}
|
||
|
||
updateCalendarDisplay() {
|
||
const el = this.$("#calendar-display")
|
||
if (!el) return
|
||
el.innerHTML = this.selectedCalendars.map(cal => `
|
||
<div style="display:flex;align-items:center;gap:0.3em;">
|
||
<div style="width:0.6em;height:0.6em;background:${cal.color};border-radius:50%;flex-shrink:0;"></div>
|
||
<p style="font-size:0.82em;font-weight:600;margin:0;color:var(--text);white-space:nowrap;">${cal.name}</p>
|
||
</div>
|
||
`).join('')
|
||
}
|
||
|
||
showError(msg) {
|
||
const wrap = this.$("#eventdetails-toast-wrap")
|
||
const toast = this.$("#eventdetails-toast")
|
||
if (!wrap || !toast) return
|
||
clearTimeout(this._errorTimer)
|
||
if (msg) {
|
||
toast.innerText = msg
|
||
wrap.style.maxHeight = "3em"
|
||
wrap.style.opacity = "1"
|
||
wrap.style.paddingTop = "0.85em"
|
||
this._errorTimer = setTimeout(() => this.hideError(), 3500)
|
||
} else {
|
||
this.hideError()
|
||
}
|
||
}
|
||
|
||
hideError() {
|
||
const wrap = this.$("#eventdetails-toast-wrap")
|
||
if (!wrap) return
|
||
clearTimeout(this._errorTimer)
|
||
wrap.style.maxHeight = "0"
|
||
wrap.style.opacity = "0"
|
||
wrap.style.paddingTop = "0"
|
||
}
|
||
|
||
saveCalendars(prevCalendars) {
|
||
const event = this.event;
|
||
const newCalendars = this.selectedCalendars.map(c => c.id);
|
||
const isRecurring = !!(event._isOccurrence || event.recurrence_parent_id || event.recurrence_id);
|
||
|
||
this._prevCalendars = prevCalendars;
|
||
this._pendingCalendars = newCalendars;
|
||
|
||
if (isRecurring) {
|
||
$('actionsheetpopup-').show(
|
||
"Edit Recurring Event",
|
||
[
|
||
{ label: "Edit just this event", onTap: () => this.performCalendarSave('single'), destructive: false },
|
||
{ label: "Edit this and future events", onTap: () => this.performCalendarSave('future'), destructive: false },
|
||
{ label: "Edit all events in series", onTap: () => this.performCalendarSave('all'), destructive: false },
|
||
],
|
||
() => {
|
||
this._pendingCalendars = null;
|
||
this._revertCalendars(prevCalendars);
|
||
}
|
||
);
|
||
return;
|
||
}
|
||
|
||
this.performCalendarSave(null);
|
||
}
|
||
|
||
_revertCalendars(prev) {
|
||
this.selectedCalendars = prev;
|
||
this.calendars.forEach(cal => {
|
||
const check = this.$(`#cal-check-${cal.id}`);
|
||
if (check) check.style.display = prev.some(c => c.id === cal.id) ? "" : "none";
|
||
});
|
||
this.updateCalendarDisplay();
|
||
}
|
||
|
||
async performCalendarSave(scope) {
|
||
const event = this.event;
|
||
const newCalendars = this._pendingCalendars ?? this.selectedCalendars.map(c => c.id);
|
||
this._pendingCalendars = null;
|
||
const prevCalendars = this._prevCalendars;
|
||
|
||
try {
|
||
if (scope) {
|
||
const isOverride = !!event.recurrence_parent_id;
|
||
const templateId = isOverride ? event.recurrence_parent_id : event.id;
|
||
const occurrenceDate = isOverride
|
||
? (event.recurrence_exception_date instanceof Date
|
||
? event.recurrence_exception_date.toISOString()
|
||
: event.recurrence_exception_date) ?? null
|
||
: event._occurrenceDate?.toISOString() ?? null;
|
||
const serverEventId = (scope === 'single' && isOverride) ? event.id : templateId;
|
||
|
||
const result = await server.editEvent(serverEventId, {
|
||
title: event.title,
|
||
description: event.description ?? null,
|
||
location: event.location ?? null,
|
||
time_start: event.time_start instanceof Date ? event.time_start.toISOString() : event.time_start,
|
||
time_end: event.time_end instanceof Date ? event.time_end.toISOString() : event.time_end,
|
||
all_day: event.all_day,
|
||
calendars: newCalendars,
|
||
scope,
|
||
exception_date: occurrenceDate
|
||
}, global.currentNetwork.id);
|
||
|
||
if (result.status === 200) {
|
||
const editResult = {
|
||
scope,
|
||
event: { ...result.event, calendars: newCalendars, attachments: event.attachments ?? [] },
|
||
templateId,
|
||
occurrenceDate
|
||
};
|
||
this.event = { ...editResult.event, time_start: new Date(result.event.time_start), time_end: new Date(result.event.time_end) };
|
||
this.selectedCalendars = this.calendars.filter(c => newCalendars.includes(c.id));
|
||
this._prevCalendars = null;
|
||
$("bottomsheet-")._closeOverride = null;
|
||
this.onEventEdited(editResult);
|
||
} else {
|
||
this._revertCalendars(prevCalendars);
|
||
this.showError(result.error ?? "Failed to update calendars.");
|
||
$("bottomsheet-")._closeOverride = () => $("bottomsheet-").forceClose();
|
||
}
|
||
} else {
|
||
const result = await server.editEvent(event.id, { ...event, calendars: newCalendars }, global.currentNetwork.id);
|
||
if (result.status === 200) {
|
||
this.event = { ...event, calendars: newCalendars };
|
||
this._prevCalendars = null;
|
||
$("bottomsheet-")._closeOverride = null;
|
||
this.onEventEdited(this.event);
|
||
} else {
|
||
this._revertCalendars(prevCalendars);
|
||
this.showError(result.error ?? "Failed to update calendars.");
|
||
$("bottomsheet-")._closeOverride = () => $("bottomsheet-").forceClose();
|
||
}
|
||
}
|
||
} catch (err) {
|
||
console.error("Failed to update calendars:", err);
|
||
this._revertCalendars(prevCalendars);
|
||
this.showError("Failed to update calendars.");
|
||
$("bottomsheet-")._closeOverride = () => $("bottomsheet-").forceClose();
|
||
}
|
||
}
|
||
|
||
handleDelete() {
|
||
const event = this.event;
|
||
const isRecurring = !!(event?._isOccurrence || event?.recurrence_parent_id || event?.recurrence_id);
|
||
if (isRecurring) {
|
||
$('actionsheetpopup-').show(
|
||
"Delete Recurring Event",
|
||
[
|
||
{ label: "Delete just this event", onTap: () => this.performDelete('single') },
|
||
{ label: "Delete this and future events", onTap: () => this.performDelete('future') },
|
||
{ label: "Delete all events in series", onTap: () => this.performDelete('all') },
|
||
],
|
||
() => {}
|
||
)
|
||
return;
|
||
}
|
||
this.performDelete(null);
|
||
}
|
||
|
||
async performDelete(scope) {
|
||
const event = this.event;
|
||
const isOverride = !!event.recurrence_parent_id;
|
||
const templateId = isOverride ? event.recurrence_parent_id : event.id;
|
||
const occurrenceDate = isOverride
|
||
? (event.recurrence_exception_date instanceof Date
|
||
? event.recurrence_exception_date.toISOString()
|
||
: event.recurrence_exception_date) ?? null
|
||
: event._occurrenceDate?.toISOString() ?? null;
|
||
const serverEventId = (scope === 'single' && isOverride) ? event.id : templateId;
|
||
|
||
try {
|
||
const result = await server.deleteEvent(serverEventId, global.currentNetwork.id, scope, occurrenceDate)
|
||
if (result.status === 200) {
|
||
$("bottomsheet-").toggle()
|
||
const deleteResult = { scope: scope ?? 'all', templateId, occurrenceDate, overrideId: isOverride ? event.id : null };
|
||
setTimeout(() => this.onEventDeleted(deleteResult), 300)
|
||
} else {
|
||
this.showError(result.error ?? "Failed to delete event.")
|
||
$("bottomsheet-")._closeOverride = () => $("bottomsheet-").forceClose()
|
||
}
|
||
} catch (err) {
|
||
console.error("Failed to delete event:", err)
|
||
this.showError("Failed to delete event.")
|
||
$("bottomsheet-")._closeOverride = () => $("bottomsheet-").forceClose()
|
||
}
|
||
}
|
||
|
||
renderFile(file) {
|
||
const isImage = file.type?.startsWith("image/");
|
||
const url = `${config.SERVER}/db/images/events/${file.name}`;
|
||
|
||
if (isImage) {
|
||
img(url, "100%", "100%")
|
||
.borderRadius(8, px).display("block").boxSizing("border-box")
|
||
.cursor("pointer")
|
||
.onTap(() => $("filepreview-")?.open(file, url))
|
||
} else {
|
||
HStack(() => {
|
||
p("📎").margin(0).fontSize(1, em)
|
||
p(file.original_name ?? file.name)
|
||
.margin(0).color("var(--text)").fontSize(0.9, em)
|
||
.overflow("hidden").whiteSpace("nowrap").textOverflow("ellipsis")
|
||
})
|
||
.gap(0.5, em).alignItems("center")
|
||
.padding(0.5, em)
|
||
.background("var(--searchbackground)")
|
||
.borderRadius(8, px).boxSizing("border-box")
|
||
.cursor("pointer")
|
||
.onTap(() => $("filepreview-")?.open(file, url))
|
||
}
|
||
}
|
||
|
||
toggleAttachments() {
|
||
this.attachmentsOpen = !this.attachmentsOpen;
|
||
const content = this.$("#attachments-content");
|
||
const chevron = this.$("#attachments-chevron");
|
||
if (content) content.style.maxHeight = this.attachmentsOpen ? content.scrollHeight + "px" : "0";
|
||
if (chevron) chevron.style.transform = this.attachmentsOpen ? "rotate(180deg)" : "rotate(0deg)";
|
||
}
|
||
|
||
}
|
||
|
||
register(EventDetails)
|