feat(react/widgets): port shared_info

This commit is contained in:
Elian Doran
2025-08-30 13:59:53 +03:00
parent 5f647a932d
commit fbec6d8873
16 changed files with 103 additions and 104 deletions

View File

@@ -1,15 +1,17 @@
import { ComponentChildren } from "preact";
import { CSSProperties } from "preact/compat";
interface AlertProps {
type: "info" | "danger" | "warning";
title?: string;
children: ComponentChildren;
className?: string;
style?: CSSProperties;
}
export default function Alert({ title, type, children, className }: AlertProps) {
export default function Alert({ title, type, children, className, style }: AlertProps) {
return (
<div className={`alert alert-${type} ${className ?? ""}`}>
<div className={`alert alert-${type} ${className ?? ""}`} style={style}>
{title && <h4>{title}</h4>}
{children}

View File

@@ -1,77 +0,0 @@
import NoteContextAwareWidget from "./note_context_aware_widget.js";
import options from "../services/options.js";
import attributeService from "../services/attributes.js";
import { t } from "../services/i18n.js";
import type FNote from "../entities/fnote.js";
import type { EventData } from "../components/app_context.js";
const TPL = /*html*/`
<div class="shared-info-widget alert alert-warning use-tn-links">
<style>
.shared-info-widget {
margin: 10px;
contain: none;
padding: 10px;
font-weight: bold;
}
</style>
<span class="shared-text"></span> <a class="shared-link external"></a>. ${t("shared_info.help_link")}
</div>`;
export default class SharedInfoWidget extends NoteContextAwareWidget {
private $sharedLink!: JQuery<HTMLElement>;
private $sharedText!: JQuery<HTMLElement>;
isEnabled() {
return super.isEnabled() && this.noteId !== "_share" && this.note?.hasAncestor("_share");
}
doRender() {
this.$widget = $(TPL);
this.$sharedLink = this.$widget.find(".shared-link");
this.$sharedText = this.$widget.find(".shared-text");
this.contentSized();
}
async refreshWithNote(note: FNote) {
const syncServerHost = options.get("syncServerHost");
let link;
const shareId = this.getShareId(note);
if (syncServerHost) {
link = `${syncServerHost}/share/${shareId}`;
this.$sharedText.text(t("shared_info.shared_publicly"));
} else {
let host = location.host;
if (host.endsWith("/")) {
// seems like IE has trailing slash
// https://github.com/zadam/trilium/issues/3782
host = host.substr(0, host.length - 1);
}
link = `${location.protocol}//${host}${location.pathname}share/${shareId}`;
this.$sharedText.text(t("shared_info.shared_locally"));
}
this.$sharedLink.attr("href", link).text(link);
}
getShareId(note: FNote) {
if (note.hasOwnedLabel("shareRoot")) {
return "";
}
return note.getOwnedLabelValue("shareAlias") || note.noteId;
}
entitiesReloadedEvent({ loadResults }: EventData<"entitiesReloaded">) {
if (loadResults.getAttributeRows().find((attr) => attr.name?.startsWith("_share") && attributeService.isAffecting(attr, this.note))) {
this.refresh();
} else if (loadResults.getBranchRows().find((branch) => branch.noteId === this.noteId)) {
this.refresh();
}
}
}

View File

@@ -0,0 +1,74 @@
import { useEffect, useState } from "preact/hooks";
import { t } from "../services/i18n";
import Alert from "./react/Alert";
import { useNoteContext, useTriliumEvent, useTriliumOption } from "./react/hooks";
import FNote from "../entities/fnote";
import attributes from "../services/attributes";
import RawHtml from "./react/RawHtml";
import HelpButton from "./react/HelpButton";
export default function SharedInfo() {
const { note } = useNoteContext();
const [ syncServerHost ] = useTriliumOption("syncServerHost");
const [ link, setLink ] = useState<string>();
function refresh() {
if (!note) return;
if (note.noteId === "_share" || !note?.hasAncestor("_share")) {
setLink(undefined);
return;
}
let link;
const shareId = getShareId(note);
if (syncServerHost) {
link = `${syncServerHost}/share/${shareId}`;
} else {
let host = location.host;
if (host.endsWith("/")) {
// seems like IE has trailing slash
// https://github.com/zadam/trilium/issues/3782
host = host.substring(0, host.length - 1);
}
link = `${location.protocol}//${host}${location.pathname}share/${shareId}`;
}
setLink(`<a href="${link}" class="external">${link}</a>`);
}
useEffect(refresh, [ note ]);
useTriliumEvent("entitiesReloaded", ({ loadResults }) => {
if (loadResults.getAttributeRows().find((attr) => attr.name?.startsWith("_share") && attributes.isAffecting(attr, note))) {
refresh();
} else if (loadResults.getBranchRows().find((branch) => branch.noteId === note?.noteId)) {
refresh();
}
});
return (
<Alert className="shared-info-widget" type="warning" style={{
contain: "none",
margin: "10px",
padding: "10px",
fontWeight: "bold",
display: !link ? "none" : undefined
}}>
{link && (
<RawHtml html={syncServerHost
? t("shared_info.shared_publicly", { link })
: t("shared_info.shared_locally", { link })} />
)}
<HelpButton helpPage="R9pX4DGra2Vt" style={{ width: "24px", height: "24px" }} />
</Alert>
)
}
function getShareId(note: FNote) {
if (note.hasOwnedLabel("shareRoot")) {
return "";
}
return note.getOwnedLabelValue("shareAlias") || note.noteId;
}