instbyte 1.11.0 → 1.11.1
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.
- package/client/js/app.js +19 -14
- package/package.json +1 -2
- package/server/server.js +0 -91
package/client/js/app.js
CHANGED
|
@@ -425,6 +425,17 @@ async function togglePreview(id, filename) {
|
|
|
425
425
|
}
|
|
426
426
|
}
|
|
427
427
|
|
|
428
|
+
function safeCreateIcons(container) {
|
|
429
|
+
if (typeof lucide === "undefined") return;
|
|
430
|
+
requestAnimationFrame(() => {
|
|
431
|
+
if (container) {
|
|
432
|
+
lucide.createIcons({ nodes: [container] });
|
|
433
|
+
} else {
|
|
434
|
+
lucide.createIcons();
|
|
435
|
+
}
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
|
|
428
439
|
function handleRowClick(el, type, value) {
|
|
429
440
|
if (type === "text") {
|
|
430
441
|
navigator.clipboard.writeText(value).then(() => {
|
|
@@ -720,11 +731,6 @@ function buildItemEl(i) {
|
|
|
720
731
|
<div class="preview-panel" id="preview-${i.id}"></div>`;
|
|
721
732
|
|
|
722
733
|
seenObserver.observe(div);
|
|
723
|
-
if (typeof lucide !== "undefined") {
|
|
724
|
-
lucide.createIcons({ nodes: [div] });
|
|
725
|
-
} else {
|
|
726
|
-
console.warn("Lucide not yet defined when building item", i.id);
|
|
727
|
-
}
|
|
728
734
|
return div;
|
|
729
735
|
}
|
|
730
736
|
|
|
@@ -896,18 +902,18 @@ function editContent(id) {
|
|
|
896
902
|
function render(data) {
|
|
897
903
|
const el = document.getElementById("items");
|
|
898
904
|
el.innerHTML = "";
|
|
899
|
-
|
|
900
905
|
if (!data.length) {
|
|
901
906
|
el.innerHTML = `<div class="empty-state">Nothing here yet — paste, type, or drop a file to share</div>`;
|
|
902
907
|
return;
|
|
903
908
|
}
|
|
904
|
-
|
|
905
909
|
data.forEach(i => el.appendChild(buildItemEl(i)));
|
|
910
|
+
safeCreateIcons(el);
|
|
906
911
|
}
|
|
907
912
|
|
|
908
913
|
function renderMore(data) {
|
|
909
914
|
const el = document.getElementById("items");
|
|
910
915
|
data.forEach(i => el.appendChild(buildItemEl(i)));
|
|
916
|
+
safeCreateIcons(el);
|
|
911
917
|
}
|
|
912
918
|
|
|
913
919
|
function renderGrouped(data) {
|
|
@@ -929,12 +935,13 @@ function renderGrouped(data) {
|
|
|
929
935
|
const section = document.createElement("div");
|
|
930
936
|
section.style.marginTop = "20px";
|
|
931
937
|
section.innerHTML = `
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
938
|
+
<div style="font-size:13px;font-weight:600;color:#6b7280;margin-bottom:8px;">
|
|
939
|
+
${ch.toUpperCase()}
|
|
940
|
+
</div>`;
|
|
935
941
|
grouped[ch].forEach(i => section.appendChild(buildItemEl(i)));
|
|
936
942
|
el.appendChild(section);
|
|
937
943
|
});
|
|
944
|
+
safeCreateIcons(el); // once after all sections appended, not inside the loop
|
|
938
945
|
}
|
|
939
946
|
|
|
940
947
|
async function sendText() {
|
|
@@ -1111,7 +1118,7 @@ socket.on("new-item", item => {
|
|
|
1111
1118
|
}
|
|
1112
1119
|
}
|
|
1113
1120
|
|
|
1114
|
-
|
|
1121
|
+
safeCreateIcons(el);
|
|
1115
1122
|
if (item.uploader !== uploader) playChime();
|
|
1116
1123
|
|
|
1117
1124
|
} else if (item.uploader !== uploader) {
|
|
@@ -1378,9 +1385,7 @@ async function uploadFiles(files, overrideChannel) {
|
|
|
1378
1385
|
|
|
1379
1386
|
status.style.display = "none";
|
|
1380
1387
|
fileInput.value = "";
|
|
1381
|
-
//
|
|
1382
|
-
// but this catches any case where the socket path didn't fire (e.g. network hiccup).
|
|
1383
|
-
setTimeout(() => load(), 500);
|
|
1388
|
+
// socket new-item handles DOM update in real time — no reload needed
|
|
1384
1389
|
}
|
|
1385
1390
|
|
|
1386
1391
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "instbyte",
|
|
3
|
-
"version": "1.11.
|
|
3
|
+
"version": "1.11.1",
|
|
4
4
|
"description": "A self-hosted LAN sharing utility for fast, frictionless file, link, and snippet exchange across devices — no cloud required.",
|
|
5
5
|
"main": "bin/instbyte.js",
|
|
6
6
|
"bin": {
|
|
@@ -43,7 +43,6 @@
|
|
|
43
43
|
"express-rate-limit": "^7.1.5",
|
|
44
44
|
"helmet": "^8.1.0",
|
|
45
45
|
"multer": "^2.0.2",
|
|
46
|
-
"multicast-dns": "^7.2.5",
|
|
47
46
|
"sharp": "^0.33.2",
|
|
48
47
|
"socket.io": "^4.6.1",
|
|
49
48
|
"sqlite3": "^5.1.6"
|
package/server/server.js
CHANGED
|
@@ -19,8 +19,6 @@ const db = require("./db");
|
|
|
19
19
|
|
|
20
20
|
const config = require("./config");
|
|
21
21
|
|
|
22
|
-
let mdns = null;
|
|
23
|
-
try { mdns = require('multicast-dns'); } catch (e) { }
|
|
24
22
|
|
|
25
23
|
const UPLOADS_DIR = process.env.INSTBYTE_UPLOADS
|
|
26
24
|
|| path.join(__dirname, "../uploads");
|
|
@@ -1080,62 +1078,6 @@ function getLocalIP() {
|
|
|
1080
1078
|
}
|
|
1081
1079
|
|
|
1082
1080
|
|
|
1083
|
-
function getMdnsName() {
|
|
1084
|
-
const appName = config.branding && config.branding.appName;
|
|
1085
|
-
if (appName && appName.toLowerCase() !== 'instbyte') {
|
|
1086
|
-
return appName.toLowerCase().replace(/\s+/g, '-') + '.local';
|
|
1087
|
-
}
|
|
1088
|
-
return 'instbyte.local';
|
|
1089
|
-
}
|
|
1090
|
-
|
|
1091
|
-
function getHostnameFallback() {
|
|
1092
|
-
return os.hostname().toLowerCase() + '.local';
|
|
1093
|
-
}
|
|
1094
|
-
|
|
1095
|
-
function probeMdns(name) {
|
|
1096
|
-
return new Promise((resolve) => {
|
|
1097
|
-
if (!mdns) return resolve(false);
|
|
1098
|
-
const m = mdns();
|
|
1099
|
-
const timer = setTimeout(() => {
|
|
1100
|
-
m.destroy();
|
|
1101
|
-
resolve(false); // no response = name is free
|
|
1102
|
-
}, 2000);
|
|
1103
|
-
|
|
1104
|
-
m.on('response', (response) => {
|
|
1105
|
-
const taken = response.answers.some(a =>
|
|
1106
|
-
a.name === name && a.type === 'A'
|
|
1107
|
-
);
|
|
1108
|
-
if (taken) {
|
|
1109
|
-
clearTimeout(timer);
|
|
1110
|
-
m.destroy();
|
|
1111
|
-
resolve(true); // name is taken
|
|
1112
|
-
}
|
|
1113
|
-
});
|
|
1114
|
-
|
|
1115
|
-
m.query({ questions: [{ name, type: 'A' }] });
|
|
1116
|
-
});
|
|
1117
|
-
}
|
|
1118
|
-
|
|
1119
|
-
function startMdnsAdvertise(name, ip) {
|
|
1120
|
-
if (!mdns) return null;
|
|
1121
|
-
try {
|
|
1122
|
-
const m = mdns();
|
|
1123
|
-
m.on('query', (query) => {
|
|
1124
|
-
query.questions.forEach(q => {
|
|
1125
|
-
if (q.name === name && q.type === 'A') {
|
|
1126
|
-
m.respond({
|
|
1127
|
-
answers: [{ name, type: 'A', ttl: 300, data: ip }]
|
|
1128
|
-
});
|
|
1129
|
-
}
|
|
1130
|
-
});
|
|
1131
|
-
});
|
|
1132
|
-
return m;
|
|
1133
|
-
} catch (e) {
|
|
1134
|
-
return null;
|
|
1135
|
-
}
|
|
1136
|
-
}
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
1081
|
function listenOnFreePort(server, preferredPort) {
|
|
1140
1082
|
return new Promise((resolve, reject) => {
|
|
1141
1083
|
server.listen(preferredPort, () => resolve(server.address().port));
|
|
@@ -1155,7 +1097,6 @@ const PREFERRED = parseInt(process.env.PORT) || config.server.port;
|
|
|
1155
1097
|
const localIP = getLocalIP();
|
|
1156
1098
|
|
|
1157
1099
|
let PORT;
|
|
1158
|
-
let mdnsAdvertiser = null;
|
|
1159
1100
|
|
|
1160
1101
|
if (process.env.INSTBYTE_BOOT === '1') {
|
|
1161
1102
|
listenOnFreePort(server, PREFERRED).then(async p => {
|
|
@@ -1167,33 +1108,6 @@ if (process.env.INSTBYTE_BOOT === '1') {
|
|
|
1167
1108
|
console.log(`(port ${PREFERRED} was busy, switched to ${PORT})`);
|
|
1168
1109
|
}
|
|
1169
1110
|
|
|
1170
|
-
// mDNS
|
|
1171
|
-
if (mdns) {
|
|
1172
|
-
try {
|
|
1173
|
-
const preferredName = getMdnsName();
|
|
1174
|
-
const isTaken = await probeMdns(preferredName);
|
|
1175
|
-
|
|
1176
|
-
let mdnsName;
|
|
1177
|
-
if (isTaken) {
|
|
1178
|
-
mdnsName = getHostnameFallback();
|
|
1179
|
-
if (os.platform() !== 'win32') {
|
|
1180
|
-
console.log(`mDNS: http://${preferredName} already in use on this network`);
|
|
1181
|
-
console.log(`mDNS: http://${mdnsName}`);
|
|
1182
|
-
}
|
|
1183
|
-
} else {
|
|
1184
|
-
mdnsName = preferredName;
|
|
1185
|
-
if (os.platform() !== 'win32') {
|
|
1186
|
-
console.log(`mDNS: http://${mdnsName}`);
|
|
1187
|
-
}
|
|
1188
|
-
}
|
|
1189
|
-
|
|
1190
|
-
mdnsAdvertiser = startMdnsAdvertise(mdnsName, localIP);
|
|
1191
|
-
|
|
1192
|
-
} catch (e) {
|
|
1193
|
-
console.log("mDNS: unavailable on this network — use IP or QR code to join");
|
|
1194
|
-
}
|
|
1195
|
-
}
|
|
1196
|
-
|
|
1197
1111
|
console.log("");
|
|
1198
1112
|
scanOrphans();
|
|
1199
1113
|
}).catch(err => {
|
|
@@ -1211,11 +1125,6 @@ module.exports = { app, server, sessions };
|
|
|
1211
1125
|
function shutdown(signal) {
|
|
1212
1126
|
console.log(`\n${signal} received — shutting down gracefully...`);
|
|
1213
1127
|
|
|
1214
|
-
// destroy mDNS advertiser if running
|
|
1215
|
-
if (typeof mdnsAdvertiser !== 'undefined' && mdnsAdvertiser) {
|
|
1216
|
-
try { mdnsAdvertiser.destroy(); } catch (e) { }
|
|
1217
|
-
}
|
|
1218
|
-
|
|
1219
1128
|
// stop accepting new connections
|
|
1220
1129
|
server.close(() => {
|
|
1221
1130
|
console.log("HTTP server closed");
|