fix: chat not opening after SAS in v4.8.14 (nowTick scope) — v4.8.15
The new composer props (nowTick, codeMode, view-once/timer setters, unsend/expire handlers) were threaded into EnhancedConnectionSetup, but the message list and composer live in the sibling EnhancedChatInterface. After SAS confirmation the verified-state re-render referenced an out-of-scope `nowTick`, throwing "ReferenceError: Can't find variable: nowTick" so the chat never rendered. Move the prop destructuring and pass-through onto EnhancedChatInterface (where the chat UI actually is) and revert the mistaken additions on EnhancedConnectionSetup. No behavioural change to the v4.8.14 features otherwise. Bumps to 4.8.15.
This commit is contained in:
1 parent
15173a9278
commit
cb72b9cb1c
14 files changed
+111
-101
No files matched your search
@@ -1,5 +1,11 @@
|
||||
# Changelog
|
||||
|
||||
## v4.8.15 — Fix: chat would not open after SAS in v4.8.14
|
||||
|
||||
### Fixed
|
||||
|
||||
- The secure chat failed to open after both peers confirmed the SAS code: the message list and composer (in `EnhancedChatInterface`) referenced `nowTick`, `onUnsendMessage` and the new composer props, but those were threaded into the sibling `EnhancedConnectionSetup` component by mistake. At runtime this threw `ReferenceError: Can't find variable: nowTick` during the verified-state re-render, so the chat never rendered. The new props are now destructured and passed on `EnhancedChatInterface`, where the chat UI actually lives. No behavioural change to the v4.8.14 features otherwise.
|
||||
|
||||
## v4.8.14 — Secure chat tools: code blocks, view-once, disappearing, unsend, panic
|
||||
|
||||
Adds privacy-focused messaging controls. Per-message metadata (id, view-once, timer) travels **inside the encrypted message envelope**, never in the sanitized text, so message content cannot spoof or corrupt these controls. The unsend/delete signal travels over the authenticated DTLS control channel like other system messages.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# SecureBit.chat v4.8.14
|
||||
# SecureBit.chat v4.8.15
|
||||
|
||||
SecureBit.chat is a browser-based peer-to-peer chat application built on WebRTC and Web Crypto APIs. It is designed for direct encrypted communication, explicit peer verification, and a small operational footprint without account registration or server-side message storage.
|
||||
|
||||
@@ -15,7 +15,11 @@ SecureBit.chat uses:
|
||||
|
||||
A session is not treated as verified until both peers complete the interactive SAS flow. Each user must compare the displayed code with the peer through an out-of-band channel and enter the matching code manually. Three failed SAS attempts terminate the session.
|
||||
|
||||
## Highlights in v4.8.14
|
||||
## Highlights in v4.8.15
|
||||
|
||||
- Fix: the secure chat failed to open after SAS confirmation in v4.8.14 (a `nowTick` reference was scoped to the wrong component). The new messaging controls are now wired into the chat component correctly.
|
||||
|
||||
The v4.8.14 messaging features:
|
||||
|
||||
- Code blocks: a composer button wraps a message in a monospace code window with a one-click copy button (clipboard auto-clears after 30s).
|
||||
- View-once messages: the recipient sees a blurred bubble that reveals on tap and is then deleted. Cooperative, like WhatsApp view-once — not screenshot-proof.
|
||||
|
||||
@@ -22,6 +22,6 @@ SecureBit.chat is intended for legitimate private communication, journalism, res
|
||||
|
||||
## Current release
|
||||
|
||||
- Product release: `v4.8.14`
|
||||
- Product release: `v4.8.15`
|
||||
- Protocol version: `4.1`
|
||||
- Last updated: May 17, 2026
|
||||
Vendored
+1
-1
@@ -17487,7 +17487,7 @@ Right-click or Ctrl+click to disconnect`,
|
||||
React.createElement("p", {
|
||||
key: "subtitle",
|
||||
className: "text-xs sm:text-sm text-muted hidden sm:block"
|
||||
}, "End-to-end freedom v4.8.14")
|
||||
}, "End-to-end freedom v4.8.15")
|
||||
])
|
||||
]),
|
||||
// Status and Controls - Responsive
|
||||
|
||||
Vendored
+1
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"version": 3,
|
||||
"sources": ["../src/notifications/SecureNotificationManager.js", "../src/notifications/NotificationIntegration.js", "../node_modules/dompurify/src/utils.ts", "../node_modules/dompurify/src/tags.ts", "../node_modules/dompurify/src/attrs.ts", "../node_modules/dompurify/src/regexp.ts", "../node_modules/dompurify/src/purify.ts", "../src/crypto/EnhancedSecureCryptoUtils.js", "../src/transfer/EnhancedSecureFileTransfer.js", "../src/network/EnhancedSecureWebRTCManager.js", "../src/scripts/app-boot.js", "../src/components/ui/Header.jsx", "../src/components/ui/DownloadApps.jsx", "../src/components/ui/BecomePartner.jsx", "../src/components/ui/UniqueFeatureSlider.jsx", "../src/components/ui/SecurityFeatures.jsx", "../src/components/ui/Testimonials.jsx", "../src/components/ui/ComparisonTable.jsx", "../src/components/ui/Roadmap.jsx", "../src/components/ui/FileTransfer.jsx", "../src/network/iceServers.js", "../src/components/ui/IceServerSettings.jsx"],
|
||||
"sourcesContent": ["/**\n * Secure and Reliable Notification Manager for P2P WebRTC Chat\n * Follows best practices: OWASP, MDN, Chrome DevRel\n * \n * @version 1.0.0\n * @author SecureBit Team\n * @license MIT\n */\n\nclass SecureChatNotificationManager {\n constructor(config = {}) {\n // Safely read Notification permission (iOS Safari may not define Notification)\n this.permission = (typeof Notification !== 'undefined' && Notification && typeof Notification.permission === 'string')\n ? Notification.permission\n : 'denied';\n this.isTabActive = this.checkTabActive(); // Initialize with proper check\n this.unreadCount = 0;\n this.originalTitle = document.title;\n this.notificationQueue = [];\n this.maxQueueSize = config.maxQueueSize || 5;\n this.rateLimitMs = config.rateLimitMs || 2000; // Spam protection\n this.lastNotificationTime = 0;\n this.trustedOrigins = config.trustedOrigins || [];\n \n // Secure context flag\n this.isSecureContext = window.isSecureContext;\n \n // Cross-browser compatibility for Page Visibility API\n this.hidden = this.getHiddenProperty();\n this.visibilityChange = this.getVisibilityChangeEvent();\n \n this.initVisibilityTracking();\n this.initSecurityChecks();\n }\n\n /**\n * Initialize security checks and validation\n * @private\n */\n initSecurityChecks() {\n // Security checks are performed silently\n }\n\n /**\n * Get hidden property name for cross-browser compatibility\n * @returns {string} Hidden property name\n * @private\n */\n getHiddenProperty() {\n if (typeof document.hidden !== \"undefined\") {\n return \"hidden\";\n } else if (typeof document.msHidden !== \"undefined\") {\n return \"msHidden\";\n } else if (typeof document.webkitHidden !== \"undefined\") {\n return \"webkitHidden\";\n }\n return \"hidden\"; // fallback\n }\n\n /**\n * Get visibility change event name for cross-browser compatibility\n * @returns {string} Visibility change event name\n * @private\n */\n getVisibilityChangeEvent() {\n if (typeof document.hidden !== \"undefined\") {\n return \"visibilitychange\";\n } else if (typeof document.msHidden !== \"undefined\") {\n return \"msvisibilitychange\";\n } else if (typeof document.webkitHidden !== \"undefined\") {\n return \"webkitvisibilitychange\";\n }\n return \"visibilitychange\"; // fallback\n }\n\n /**\n * Check if tab is currently active using multiple methods\n * @returns {boolean} True if tab is active\n * @private\n */\n checkTabActive() {\n // Primary method: Page Visibility API\n if (this.hidden && typeof document[this.hidden] !== \"undefined\") {\n return !document[this.hidden];\n }\n \n // Fallback method: document.hasFocus()\n if (typeof document.hasFocus === \"function\") {\n return document.hasFocus();\n }\n \n // Ultimate fallback: assume active\n return true;\n }\n\n /**\n * Initialize page visibility tracking (Page Visibility API)\n * @private\n */\n initVisibilityTracking() {\n // Primary method: Page Visibility API with cross-browser support\n if (typeof document.addEventListener !== \"undefined\" && typeof document[this.hidden] !== \"undefined\") {\n document.addEventListener(this.visibilityChange, () => {\n this.isTabActive = this.checkTabActive();\n \n if (this.isTabActive) {\n this.resetUnreadCount();\n this.clearNotificationQueue();\n }\n });\n }\n\n // Fallback method: Window focus/blur events\n window.addEventListener('focus', () => {\n this.isTabActive = this.checkTabActive();\n if (this.isTabActive) {\n this.resetUnreadCount();\n }\n });\n\n window.addEventListener('blur', () => {\n this.isTabActive = this.checkTabActive();\n });\n\n // Page unload cleanup\n window.addEventListener('beforeunload', () => {\n this.clearNotificationQueue();\n });\n }\n\n /**\n * Request notification permission (BEST PRACTICE: Only call in response to user action)\n * Never call on page load!\n * @returns {Promise<boolean>} Permission granted status\n */\n async requestPermission() {\n // Secure context check\n if (!this.isSecureContext || !('Notification' in window)) {\n return false;\n }\n\n if (this.permission === 'granted') {\n return true;\n }\n\n if (this.permission === 'denied') {\n return false;\n }\n\n try {\n this.permission = await Notification.requestPermission();\n return this.permission === 'granted';\n } catch (error) {\n return false;\n }\n }\n\n /**\n * Update page title with unread count\n * @private\n */\n updateTitle() {\n if (this.unreadCount > 0) {\n document.title = `(${this.unreadCount}) ${this.originalTitle}`;\n } else {\n document.title = this.originalTitle;\n }\n }\n\n /**\n Line truncated
|
||||
"sourcesContent": ["/**\n * Secure and Reliable Notification Manager for P2P WebRTC Chat\n * Follows best practices: OWASP, MDN, Chrome DevRel\n * \n * @version 1.0.0\n * @author SecureBit Team\n * @license MIT\n */\n\nclass SecureChatNotificationManager {\n constructor(config = {}) {\n // Safely read Notification permission (iOS Safari may not define Notification)\n this.permission = (typeof Notification !== 'undefined' && Notification && typeof Notification.permission === 'string')\n ? Notification.permission\n : 'denied';\n this.isTabActive = this.checkTabActive(); // Initialize with proper check\n this.unreadCount = 0;\n this.originalTitle = document.title;\n this.notificationQueue = [];\n this.maxQueueSize = config.maxQueueSize || 5;\n this.rateLimitMs = config.rateLimitMs || 2000; // Spam protection\n this.lastNotificationTime = 0;\n this.trustedOrigins = config.trustedOrigins || [];\n \n // Secure context flag\n this.isSecureContext = window.isSecureContext;\n \n // Cross-browser compatibility for Page Visibility API\n this.hidden = this.getHiddenProperty();\n this.visibilityChange = this.getVisibilityChangeEvent();\n \n this.initVisibilityTracking();\n this.initSecurityChecks();\n }\n\n /**\n * Initialize security checks and validation\n * @private\n */\n initSecurityChecks() {\n // Security checks are performed silently\n }\n\n /**\n * Get hidden property name for cross-browser compatibility\n * @returns {string} Hidden property name\n * @private\n */\n getHiddenProperty() {\n if (typeof document.hidden !== \"undefined\") {\n return \"hidden\";\n } else if (typeof document.msHidden !== \"undefined\") {\n return \"msHidden\";\n } else if (typeof document.webkitHidden !== \"undefined\") {\n return \"webkitHidden\";\n }\n return \"hidden\"; // fallback\n }\n\n /**\n * Get visibility change event name for cross-browser compatibility\n * @returns {string} Visibility change event name\n * @private\n */\n getVisibilityChangeEvent() {\n if (typeof document.hidden !== \"undefined\") {\n return \"visibilitychange\";\n } else if (typeof document.msHidden !== \"undefined\") {\n return \"msvisibilitychange\";\n } else if (typeof document.webkitHidden !== \"undefined\") {\n return \"webkitvisibilitychange\";\n }\n return \"visibilitychange\"; // fallback\n }\n\n /**\n * Check if tab is currently active using multiple methods\n * @returns {boolean} True if tab is active\n * @private\n */\n checkTabActive() {\n // Primary method: Page Visibility API\n if (this.hidden && typeof document[this.hidden] !== \"undefined\") {\n return !document[this.hidden];\n }\n \n // Fallback method: document.hasFocus()\n if (typeof document.hasFocus === \"function\") {\n return document.hasFocus();\n }\n \n // Ultimate fallback: assume active\n return true;\n }\n\n /**\n * Initialize page visibility tracking (Page Visibility API)\n * @private\n */\n initVisibilityTracking() {\n // Primary method: Page Visibility API with cross-browser support\n if (typeof document.addEventListener !== \"undefined\" && typeof document[this.hidden] !== \"undefined\") {\n document.addEventListener(this.visibilityChange, () => {\n this.isTabActive = this.checkTabActive();\n \n if (this.isTabActive) {\n this.resetUnreadCount();\n this.clearNotificationQueue();\n }\n });\n }\n\n // Fallback method: Window focus/blur events\n window.addEventListener('focus', () => {\n this.isTabActive = this.checkTabActive();\n if (this.isTabActive) {\n this.resetUnreadCount();\n }\n });\n\n window.addEventListener('blur', () => {\n this.isTabActive = this.checkTabActive();\n });\n\n // Page unload cleanup\n window.addEventListener('beforeunload', () => {\n this.clearNotificationQueue();\n });\n }\n\n /**\n * Request notification permission (BEST PRACTICE: Only call in response to user action)\n * Never call on page load!\n * @returns {Promise<boolean>} Permission granted status\n */\n async requestPermission() {\n // Secure context check\n if (!this.isSecureContext || !('Notification' in window)) {\n return false;\n }\n\n if (this.permission === 'granted') {\n return true;\n }\n\n if (this.permission === 'denied') {\n return false;\n }\n\n try {\n this.permission = await Notification.requestPermission();\n return this.permission === 'granted';\n } catch (error) {\n return false;\n }\n }\n\n /**\n * Update page title with unread count\n * @private\n */\n updateTitle() {\n if (this.unreadCount > 0) {\n document.title = `(${this.unreadCount}) ${this.originalTitle}`;\n } else {\n document.title = this.originalTitle;\n }\n }\n\n /**\n Line truncated
|
||||
"mappings": "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 truncated
|
||||
"names": ["text", "NotificationIntegration", "entries", "Object", "setPrototypeOf", "isFrozen", "getPrototypeOf", "getOwnPropertyDescriptor", "freeze", "seal", "create", "_ref", "Reflect", "apply", "construct", "x", "func", "thisArg", "_len", "arguments", "length", "args", "Array", "_key", "Func", "_len2", "_key2", "arrayForEach", "unapply", "prototype", "forEach", "arrayLastIndexOf", "lastIndexOf", "arrayPop", "pop", "arrayPush", "push", "arraySplice", "splice", "arrayIsArray", "isArray", "stringToLowerCase", "String", "toLowerCase", "stringToString", "toString", "stringMatch", "match", "stringReplace", "replace", "stringIndexOf", "indexOf", "stringTrim", "trim", "numberToString", "Number", "booleanToString", "Boolean", "bigintToString", "BigInt", "symbolToString", "Symbol", "objectHasOwnProperty", "hasOwnProperty", "objectToString", "regExpTest", "RegExp", "test", "typeErrorCreate", "unconstruct", "TypeError", "lastIndex", "_len3", "_key3", "_len4", "_key4", "addToSet", "set", "array", "transformCaseFunc", "l", "element", "lcElement", "cleanArray", "index", "isPropertyExist", "clone", "object", "newObject", "_ref2", "_ref3", "_slicedToArray", "property", "value", "constructor", "stringifyValue", "valueAsRecord", "valueToString", "lookupGetter", "stringified", "prop", "desc", "get", "fallbackValue", "isRegex", "_unused", "html", "svg", "svgFilters", "svgDisallowed", "mathMl", "mathMlDisallowed", "text", "xml", "MUSTACHE_EXPR", "ERB_EXPR", "TMPLIT_EXPR", "DATA_ATTR", "ARIA_ATTR", "IS_ALLOWED_URI", "IS_SCRIPT_OR_DATA", "ATTR_WHITESPACE", "DOCTYPE_NAME", "CUSTOM_ELEMENT", "ELEMENT_MARKUP_PROBE", "COMMENT_MARKUP_PROBE", "FALLBACK_TAG_CLOSE", "SELF_CLOSING_TAG", "NODE_TYPE", "attribute", "cdataSection", "entityReference", "entityNode", "processingInstruction", "comment", "document", "documentType", "documentFragment", "notation", "getGlobal", "window", "_createTrustedTypesPolicy", "trustedTypes", "purifyHostElement", "createPolicy", "suffix", "ATTR_NAME", "hasAttribute", "getAttribute", "policyName", "createHTML", "createScriptURL", "scriptUrl", "_", "console", "warn", "_createHooksMap", "afterSanitizeAttributes", "afterSanitizeElements", "afterSanitizeShadowDOM", "beforeSanitizeAttributes", "beforeSanitizeElements", "beforeSanitizeShadowDOM", "uponSanitizeAttribute", "uponSanitizeElement", "uponSanitizeShadowNode", "_resolveSetOption", "cfg", "key", "fallback", "options", "base", "transform", "createDOMPurify", "undefined", "DOMPurify", "root", "version", "VERSION", "removed", "nodeType", "Element", "isSupported", "originalDocument", "currentScript", "DocumentFragment", "HTMLTemplateElement", "Node", "NodeFilter", "_window$NamedNodeMap", "NamedNodeMap", "MozNamedAttrMap", "HTMLFormElement", "DOMParser", "ElementPrototype", "cloneNode", "remove", "getNextSibling", "getChildNodes", "getParentNode", "getShadowRoot", "getAttributes", "getNodeType", "getNodeName", "template", "createElement", "content", "ownerDocument", "trustedTypesPolicy", "emptyHTML", "defaultTrustedTypesPolicy", "defaultTrustedTypesPolicyResolved", "IN_TRUSTED_TYPES_POLICY", "_assertNotInTrustedTypesPolicy", "_createTrustedHTML", "_createTrustedScriptURL", "_getDefaultTrustedTypesPolicy", "_document", "implementation", "createNodeIterator", "createDocumentFragment", "getElementsByTagName", "importNode", "hooks", "createHTMLDocument", "EXPRESSIONS", "ALLOWED_TAGS", "DEFAULT_ALLOWED_TAGS", "TAGS", "ALLOWED_ATTR", "DEFAULT_ALLOWED_ATTR", "ATTRS", "CUSTOM_ELEMENT_HANDLING", "tagNameCheck", "writable", "configurable", "enumerable", "attributeNameCheck", "allowCustomizedBuiltInElements", "FORBID_TAGS", "FORBID_ATTR", "EXTRA_ELEMENT_HANDLING", "tagCheck", "attributeCheck", "ALLOW_ARIA_ATTR", "ALLOW_DATA_ATTR", "ALLOW_UNKNOWN_PROTOCOLS", "ALLOW_SELF_CLOSE_IN_ATTR", "SAFE_FOR_TEMPLATES", "SAFE_FOR_XML", "WHOLE_DOCUMENT", "SET_CONFIG", "FORCE_BODY", "RETURN_DOM", "RETURN_DOM_FRAGMENT", "RETURN_TRUSTED_TYPE", "SANITIZE_DOM", "SANITIZE_NAMED_PROPS", "SANITIZE_NAMED_PROPS_PREFIX", "KEEP_CONTENT", "IN_PLACE", "USE_PROFILES", "FORBID_CONTENTS", "DEFAULT_FORBID_CONTENTS", "DATA_URI_TAGS", "DEFAULT_DATA_URI_TAGS", "URI_SAFE_ATTRIBUTES", "DEFAULT_URI_SAFE_ATTRIBUTES", "MATHML_NAMESPACE", "SVG_NAMESPACE", "HTML_NAMESPACE", "NAMESPACE", "IS_EMPTY_INPUT", "ALLOWED_NAMESPACES", "DEFAULT_ALLOWED_NAMESPACES", "DEFAULT_MATHML_TEXT_INTEGRATION_POINTS", "MATHML_TEXT_INTEGRATION_POINTS", "DEFAULT_HTML_INTEGRATION_POINTS", "HTML_INTEGRATION_POINTS", "COMMON_SVG_AND_HTML_ELEMENTS", "PARSER_MEDIA_TYPE", "SUPPORTED_PARSER_MEDIA_TYPES", "DEFAULT_PARSER_MEDIA_TYPE", "CONFIG", "formElement", "isRegexOrFunction", "testValue", "Function", "_parseConfig", "ALLOWED_URI_REGEXP", "customElementHandling", "ADD_TAGS", "ADD_ATTR", "ADD_URI_SAFE_ATTR", "ADD_FORBID_CONTENTS", "table", "tbody", "TRUSTED_TYPES_POLICY", "previousTrustedTypesPolicy", "error", "ALL_SVG_TAGS", "ALL_MATHML_TAGS", "_checkSvgNamespace", "tagName", "parent", "parentTagName", "namespaceURI", "_checkMathMlNamespaceLine truncated
|
||||
}
|
||||
Vendored
+49
-49
@@ -266,12 +266,12 @@ var MessageBody = ({ text }) => {
|
||||
)
|
||||
);
|
||||
};
|
||||
var ChatToolbar = ({ codeMode: codeMode2, setCodeMode: setCodeMode2, viewOnceMode: viewOnceMode2, setViewOnceMode: setViewOnceMode2, disappearTtl: disappearTtl2, setDisappearTtl: setDisappearTtl2, onPanicWipe: onPanicWipe2 }) => {
|
||||
var ChatToolbar = ({ codeMode, setCodeMode, viewOnceMode, setViewOnceMode, disappearTtl, setDisappearTtl, onPanicWipe }) => {
|
||||
const ttlCycle = [0, 30, 300, 3600];
|
||||
const ttlLabel = (s) => s === 0 ? "Off" : s >= 3600 ? `${Math.round(s / 3600)}h` : s >= 60 ? `${Math.round(s / 60)}m` : `${s}s`;
|
||||
const cycleTtl = () => {
|
||||
const i = ttlCycle.indexOf(disappearTtl2);
|
||||
setDisappearTtl2(ttlCycle[(i + 1) % ttlCycle.length] || 0);
|
||||
const i = ttlCycle.indexOf(disappearTtl);
|
||||
setDisappearTtl(ttlCycle[(i + 1) % ttlCycle.length] || 0);
|
||||
};
|
||||
const pill = (key, { active, activeClass, icon, label, title, onClick }) => React.createElement("button", {
|
||||
key,
|
||||
@@ -287,26 +287,26 @@ var ChatToolbar = ({ codeMode: codeMode2, setCodeMode: setCodeMode2, viewOnceMod
|
||||
className: "flex items-center flex-wrap gap-2 pb-3"
|
||||
}, [
|
||||
pill("code", {
|
||||
active: codeMode2,
|
||||
active: codeMode,
|
||||
activeClass: "text-green-400 border-green-500/40 bg-green-500/10",
|
||||
icon: "fas fa-code",
|
||||
label: "Code",
|
||||
title: "Send as a code block (with copy button)",
|
||||
onClick: () => setCodeMode2((v) => !v)
|
||||
onClick: () => setCodeMode((v) => !v)
|
||||
}),
|
||||
pill("once", {
|
||||
active: viewOnceMode2,
|
||||
active: viewOnceMode,
|
||||
activeClass: "text-orange-400 border-orange-500/40 bg-orange-500/10",
|
||||
icon: "fas fa-eye-slash",
|
||||
label: "View once",
|
||||
title: "Recipient can read it once, then it is deleted (cooperative \u2014 not screenshot-proof)",
|
||||
onClick: () => setViewOnceMode2((v) => !v)
|
||||
onClick: () => setViewOnceMode((v) => !v)
|
||||
}),
|
||||
pill("ttl", {
|
||||
active: disappearTtl2 > 0,
|
||||
active: disappearTtl > 0,
|
||||
activeClass: "text-blue-400 border-blue-500/40 bg-blue-500/10",
|
||||
icon: "fas fa-stopwatch",
|
||||
label: `Timer: ${ttlLabel(disappearTtl2)}`,
|
||||
label: `Timer: ${ttlLabel(disappearTtl)}`,
|
||||
title: "Disappearing messages \u2014 auto-delete on both sides",
|
||||
onClick: cycleTtl
|
||||
}),
|
||||
@@ -319,7 +319,7 @@ var ChatToolbar = ({ codeMode: codeMode2, setCodeMode: setCodeMode2, viewOnceMod
|
||||
title: "Wipe this conversation and keys, and disconnect",
|
||||
onClick: () => {
|
||||
const ok = typeof window !== "undefined" && window.confirm ? window.confirm("Panic wipe: delete all messages, wipe keys and disconnect now?") : true;
|
||||
if (ok && typeof onPanicWipe2 === "function") onPanicWipe2();
|
||||
if (ok && typeof onPanicWipe === "function") onPanicWipe();
|
||||
}
|
||||
})
|
||||
]);
|
||||
@@ -536,7 +536,7 @@ var VerificationStep = ({ verificationCode, onConfirm, onReject, localConfirmed,
|
||||
])
|
||||
]);
|
||||
};
|
||||
var EnhancedChatMessage = ({ message, type, timestamp, mid, viewOnce, expiresAt, nowTick: nowTick2, canUnsend, onUnsend, onExpire }) => {
|
||||
var EnhancedChatMessage = ({ message, type, timestamp, mid, viewOnce, expiresAt, nowTick, canUnsend, onUnsend, onExpire }) => {
|
||||
const [revealed, setRevealed] = React.useState(false);
|
||||
const revealTimerRef = React.useRef(null);
|
||||
const formatTime = (ts) => {
|
||||
@@ -578,7 +578,7 @@ var EnhancedChatMessage = ({ message, type, timestamp, mid, viewOnce, expiresAt,
|
||||
}
|
||||
};
|
||||
const style = getMessageStyle();
|
||||
const remaining = typeof expiresAt === "number" ? Math.max(0, Math.ceil((expiresAt - (nowTick2 || Date.now())) / 1e3)) : null;
|
||||
const remaining = typeof expiresAt === "number" ? Math.max(0, Math.ceil((expiresAt - (nowTick || Date.now())) / 1e3)) : null;
|
||||
const isViewOnce = type === "received" && viewOnce === true;
|
||||
const handleReveal = () => {
|
||||
if (revealed) return;
|
||||
@@ -700,18 +700,7 @@ var EnhancedConnectionSetup = ({
|
||||
handleCreateOffer,
|
||||
relayOnlyMode,
|
||||
setRelayOnlyMode,
|
||||
webrtcManagerRef,
|
||||
// Secure chat extras
|
||||
codeMode: codeMode2,
|
||||
setCodeMode: setCodeMode2,
|
||||
viewOnceMode: viewOnceMode2,
|
||||
setViewOnceMode: setViewOnceMode2,
|
||||
disappearTtl: disappearTtl2,
|
||||
setDisappearTtl: setDisappearTtl2,
|
||||
nowTick: nowTick2,
|
||||
onUnsendMessage: onUnsendMessage2,
|
||||
onMessageExpire: onMessageExpire2,
|
||||
onPanicWipe: onPanicWipe2
|
||||
webrtcManagerRef
|
||||
}) => {
|
||||
const [mode, setMode] = React.useState("select");
|
||||
const [notificationPermissionRequested, setNotificationPermissionRequested] = React.useState(false);
|
||||
@@ -1536,7 +1525,18 @@ var EnhancedChatInterface = ({
|
||||
scrollToBottom,
|
||||
webrtcManager,
|
||||
pendingIncomingFiles = [],
|
||||
onIncomingDecision
|
||||
onIncomingDecision,
|
||||
// Secure chat extras
|
||||
codeMode,
|
||||
setCodeMode,
|
||||
viewOnceMode,
|
||||
setViewOnceMode,
|
||||
disappearTtl,
|
||||
setDisappearTtl,
|
||||
nowTick,
|
||||
onUnsendMessage,
|
||||
onMessageExpire,
|
||||
onPanicWipe
|
||||
}) => {
|
||||
const [showScrollButton, setShowScrollButton] = React.useState(false);
|
||||
const [showFileTransfer, setShowFileTransfer] = React.useState(false);
|
||||
@@ -1840,10 +1840,10 @@ var EnhancedChatInterface = ({
|
||||
};
|
||||
var EnhancedSecureP2PChat = () => {
|
||||
const [messages, setMessages] = React.useState([]);
|
||||
const [codeMode2, setCodeMode2] = React.useState(false);
|
||||
const [viewOnceMode2, setViewOnceMode2] = React.useState(false);
|
||||
const [disappearTtl2, setDisappearTtl2] = React.useState(0);
|
||||
const [nowTick2, setNowTick] = React.useState(() => Date.now());
|
||||
const [codeMode, setCodeMode] = React.useState(false);
|
||||
const [viewOnceMode, setViewOnceMode] = React.useState(false);
|
||||
const [disappearTtl, setDisappearTtl] = React.useState(0);
|
||||
const [nowTick, setNowTick] = React.useState(() => Date.now());
|
||||
const [connectionStatus, setConnectionStatus] = React.useState("disconnected");
|
||||
const [relayOnlyMode, setRelayOnlyMode] = React.useState(() => {
|
||||
try {
|
||||
@@ -2270,7 +2270,7 @@ var EnhancedSecureP2PChat = () => {
|
||||
} catch (error) {
|
||||
}
|
||||
}
|
||||
handleMessage(" SecureBit.chat Enhanced Security Edition v4.8.14 - ECDH + DTLS + SAS initialized. Ready to establish a secure connection with ECDH key exchange, DTLS fingerprint verification, and SAS authentication to prevent MITM attacks.", "system");
|
||||
handleMessage(" SecureBit.chat Enhanced Security Edition v4.8.15 - ECDH + DTLS + SAS initialized. Ready to establish a secure connection with ECDH key exchange, DTLS fingerprint verification, and SAS authentication to prevent MITM attacks.", "system");
|
||||
const handleBeforeUnload = (event) => {
|
||||
if (event.type === "beforeunload" && !isTabSwitching) {
|
||||
if (webrtcManagerRef.current && webrtcManagerRef.current.isConnected()) {
|
||||
@@ -3467,18 +3467,18 @@ var EnhancedSecureP2PChat = () => {
|
||||
}
|
||||
try {
|
||||
const baseText = messageInput.trim();
|
||||
const outText = codeMode2 ? "```\n" + baseText + "\n```" : baseText;
|
||||
const outText = codeMode ? "```\n" + baseText + "\n```" : baseText;
|
||||
const mid = `m_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
|
||||
const meta = { mid };
|
||||
if (viewOnceMode2) meta.once = true;
|
||||
if (disappearTtl2 > 0) meta.ttl = disappearTtl2;
|
||||
if (viewOnceMode) meta.once = true;
|
||||
if (disappearTtl > 0) meta.ttl = disappearTtl;
|
||||
const localOpts = { mid };
|
||||
if (disappearTtl2 > 0) localOpts.expiresAt = Date.now() + disappearTtl2 * 1e3;
|
||||
if (disappearTtl > 0) localOpts.expiresAt = Date.now() + disappearTtl * 1e3;
|
||||
addMessageWithAutoScroll(outText, "sent", localOpts);
|
||||
await webrtcManagerRef.current.sendMessage(outText, meta);
|
||||
setMessageInput("");
|
||||
if (codeMode2) setCodeMode2(false);
|
||||
if (viewOnceMode2) setViewOnceMode2(false);
|
||||
if (codeMode) setCodeMode(false);
|
||||
if (viewOnceMode) setViewOnceMode(false);
|
||||
} catch (error) {
|
||||
const msg = String(error?.message || error);
|
||||
if (!/queued for sending|Data channel not ready/i.test(msg)) {
|
||||
@@ -3782,7 +3782,18 @@ var EnhancedSecureP2PChat = () => {
|
||||
scrollToBottom,
|
||||
webrtcManager: webrtcManagerRef.current,
|
||||
pendingIncomingFiles,
|
||||
onIncomingDecision: handleIncomingDecision
|
||||
onIncomingDecision: handleIncomingDecision,
|
||||
// Secure chat extras
|
||||
codeMode,
|
||||
setCodeMode,
|
||||
viewOnceMode,
|
||||
setViewOnceMode,
|
||||
disappearTtl,
|
||||
setDisappearTtl,
|
||||
nowTick,
|
||||
onUnsendMessage: handleUnsendMessage,
|
||||
onMessageExpire: handleMessageExpire,
|
||||
onPanicWipe: handlePanicWipe
|
||||
});
|
||||
})() : React.createElement(EnhancedConnectionSetup, {
|
||||
onCreateOffer: handleCreateOffer,
|
||||
@@ -3826,18 +3837,7 @@ var EnhancedSecureP2PChat = () => {
|
||||
handleCreateOffer,
|
||||
relayOnlyMode,
|
||||
setRelayOnlyMode,
|
||||
webrtcManagerRef,
|
||||
// Secure chat extras
|
||||
codeMode: codeMode2,
|
||||
setCodeMode: setCodeMode2,
|
||||
viewOnceMode: viewOnceMode2,
|
||||
setViewOnceMode: setViewOnceMode2,
|
||||
disappearTtl: disappearTtl2,
|
||||
setDisappearTtl: setDisappearTtl2,
|
||||
nowTick: nowTick2,
|
||||
onUnsendMessage: handleUnsendMessage,
|
||||
onMessageExpire: handleMessageExpire,
|
||||
onPanicWipe: handlePanicWipe
|
||||
webrtcManagerRef
|
||||
})
|
||||
),
|
||||
// QR Scanner Modal
|
||||
|
||||
Vendored
+3
-3
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"version": 3,
|
||||
"sources": ["../src/utils/debugWindowHooks.js", "../src/network/iceSettingsStore.js", "../src/app.jsx"],
|
||||
"sourcesContent": ["function isSecureBitDebugEnabled(targetWindow = globalThis.window) {\n return targetWindow?.SECUREBIT_DEBUG === true;\n}\n\nfunction installDebugWindowHooks({\n targetWindow = globalThis.window,\n webrtcManagerRef,\n onClearData,\n clearConsole = () => {\n if (typeof console.clear === 'function') {\n console.clear();\n }\n }\n}) {\n if (!isSecureBitDebugEnabled(targetWindow)) {\n return () => {};\n }\n\n targetWindow.forceCleanup = () => {\n onClearData();\n if (webrtcManagerRef.current) {\n webrtcManagerRef.current.disconnect();\n }\n };\n targetWindow.clearLogs = clearConsole;\n targetWindow.webrtcManagerRef = webrtcManagerRef;\n\n return () => {\n delete targetWindow.forceCleanup;\n delete targetWindow.clearLogs;\n delete targetWindow.webrtcManagerRef;\n };\n}\n\nexport { installDebugWindowHooks, isSecureBitDebugEnabled };\n", "// Persistent, at-rest-encrypted storage for the user's custom ICE (STUN/TURN)\n// configuration. Persistence is OPTIONAL: the UI only calls saveIceSettings when\n// the user explicitly opts in (\"Save on this device\"). Session-only use never\n// touches this store \u2014 the settings live in React state and vanish on reload.\n//\n// At-rest protection model:\n// - A non-extractable AES-GCM device key is generated once and kept in\n// IndexedDB. It can never be exported back into JS, so a copy of the\n// on-disk database is useless without executing code in this exact origin.\n// - The settings blob (which may contain TURN credentials) is encrypted with\n// that key before being written.\n// This protects against disk/profile inspection. It does NOT protect against a\n// live code-execution compromise of the page (consistent with the project's\n// stated threat model \u2014 see SECURITY.md). Credentials are never persisted in\n// plaintext, and the user can delete them at any time via clearIceSettings().\n\nconst DB_NAME = 'securebit-net';\nconst DB_VERSION = 1;\nconst STORE = 'kv';\nconst KEY_RECORD = 'ice-device-key';\nconst SETTINGS_RECORD = 'ice-settings';\nconst SETTINGS_VERSION = 1;\n\nfunction isSupported() {\n return typeof indexedDB !== 'undefined' &&\n typeof crypto !== 'undefined' &&\n !!crypto.subtle;\n}\n\nfunction openDb() {\n return new Promise((resolve, reject) => {\n let request;\n try {\n request = indexedDB.open(DB_NAME, DB_VERSION);\n } catch (error) {\n reject(error);\n return;\n }\n request.onupgradeneeded = () => {\n const db = request.result;\n if (!db.objectStoreNames.contains(STORE)) {\n db.createObjectStore(STORE);\n }\n };\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error);\n });\n}\n\nfunction idbGet(db, key) {\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE, 'readonly');\n const req = tx.objectStore(STORE).get(key);\n req.onsuccess = () => resolve(req.result);\n req.onerror = () => reject(req.error);\n });\n}\n\nfunction idbPut(db, key, value) {\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE, 'readwrite');\n tx.objectStore(STORE).put(value, key);\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n });\n}\n\nfunction idbDelete(db, key) {\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE, 'readwrite');\n tx.objectStore(STORE).delete(key);\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n });\n}\n\nasync function getOrCreateDeviceKey(db) {\n const existing = await idbGet(db, KEY_RECORD);\n if (existing instanceof CryptoKey) {\n return existing;\n }\n const key = await crypto.subtle.generateKey(\n { name: 'AES-GCM', length: 256 },\n false, // non-extractable\n ['encrypt', 'decrypt']\n );\n await idbPut(db, KEY_RECORD, key);\n return key;\n}\n\n/**\n * Persist custom ICE settings, encrypted at rest.\n * @param {{ servers: Array, privacyMode: string }} settings\n */\nexport async function saveIceSettings(settings) {\n if (!isSupported()) throw new Error('Persistent storage is not available in this browser');\n\n const db = await openDb();\n const key = await getOrCreateDeviceKey(db);\n\n const payload = JSON.stringify({\n version: SETTINGS_VERSION,\n servers: Array.isArray(settings?.servers) ? settings.servers : [],\n privacyMode: settings?.privacyMode === 'relay-only' ? 'relay-only' : 'standard'\n });\n\n const iv = crypto.getRandomValues(new Uint8Array(12));\n const ciphertext = await crypto.subtle.encrypt(\n { name: 'AES-GCM', iv },\n keLine truncated
|
||||
"mappings": "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 truncated
|
||||
"names": ["codeMode", "setCodeMode", "viewOnceMode", "setViewOnceMode", "disappearTtl", "setDisappearTtl", "onPanicWipe", "nowTick", "onUnsendMessage", "onMessageExpire", "offerData", "payload", "UpdateCheckerWrapper"]
|
||||
"sourcesContent": ["function isSecureBitDebugEnabled(targetWindow = globalThis.window) {\n return targetWindow?.SECUREBIT_DEBUG === true;\n}\n\nfunction installDebugWindowHooks({\n targetWindow = globalThis.window,\n webrtcManagerRef,\n onClearData,\n clearConsole = () => {\n if (typeof console.clear === 'function') {\n console.clear();\n }\n }\n}) {\n if (!isSecureBitDebugEnabled(targetWindow)) {\n return () => {};\n }\n\n targetWindow.forceCleanup = () => {\n onClearData();\n if (webrtcManagerRef.current) {\n webrtcManagerRef.current.disconnect();\n }\n };\n targetWindow.clearLogs = clearConsole;\n targetWindow.webrtcManagerRef = webrtcManagerRef;\n\n return () => {\n delete targetWindow.forceCleanup;\n delete targetWindow.clearLogs;\n delete targetWindow.webrtcManagerRef;\n };\n}\n\nexport { installDebugWindowHooks, isSecureBitDebugEnabled };\n", "// Persistent, at-rest-encrypted storage for the user's custom ICE (STUN/TURN)\n// configuration. Persistence is OPTIONAL: the UI only calls saveIceSettings when\n// the user explicitly opts in (\"Save on this device\"). Session-only use never\n// touches this store \u2014 the settings live in React state and vanish on reload.\n//\n// At-rest protection model:\n// - A non-extractable AES-GCM device key is generated once and kept in\n// IndexedDB. It can never be exported back into JS, so a copy of the\n// on-disk database is useless without executing code in this exact origin.\n// - The settings blob (which may contain TURN credentials) is encrypted with\n// that key before being written.\n// This protects against disk/profile inspection. It does NOT protect against a\n// live code-execution compromise of the page (consistent with the project's\n// stated threat model \u2014 see SECURITY.md). Credentials are never persisted in\n// plaintext, and the user can delete them at any time via clearIceSettings().\n\nconst DB_NAME = 'securebit-net';\nconst DB_VERSION = 1;\nconst STORE = 'kv';\nconst KEY_RECORD = 'ice-device-key';\nconst SETTINGS_RECORD = 'ice-settings';\nconst SETTINGS_VERSION = 1;\n\nfunction isSupported() {\n return typeof indexedDB !== 'undefined' &&\n typeof crypto !== 'undefined' &&\n !!crypto.subtle;\n}\n\nfunction openDb() {\n return new Promise((resolve, reject) => {\n let request;\n try {\n request = indexedDB.open(DB_NAME, DB_VERSION);\n } catch (error) {\n reject(error);\n return;\n }\n request.onupgradeneeded = () => {\n const db = request.result;\n if (!db.objectStoreNames.contains(STORE)) {\n db.createObjectStore(STORE);\n }\n };\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error);\n });\n}\n\nfunction idbGet(db, key) {\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE, 'readonly');\n const req = tx.objectStore(STORE).get(key);\n req.onsuccess = () => resolve(req.result);\n req.onerror = () => reject(req.error);\n });\n}\n\nfunction idbPut(db, key, value) {\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE, 'readwrite');\n tx.objectStore(STORE).put(value, key);\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n });\n}\n\nfunction idbDelete(db, key) {\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE, 'readwrite');\n tx.objectStore(STORE).delete(key);\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n });\n}\n\nasync function getOrCreateDeviceKey(db) {\n const existing = await idbGet(db, KEY_RECORD);\n if (existing instanceof CryptoKey) {\n return existing;\n }\n const key = await crypto.subtle.generateKey(\n { name: 'AES-GCM', length: 256 },\n false, // non-extractable\n ['encrypt', 'decrypt']\n );\n await idbPut(db, KEY_RECORD, key);\n return key;\n}\n\n/**\n * Persist custom ICE settings, encrypted at rest.\n * @param {{ servers: Array, privacyMode: string }} settings\n */\nexport async function saveIceSettings(settings) {\n if (!isSupported()) throw new Error('Persistent storage is not available in this browser');\n\n const db = await openDb();\n const key = await getOrCreateDeviceKey(db);\n\n const payload = JSON.stringify({\n version: SETTINGS_VERSION,\n servers: Array.isArray(settings?.servers) ? settings.servers : [],\n privacyMode: settings?.privacyMode === 'relay-only' ? 'relay-only' : 'standard'\n });\n\n const iv = crypto.getRandomValues(new Uint8Array(12));\n const ciphertext = await crypto.subtle.encrypt(\n { name: 'AES-GCM', iv },\n keLine truncated
|
||||
"mappings": "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 truncated
|
||||
"names": ["offerData", "payload", "UpdateCheckerWrapper"]
|
||||
}
|
||||
+5
-5
@@ -113,7 +113,7 @@
|
||||
|
||||
|
||||
<!-- GitHub Pages SEO -->
|
||||
<meta name="description" content="SecureBit.chat v4.8.14 — P2P messenger with ECDH + DTLS + SAS security and 18-layer military-grade cryptography">
|
||||
<meta name="description" content="SecureBit.chat v4.8.15 — P2P messenger with ECDH + DTLS + SAS security and 18-layer military-grade cryptography">
|
||||
<meta name="keywords" content="P2P messenger, ECDH, DTLS, SAS, encryption, WebRTC, privacy, ASN.1 validation, military-grade security, 18-layer defense, MITM protection, PFS">
|
||||
<meta name="author" content="Volodymyr">
|
||||
<link rel="canonical" href="https://github.com/SecureBitChat/securebit-chat/">
|
||||
@@ -148,13 +148,13 @@
|
||||
<!-- Update Manager - система принудительного обновления -->
|
||||
<script src="src/utils/updateManager.js"></script>
|
||||
<script type="module" src="src/components/UpdateChecker.jsx"></script>
|
||||
<script type="module" src="dist/qr-local.js?v=1781829306093"></script>
|
||||
<script type="module" src="src/components/QRScanner.js?v=1781829306093"></script>
|
||||
<script type="module" src="dist/qr-local.js?v=1781831678894"></script>
|
||||
<script type="module" src="src/components/QRScanner.js?v=1781831678894"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="dist/app-boot.js?v=1781829306093"></script>
|
||||
<script type="module" src="dist/app.js?v=1781829306093"></script>
|
||||
<script type="module" src="dist/app-boot.js?v=1781831678894"></script>
|
||||
<script type="module" src="dist/app.js?v=1781831678894"></script>
|
||||
|
||||
<script src="src/scripts/pwa-register.js"></script>
|
||||
<script src="./src/pwa/install-prompt.js" type="module"></script>
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "SecureBit.chat v4.8.14 - ECDH + DTLS + SAS",
|
||||
"name": "SecureBit.chat v4.8.15 - ECDH + DTLS + SAS",
|
||||
"short_name": "SecureBit",
|
||||
"description": "P2P messenger with ECDH + DTLS + SAS security, military-grade cryptography and Lightning Network payments",
|
||||
"start_url": "./",
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"version": "1781829306093",
|
||||
"buildVersion": "1781829306093",
|
||||
"appVersion": "4.8.14",
|
||||
"buildTime": "2026-06-19T00:35:06.138Z",
|
||||
"buildId": "1781829306093-cf36656",
|
||||
"gitHash": "cf36656",
|
||||
"version": "1781831678894",
|
||||
"buildVersion": "1781831678894",
|
||||
"appVersion": "4.8.15",
|
||||
"buildTime": "2026-06-19T01:14:38.934Z",
|
||||
"buildId": "1781831678894-15173a9",
|
||||
"gitHash": "15173a9",
|
||||
"generated": true,
|
||||
"generatedAt": "2026-06-19T00:35:06.139Z"
|
||||
"generatedAt": "2026-06-19T01:14:38.935Z"
|
||||
}
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "securebit-chat",
|
||||
"version": "4.8.14",
|
||||
"version": "4.8.15",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "securebit-chat",
|
||||
"version": "4.8.14",
|
||||
"version": "4.8.15",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"base64-js": "1.5.1",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "securebit-chat",
|
||||
"version": "4.8.14",
|
||||
"version": "4.8.15",
|
||||
"description": "Secure P2P Communication Application with End-to-End Encryption",
|
||||
"main": "index.html",
|
||||
"scripts": {
|
||||
|
||||
+27
-27
@@ -594,18 +594,7 @@ import { loadIceSettings, saveIceSettings, clearIceSettings } from './network/ic
|
||||
handleCreateOffer,
|
||||
relayOnlyMode,
|
||||
setRelayOnlyMode,
|
||||
webrtcManagerRef,
|
||||
// Secure chat extras
|
||||
codeMode,
|
||||
setCodeMode,
|
||||
viewOnceMode,
|
||||
setViewOnceMode,
|
||||
disappearTtl,
|
||||
setDisappearTtl,
|
||||
nowTick,
|
||||
onUnsendMessage,
|
||||
onMessageExpire,
|
||||
onPanicWipe
|
||||
webrtcManagerRef
|
||||
}) => {
|
||||
const [mode, setMode] = React.useState('select');
|
||||
const [notificationPermissionRequested, setNotificationPermissionRequested] = React.useState(false);
|
||||
@@ -1503,7 +1492,18 @@ import { loadIceSettings, saveIceSettings, clearIceSettings } from './network/ic
|
||||
scrollToBottom,
|
||||
webrtcManager,
|
||||
pendingIncomingFiles = [],
|
||||
onIncomingDecision
|
||||
onIncomingDecision,
|
||||
// Secure chat extras
|
||||
codeMode,
|
||||
setCodeMode,
|
||||
viewOnceMode,
|
||||
setViewOnceMode,
|
||||
disappearTtl,
|
||||
setDisappearTtl,
|
||||
nowTick,
|
||||
onUnsendMessage,
|
||||
onMessageExpire,
|
||||
onPanicWipe
|
||||
}) => {
|
||||
const [showScrollButton, setShowScrollButton] = React.useState(false);
|
||||
const [showFileTransfer, setShowFileTransfer] = React.useState(false);
|
||||
@@ -2388,7 +2388,7 @@ import { loadIceSettings, saveIceSettings, clearIceSettings } from './network/ic
|
||||
}
|
||||
}
|
||||
|
||||
handleMessage(' SecureBit.chat Enhanced Security Edition v4.8.14 - ECDH + DTLS + SAS initialized. Ready to establish a secure connection with ECDH key exchange, DTLS fingerprint verification, and SAS authentication to prevent MITM attacks.', 'system');
|
||||
handleMessage(' SecureBit.chat Enhanced Security Edition v4.8.15 - ECDH + DTLS + SAS initialized. Ready to establish a secure connection with ECDH key exchange, DTLS fingerprint verification, and SAS authentication to prevent MITM attacks.', 'system');
|
||||
|
||||
const handleBeforeUnload = (event) => {
|
||||
if (event.type === 'beforeunload' && !isTabSwitching) {
|
||||
@@ -4171,7 +4171,18 @@ import { loadIceSettings, saveIceSettings, clearIceSettings } from './network/ic
|
||||
scrollToBottom: scrollToBottom,
|
||||
webrtcManager: webrtcManagerRef.current,
|
||||
pendingIncomingFiles: pendingIncomingFiles,
|
||||
onIncomingDecision: handleIncomingDecision
|
||||
onIncomingDecision: handleIncomingDecision,
|
||||
// Secure chat extras
|
||||
codeMode: codeMode,
|
||||
setCodeMode: setCodeMode,
|
||||
viewOnceMode: viewOnceMode,
|
||||
setViewOnceMode: setViewOnceMode,
|
||||
disappearTtl: disappearTtl,
|
||||
setDisappearTtl: setDisappearTtl,
|
||||
nowTick: nowTick,
|
||||
onUnsendMessage: handleUnsendMessage,
|
||||
onMessageExpire: handleMessageExpire,
|
||||
onPanicWipe: handlePanicWipe
|
||||
});
|
||||
})()
|
||||
: React.createElement(EnhancedConnectionSetup, {
|
||||
@@ -4216,18 +4227,7 @@ import { loadIceSettings, saveIceSettings, clearIceSettings } from './network/ic
|
||||
handleCreateOffer: handleCreateOffer,
|
||||
relayOnlyMode: relayOnlyMode,
|
||||
setRelayOnlyMode: setRelayOnlyMode,
|
||||
webrtcManagerRef: webrtcManagerRef,
|
||||
// Secure chat extras
|
||||
codeMode: codeMode,
|
||||
setCodeMode: setCodeMode,
|
||||
viewOnceMode: viewOnceMode,
|
||||
setViewOnceMode: setViewOnceMode,
|
||||
disappearTtl: disappearTtl,
|
||||
setDisappearTtl: setDisappearTtl,
|
||||
nowTick: nowTick,
|
||||
onUnsendMessage: handleUnsendMessage,
|
||||
onMessageExpire: handleMessageExpire,
|
||||
onPanicWipe: handlePanicWipe
|
||||
webrtcManagerRef: webrtcManagerRef
|
||||
})
|
||||
),
|
||||
|
||||
|
||||
@@ -539,7 +539,7 @@ const EnhancedMinimalHeader = ({
|
||||
React.createElement('p', {
|
||||
key: 'subtitle',
|
||||
className: 'text-xs sm:text-sm text-muted hidden sm:block'
|
||||
}, 'End-to-end freedom v4.8.14')
|
||||
}, 'End-to-end freedom v4.8.15')
|
||||
])
|
||||
]),
|
||||
|
||||
|
||||
Reference in new issue
Block a user