setImageError(true)} />;
}
// Anything else: Show box
const infos = [];
if (attachment.size) {
infos.push(formatBytes(attachment.size));
}
if (expires) {
infos.push(
t("notifications_attachment_link_expires", {
date: formatShortDateTime(attachment.expires),
})
);
}
if (expired) {
infos.push(t("notifications_attachment_link_expired"));
}
const maybeInfoText =
infos.length > 0 ? (
<>
{infos.join(", ")}
>
) : null;
// If expired, just show infos without click target
if (expired) {
return (
{attachment.name}
{maybeInfoText}
);
}
// Not expired
return (
{attachment.name}
{maybeInfoText}
);
};
const Image = (props) => {
const { t } = useTranslation();
const [open, setOpen] = useState(false);
const [loaded, setLoaded] = useState(false);
return (
setOpen(true)}
onLoad={() => setLoaded(true)}
onError={props.onError}
sx={{
marginTop: 2,
borderRadius: "4px",
boxShadow: 2,
width: 1,
maxHeight: "400px",
objectFit: "cover",
cursor: "pointer",
}}
/>
setOpen(false)} BackdropComponent={LightboxBackdrop}>
);
};
const UserActions = (props) => (
<>
{props.notification.actions.map((action) => (
))}
>
);
const ACTION_PROGRESS_ONGOING = 1;
const ACTION_PROGRESS_SUCCESS = 2;
const ACTION_PROGRESS_FAILED = 3;
const ACTION_LABEL_SUFFIX = {
[ACTION_PROGRESS_ONGOING]: " …",
[ACTION_PROGRESS_SUCCESS]: " ✔",
[ACTION_PROGRESS_FAILED]: " ❌",
};
const updateActionStatus = (notification, action, progress, error) => {
subscriptionManager.updateNotification({
...notification,
actions: notification.actions.map((a) => (a.id === action.id ? { ...a, progress, error } : a)),
});
};
const performHttpAction = async (notification, action) => {
console.log(`[Notifications] Performing HTTP user action`, action);
try {
updateActionStatus(notification, action, ACTION_PROGRESS_ONGOING, null);
const response = await fetch(action.url, {
method: action.method ?? "POST",
headers: action.headers ?? {},
// This must not null-coalesce to a non nullish value. Otherwise, the fetch API
// will reject it for "having a body"
body: action.body,
});
console.log(`[Notifications] HTTP user action response`, response);
const success = response.status >= 200 && response.status <= 299;
if (success) {
updateActionStatus(notification, action, ACTION_PROGRESS_SUCCESS, null);
} else {
updateActionStatus(notification, action, ACTION_PROGRESS_FAILED, `${action.label}: Unexpected response HTTP ${response.status}`);
}
} catch (e) {
console.log(`[Notifications] HTTP action failed`, e);
updateActionStatus(notification, action, ACTION_PROGRESS_FAILED, `${action.label}: ${e} Check developer console for details.`);
}
};
const UserAction = (props) => {
const { t } = useTranslation();
const { notification } = props;
const { action } = props;
if (action.action === "broadcast") {
return (
);
}
if (action.action === "view") {
return (
);
}
if (action.action === "http") {
const method = action.method ?? "POST";
const label = action.label + (ACTION_LABEL_SUFFIX[action.progress ?? 0] ?? "");
return (
);
}
return null; // Others
};
const NoNotifications = (props) => {
const { t } = useTranslation();
const topicShortUrlResolved = topicShortUrl(props.subscription.baseUrl, props.subscription.topic);
return (
{t("notifications_none_for_topic_title")}
{t("notifications_none_for_topic_description")}
{t("notifications_example")}:
{'$ curl -d "Hi" '}
{topicShortUrlResolved}
);
};
const NoNotificationsWithoutSubscription = (props) => {
const { t } = useTranslation();
const subscription = props.subscriptions[0];
const topicShortUrlResolved = topicShortUrl(subscription.baseUrl, subscription.topic);
return (
{t("notifications_none_for_any_title")}
{t("notifications_none_for_any_description")}
{t("notifications_example")}:
{'$ curl -d "Hi" '}
{topicShortUrlResolved}
);
};
const NoSubscriptions = () => {
const { t } = useTranslation();
return (
{t("notifications_no_subscriptions_title")}
{t("notifications_no_subscriptions_description", {
linktext: t("nav_button_subscribe"),
})}
);
};
const ForMoreDetails = () => (
,
docsLink: ,
}}
/>
);
const Loading = () => {
const { t } = useTranslation();
return (
{t("notifications_loading")}
);
};