@decentnetwork/lan 0.1.142 → 0.1.144
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/dist/ui/desktop/app.js
CHANGED
|
@@ -53,6 +53,7 @@ const ICON_PATHS = {
|
|
|
53
53
|
arrowDown: '<path d="M12 4v15M6 13l6 6 6-6"/>',
|
|
54
54
|
shrink: '<path d="M4 14h6v6"/><path d="M20 10h-6V4"/><path d="m14 10 7-7"/><path d="m3 21 7-7"/>',
|
|
55
55
|
maximize: '<path d="M8 3H5a2 2 0 0 0-2 2v3"/><path d="M21 8V5a2 2 0 0 0-2-2h-3"/><path d="M3 16v3a2 2 0 0 0 2 2h3"/><path d="M16 21h3a2 2 0 0 0 2-2v-3"/>',
|
|
56
|
+
theater: '<rect x="2.5" y="6.5" width="19" height="11" rx="2"/>',
|
|
56
57
|
speaker: '<path d="M11 5 6 9H3v6h3l5 4V5Z"/><path d="M16 9a3 3 0 0 1 0 6"/><path d="M19 7a6 6 0 0 1 0 10"/>',
|
|
57
58
|
micFill: '<rect x="9" y="2.5" width="6" height="11.5" rx="3"/><path d="M5.5 11a6.5 6.5 0 0 0 13 0"/><path d="M12 17.5v3.5"/>'
|
|
58
59
|
};
|
|
@@ -1031,6 +1032,18 @@ const inputStyle = {
|
|
|
1031
1032
|
outline: "none",
|
|
1032
1033
|
minWidth: 0
|
|
1033
1034
|
};
|
|
1035
|
+
const mediaBtnStyle = {
|
|
1036
|
+
width: 28,
|
|
1037
|
+
height: 28,
|
|
1038
|
+
borderRadius: 8,
|
|
1039
|
+
border: "none",
|
|
1040
|
+
background: "rgba(0,0,0,0.5)",
|
|
1041
|
+
cursor: "pointer",
|
|
1042
|
+
display: "flex",
|
|
1043
|
+
alignItems: "center",
|
|
1044
|
+
justifyContent: "center",
|
|
1045
|
+
lineHeight: 0
|
|
1046
|
+
};
|
|
1034
1047
|
function Msg({ m, peer, T, onTheater }) {
|
|
1035
1048
|
const mine = m.from === "me";
|
|
1036
1049
|
return /* @__PURE__ */ React.createElement("div", { style: { display: "flex", justifyContent: mine ? "flex-end" : "flex-start", alignItems: "flex-end", gap: 8, margin: "3px 0" } }, !mine && /* @__PURE__ */ React.createElement(DkAvatar, { peer, size: 24, radius: 6, dot: false }), /* @__PURE__ */ React.createElement("div", { style: { maxWidth: m.file && (m.file.media === "image" || m.file.media === "video") ? "min(680px, 88%)" : "64%", display: "flex", flexDirection: "column", alignItems: mine ? "flex-end" : "flex-start" } }, m.file ? (
|
|
@@ -1049,7 +1062,7 @@ function Msg({ m, peer, T, onTheater }) {
|
|
|
1049
1062
|
border: "1px solid var(--line)",
|
|
1050
1063
|
borderRadius: 12,
|
|
1051
1064
|
padding: 6
|
|
1052
|
-
} }, (m.file.media === "image" || m.file.media === "video") && /* @__PURE__ */ React.createElement("div", { style: { position: "relative", lineHeight: 0 } }, m.file.media === "image" ? /* @__PURE__ */ React.createElement(
|
|
1065
|
+
} }, (m.file.media === "image" || m.file.media === "video") && /* @__PURE__ */ React.createElement("div", { "data-media": true, style: { position: "relative", lineHeight: 0 } }, m.file.media === "image" ? /* @__PURE__ */ React.createElement(
|
|
1053
1066
|
"img",
|
|
1054
1067
|
{
|
|
1055
1068
|
src: dkFileUrl(m.file.name),
|
|
@@ -1064,21 +1077,27 @@ function Msg({ m, peer, T, onTheater }) {
|
|
|
1064
1077
|
preload: "metadata",
|
|
1065
1078
|
style: { display: "block", width: "100%", maxHeight: "72vh", borderRadius: 8, objectFit: "contain", background: "#000" }
|
|
1066
1079
|
}
|
|
1067
|
-
), /* @__PURE__ */ React.createElement("
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1080
|
+
), /* @__PURE__ */ React.createElement("div", { style: { position: "absolute", top: 8, right: 8, display: "flex", gap: 6 } }, /* @__PURE__ */ React.createElement(
|
|
1081
|
+
"button",
|
|
1082
|
+
{
|
|
1083
|
+
onClick: () => onTheater({ kind: m.file.media, url: dkFileUrl(m.file.name), name: m.file.name }),
|
|
1084
|
+
title: "theater / \u7F51\u9875\u5168\u5C4F",
|
|
1085
|
+
style: mediaBtnStyle
|
|
1086
|
+
},
|
|
1087
|
+
/* @__PURE__ */ React.createElement(Icon, { name: "theater", size: 16, stroke: 2, color: "#fff" })
|
|
1088
|
+
), /* @__PURE__ */ React.createElement(
|
|
1089
|
+
"button",
|
|
1090
|
+
{
|
|
1091
|
+
onClick: (e) => {
|
|
1092
|
+
const w = e.currentTarget.closest("[data-media]");
|
|
1093
|
+
const el = w && w.querySelector("video,img");
|
|
1094
|
+
if (el && el.requestFullscreen) el.requestFullscreen();
|
|
1095
|
+
},
|
|
1096
|
+
title: "fullscreen / \u5168\u5C4F",
|
|
1097
|
+
style: mediaBtnStyle
|
|
1098
|
+
},
|
|
1099
|
+
/* @__PURE__ */ React.createElement(Icon, { name: "maximize", size: 16, stroke: 2, color: "#fff" })
|
|
1100
|
+
))), m.file.media === "audio" && /* @__PURE__ */ React.createElement("audio", { src: dkFileUrl(m.file.name), controls: true, style: { width: "100%" } }), /* @__PURE__ */ React.createElement("div", { style: { display: "flex", alignItems: "center", gap: 8, padding: "0 2px" } }, /* @__PURE__ */ React.createElement("span", { style: { flex: 1, minWidth: 0, fontFamily: "var(--mono)", fontSize: 11, color: "var(--faint)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" } }, m.file.name), /* @__PURE__ */ React.createElement("span", { style: { fontFamily: "var(--mono)", fontSize: 11, color: "var(--faint)", flexShrink: 0 } }, m.file.size), /* @__PURE__ */ React.createElement("a", { href: dkFileDownloadUrl(m.file.name), download: m.file.name, title: "download", style: { display: "inline-flex", flexShrink: 0 } }, /* @__PURE__ */ React.createElement(Icon, { name: "download", size: 15, stroke: 2, color: "var(--accent)" }))))
|
|
1082
1101
|
) : (() => {
|
|
1083
1102
|
const cardStyle = {
|
|
1084
1103
|
display: "flex",
|
package/dist/ui/server.js
CHANGED
|
@@ -176,7 +176,10 @@ export function startFriendUi(opts) {
|
|
|
176
176
|
const desktopIndex = join(DESKTOP_DIR, "index.html");
|
|
177
177
|
if (req.method === "GET" && (url === "/" || url === "/index.html")) {
|
|
178
178
|
if (existsSync(desktopIndex)) {
|
|
179
|
-
|
|
179
|
+
// no-store: the UI bundle is rebuilt in place on every UI change, so the
|
|
180
|
+
// browser must never serve a stale cached index/app.js (that's why UI
|
|
181
|
+
// updates appeared to "not take" until a hard reload).
|
|
182
|
+
res.writeHead(200, { "content-type": "text/html; charset=utf-8", "cache-control": "no-store" });
|
|
180
183
|
res.end(readFileSync(desktopIndex));
|
|
181
184
|
return;
|
|
182
185
|
}
|
|
@@ -195,7 +198,12 @@ export function startFriendUi(opts) {
|
|
|
195
198
|
const file = join(DESKTOP_DIR, rel);
|
|
196
199
|
// Guard against path traversal: resolved file must stay under DESKTOP_DIR.
|
|
197
200
|
if (existsSync(file) && file.startsWith(DESKTOP_DIR)) {
|
|
198
|
-
|
|
201
|
+
// app.js changes on every UI rebuild → never cache it. Vendored React
|
|
202
|
+
// UMD is stable, so let it cache normally.
|
|
203
|
+
const headers = { "content-type": "application/javascript; charset=utf-8" };
|
|
204
|
+
if (rel === "app.js")
|
|
205
|
+
headers["cache-control"] = "no-store";
|
|
206
|
+
res.writeHead(200, headers);
|
|
199
207
|
res.end(readFileSync(file));
|
|
200
208
|
return;
|
|
201
209
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@decentnetwork/lan",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.144",
|
|
4
4
|
"description": "Private virtual LAN for self-hosted services and AI agents, built on Elastos Carrier. NAT-traversal, name service, ACL, all over a peer-to-peer mesh — no public IP required.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
},
|
|
80
80
|
"dependencies": {
|
|
81
81
|
"@decentnetwork/dora": "^0.1.11",
|
|
82
|
-
"@decentnetwork/peer": "^0.1.
|
|
82
|
+
"@decentnetwork/peer": "^0.1.77",
|
|
83
83
|
"ink": "^5.2.1",
|
|
84
84
|
"js-yaml": "^4.1.0",
|
|
85
85
|
"node-forge": "^1.4.0",
|