From 5b557102b4e886620dd2b32f7a5c947884b7c28a Mon Sep 17 00:00:00 2001 From: lockbitchat Date: Tue, 7 Oct 2025 23:58:54 -0400 Subject: [PATCH] Fix QR scanner multi-chunk processing and binary data handling - Fix duplicate chunk detection by using data hash instead of index - Add comprehensive logging for QR scanner debugging - Implement proper buffer cleanup when scanner is closed - Preserve original binary data instead of decoding to JSON - Add deduplication logic to prevent same QR code being processed multiple times - Improve error handling and scanner state management - Fix binary chunk reconstruction to maintain SB1:bin: prefix format --- assets/tailwind.css | 2 +- dist/app.js | 364 +++++++++++++++++++++++++++++++-- dist/app.js.map | 6 +- src/app.jsx | 479 ++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 789 insertions(+), 62 deletions(-) diff --git a/assets/tailwind.css b/assets/tailwind.css index 1310fa5..347aa60 100644 --- a/assets/tailwind.css +++ b/assets/tailwind.css @@ -1 +1 @@ -*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }/*! tailwindcss v3.4.17 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.-right-2{right:-.5rem}.-top-2{top:-.5rem}.bottom-0{bottom:0}.bottom-2{bottom:.5rem}.bottom-4{bottom:1rem}.bottom-6{bottom:1.5rem}.left-0{left:0}.left-1\/2{left:50%}.left-4{left:1rem}.right-0{right:0}.right-3{right:.75rem}.right-4{right:1rem}.right-6{right:1.5rem}.top-0{top:0}.top-1\/2{top:50%}.top-4{top:1rem}.z-10{z-index:10}.z-20{z-index:20}.z-40{z-index:40}.z-50{z-index:50}.mx-4{margin-left:1rem;margin-right:1rem}.mx-auto{margin-left:auto;margin-right:auto}.mb-1{margin-bottom:.25rem}.mb-12{margin-bottom:3rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-5{margin-bottom:1.25rem}.mb-6{margin-bottom:1.5rem}.mb-8{margin-bottom:2rem}.ml-2{margin-left:.5rem}.ml-6{margin-left:1.5rem}.ml-auto{margin-left:auto}.mr-1{margin-right:.25rem}.mr-2{margin-right:.5rem}.mr-3{margin-right:.75rem}.mr-4{margin-right:1rem}.mr-auto{margin-right:auto}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-12{margin-top:3rem}.mt-16{margin-top:4rem}.mt-2{margin-top:.5rem}.mt-20{margin-top:5rem}.mt-4{margin-top:1rem}.mt-6{margin-top:1.5rem}.mt-8{margin-top:2rem}.block{display:block}.inline{display:inline}.flex{display:flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-1{height:.25rem}.h-10{height:2.5rem}.h-12{height:3rem}.h-16{height:4rem}.h-2{height:.5rem}.h-28{height:7rem}.h-4{height:1rem}.h-6{height:1.5rem}.h-8{height:2rem}.h-80{height:20rem}.h-\[420px\]{height:420px}.h-auto{height:auto}.h-full{height:100%}.h-px{height:1px}.max-h-\[80vh\]{max-height:80vh}.min-h-\[72px\]{min-height:72px}.min-h-\[calc\(100vh-104px\)\]{min-height:calc(100vh - 104px)}.min-h-screen{min-height:100vh}.w-10{width:2.5rem}.w-12{width:3rem}.w-16{width:4rem}.w-2{width:.5rem}.w-28{width:7rem}.w-4{width:1rem}.w-6{width:1.5rem}.w-72{width:18rem}.w-8{width:2rem}.w-\[20rem\]{width:20rem}.w-full{width:100%}.min-w-\[160px\]{min-width:160px}.min-w-\[240px\]{min-width:240px}.max-w-2xl{max-width:42rem}.max-w-3xl{max-width:48rem}.max-w-4xl{max-width:56rem}.max-w-5xl{max-width:64rem}.max-w-6xl{max-width:72rem}.max-w-7xl{max-width:80rem}.max-w-lg{max-width:32rem}.max-w-md{max-width:28rem}.max-w-none{max-width:none}.max-w-sm{max-width:24rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.border-collapse{border-collapse:collapse}.-translate-x-1\/2{--tw-translate-x:-50%}.-translate-x-1\/2,.-translate-y-1\/2{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-1\/2{--tw-translate-y:-50%}.translate-x-full{--tw-translate-x:100%}.translate-x-full,.translate-y-full{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-full{--tw-translate-y:100%}.rotate-180{--tw-rotate:180deg}.rotate-180,.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}@keyframes spin{to{transform:rotate(1turn)}}.animate-spin{animation:spin 1s linear infinite}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.resize-none{resize:none}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-center{align-items:center}.items-stretch{align-items:stretch}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-12{gap:3rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-6{gap:1.5rem}.space-x-1>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.25rem*var(--tw-space-x-reverse));margin-left:calc(.25rem*(1 - var(--tw-space-x-reverse)))}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.5rem*var(--tw-space-x-reverse));margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)))}.space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.75rem*var(--tw-space-x-reverse));margin-left:calc(.75rem*(1 - var(--tw-space-x-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1rem*var(--tw-space-x-reverse));margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem*var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem*var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem*var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem*var(--tw-space-y-reverse))}.space-y-8>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(2rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2rem*var(--tw-space-y-reverse))}.self-center{align-self:center}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.scroll-smooth{scroll-behavior:smooth}.break-words{overflow-wrap:break-word}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:1rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-t{border-top-width:1px}.border-blue-500\/20{border-color:rgba(59,130,246,.2)}.border-gray-500\/10{border-color:hsla(220,9%,46%,.1)}.border-gray-500\/20{border-color:hsla(220,9%,46%,.2)}.border-gray-600{--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity,1))}.border-gray-600\/30{border-color:rgba(75,85,99,.3)}.border-gray-700\/30{border-color:rgba(55,65,81,.3)}.border-green-500\/20{border-color:rgba(34,197,94,.2)}.border-green-500\/30{border-color:rgba(34,197,94,.3)}.border-orange-500\/20{border-color:rgba(249,115,22,.2)}.border-purple-500\/20{border-color:rgba(168,85,247,.2)}.border-red-500\/20{border-color:rgba(239,68,68,.2)}.border-yellow-500\/20{border-color:rgba(234,179,8,.2)}.bg-\[rgb\(20_20_20_\/50\%\)\]{background-color:hsla(0,0%,8%,.5)}.bg-black\/30{background-color:rgba(0,0,0,.3)}.bg-black\/50{background-color:rgba(0,0,0,.5)}.bg-black\/80{background-color:rgba(0,0,0,.8)}.bg-blue-400{--tw-bg-opacity:1;background-color:rgb(96 165 250/var(--tw-bg-opacity,1))}.bg-blue-500{--tw-bg-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity,1))}.bg-blue-500\/10{background-color:rgba(59,130,246,.1)}.bg-blue-500\/20{background-color:rgba(59,130,246,.2)}.bg-blue-500\/90{background-color:rgba(59,130,246,.9)}.bg-blue-600{--tw-bg-opacity:1;background-color:rgb(37 99 235/var(--tw-bg-opacity,1))}.bg-emerald-500{--tw-bg-opacity:1;background-color:rgb(16 185 129/var(--tw-bg-opacity,1))}.bg-gray-500\/10{background-color:hsla(220,9%,46%,.1)}.bg-gray-500\/20{background-color:hsla(220,9%,46%,.2)}.bg-gray-600{--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity,1))}.bg-gray-600\/20{background-color:rgba(75,85,99,.2)}.bg-gray-700{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity,1))}.bg-gray-700\/50{background-color:rgba(55,65,81,.5)}.bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity,1))}.bg-gray-800\/50{background-color:rgba(31,41,55,.5)}.bg-gray-800\/95{background-color:rgba(31,41,55,.95)}.bg-gray-900\/30{background-color:rgba(17,24,39,.3)}.bg-green-200{--tw-bg-opacity:1;background-color:rgb(187 247 208/var(--tw-bg-opacity,1))}.bg-green-400{--tw-bg-opacity:1;background-color:rgb(74 222 128/var(--tw-bg-opacity,1))}.bg-green-400\/20{background-color:rgba(74,222,128,.2)}.bg-green-500{--tw-bg-opacity:1;background-color:rgb(34 197 94/var(--tw-bg-opacity,1))}.bg-green-500\/10{background-color:rgba(34,197,94,.1)}.bg-green-500\/20{background-color:rgba(34,197,94,.2)}.bg-green-500\/90{background-color:rgba(34,197,94,.9)}.bg-green-600\/20{background-color:rgba(22,163,74,.2)}.bg-neutral-900{--tw-bg-opacity:1;background-color:rgb(23 23 23/var(--tw-bg-opacity,1))}.bg-orange-400{--tw-bg-opacity:1;background-color:rgb(251 146 60/var(--tw-bg-opacity,1))}.bg-orange-500{--tw-bg-opacity:1;background-color:rgb(249 115 22/var(--tw-bg-opacity,1))}.bg-orange-500\/10{background-color:rgba(249,115,22,.1)}.bg-orange-500\/15{background-color:rgba(249,115,22,.15)}.bg-orange-500\/20{background-color:rgba(249,115,22,.2)}.bg-purple-500\/10{background-color:rgba(168,85,247,.1)}.bg-purple-600{--tw-bg-opacity:1;background-color:rgb(147 51 234/var(--tw-bg-opacity,1))}.bg-red-200{--tw-bg-opacity:1;background-color:rgb(254 202 202/var(--tw-bg-opacity,1))}.bg-red-400{--tw-bg-opacity:1;background-color:rgb(248 113 113/var(--tw-bg-opacity,1))}.bg-red-500{--tw-bg-opacity:1;background-color:rgb(239 68 68/var(--tw-bg-opacity,1))}.bg-red-500\/10{background-color:rgba(239,68,68,.1)}.bg-red-500\/20{background-color:rgba(239,68,68,.2)}.bg-red-500\/90{background-color:rgba(239,68,68,.9)}.bg-red-900\/50{background-color:rgba(127,29,29,.5)}.bg-transparent{background-color:transparent}.bg-white\/20{background-color:hsla(0,0%,100%,.2)}.bg-yellow-400{--tw-bg-opacity:1;background-color:rgb(250 204 21/var(--tw-bg-opacity,1))}.bg-yellow-500{--tw-bg-opacity:1;background-color:rgb(234 179 8/var(--tw-bg-opacity,1))}.bg-yellow-500\/10{background-color:rgba(234,179,8,.1)}.bg-yellow-500\/20{background-color:rgba(234,179,8,.2)}.bg-yellow-500\/90{background-color:rgba(234,179,8,.9)}.bg-gradient-to-b{background-image:linear-gradient(to bottom,var(--tw-gradient-stops))}.bg-gradient-to-r{background-image:linear-gradient(to right,var(--tw-gradient-stops))}.bg-gradient-to-t{background-image:linear-gradient(to top,var(--tw-gradient-stops))}.from-\[\#1f1f1f\]\/90{--tw-gradient-from:rgba(31,31,31,.9) var(--tw-gradient-from-position);--tw-gradient-to:rgba(31,31,31,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-gray-800\/20{--tw-gradient-from:rgba(31,41,55,.2) var(--tw-gradient-from-position);--tw-gradient-to:rgba(31,41,55,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-orange-500{--tw-gradient-from:#f97316 var(--tw-gradient-from-position);--tw-gradient-to:rgba(249,115,22,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-transparent{--tw-gradient-from:transparent var(--tw-gradient-from-position);--tw-gradient-to:transparent var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.via-zinc-700{--tw-gradient-to:rgba(63,63,70,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),#3f3f46 var(--tw-gradient-via-position),var(--tw-gradient-to)}.to-gray-900\/20{--tw-gradient-to:rgba(17,24,39,.2) var(--tw-gradient-to-position)}.to-orange-600{--tw-gradient-to:#ea580c var(--tw-gradient-to-position)}.to-transparent{--tw-gradient-to:transparent var(--tw-gradient-to-position)}.fill-blue-500{fill:#3b82f6}.fill-white{fill:#fff}.p-1\.5{padding:.375rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.p-8{padding:2rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-14{padding-top:3.5rem;padding-bottom:3.5rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.pr-2{padding-right:.5rem}.pt-6{padding-top:1.5rem}.text-left{text-align:left}.text-center{text-align:center}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-\[3rem\]{font-size:3rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.lowercase{text-transform:lowercase}.leading-relaxed{line-height:1.625}.leading-snug{line-height:1.375}.leading-tight{line-height:1.25}.text-black{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity,1))}.text-blue-300{--tw-text-opacity:1;color:rgb(147 197 253/var(--tw-text-opacity,1))}.text-blue-400{--tw-text-opacity:1;color:rgb(96 165 250/var(--tw-text-opacity,1))}.text-blue-500{--tw-text-opacity:1;color:rgb(59 130 246/var(--tw-text-opacity,1))}.text-blue-600{--tw-text-opacity:1;color:rgb(37 99 235/var(--tw-text-opacity,1))}.text-cyan-300{--tw-text-opacity:1;color:rgb(103 232 249/var(--tw-text-opacity,1))}.text-cyan-400{--tw-text-opacity:1;color:rgb(34 211 238/var(--tw-text-opacity,1))}.text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity,1))}.text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity,1))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity,1))}.text-green-200{--tw-text-opacity:1;color:rgb(187 247 208/var(--tw-text-opacity,1))}.text-green-300{--tw-text-opacity:1;color:rgb(134 239 172/var(--tw-text-opacity,1))}.text-green-400{--tw-text-opacity:1;color:rgb(74 222 128/var(--tw-text-opacity,1))}.text-green-500{--tw-text-opacity:1;color:rgb(34 197 94/var(--tw-text-opacity,1))}.text-orange-200{--tw-text-opacity:1;color:rgb(254 215 170/var(--tw-text-opacity,1))}.text-orange-300{--tw-text-opacity:1;color:rgb(253 186 116/var(--tw-text-opacity,1))}.text-orange-400{--tw-text-opacity:1;color:rgb(251 146 60/var(--tw-text-opacity,1))}.text-orange-500{--tw-text-opacity:1;color:rgb(249 115 22/var(--tw-text-opacity,1))}.text-purple-400{--tw-text-opacity:1;color:rgb(192 132 252/var(--tw-text-opacity,1))}.text-purple-500{--tw-text-opacity:1;color:rgb(168 85 247/var(--tw-text-opacity,1))}.text-red-200{--tw-text-opacity:1;color:rgb(254 202 202/var(--tw-text-opacity,1))}.text-red-300{--tw-text-opacity:1;color:rgb(252 165 165/var(--tw-text-opacity,1))}.text-red-400{--tw-text-opacity:1;color:rgb(248 113 113/var(--tw-text-opacity,1))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.text-white\/10{color:hsla(0,0%,100%,.1)}.text-yellow-200{--tw-text-opacity:1;color:rgb(254 240 138/var(--tw-text-opacity,1))}.text-yellow-300{--tw-text-opacity:1;color:rgb(253 224 71/var(--tw-text-opacity,1))}.text-yellow-400{--tw-text-opacity:1;color:rgb(250 204 21/var(--tw-text-opacity,1))}.text-yellow-600{--tw-text-opacity:1;color:rgb(202 138 4/var(--tw-text-opacity,1))}.text-zinc-600{--tw-text-opacity:1;color:rgb(82 82 91/var(--tw-text-opacity,1))}.placeholder-gray-500::-moz-placeholder{--tw-placeholder-opacity:1;color:rgb(107 114 128/var(--tw-placeholder-opacity,1))}.placeholder-gray-500::placeholder{--tw-placeholder-opacity:1;color:rgb(107 114 128/var(--tw-placeholder-opacity,1))}.opacity-0{opacity:0}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-70{opacity:.7}.opacity-90{opacity:.9}.shadow-2xl{--tw-shadow:0 25px 50px -12px rgba(0,0,0,.25);--tw-shadow-colored:0 25px 50px -12px var(--tw-shadow-color)}.shadow-2xl,.shadow-lg{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-md{--tw-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -2px rgba(0,0,0,.1);--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.ring-2{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.blur{--tw-blur:blur(8px)}.blur,.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-md{--tw-backdrop-blur:blur(12px)}.backdrop-blur-md,.backdrop-blur-sm{-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.backdrop-blur-sm{--tw-backdrop-blur:blur(4px)}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}.duration-500{transition-duration:.5s}.\[checksum\:4\]{checksum:4}.\[data\:variable\]{data:variable}.\[name\:4\]{name:4}.\[size\:4\]{size:4}.hover\:bg-\[rgb\(20_20_20_\/30\%\)\]:hover{background-color:hsla(0,0%,8%,.3)}.hover\:bg-blue-600:hover{--tw-bg-opacity:1;background-color:rgb(37 99 235/var(--tw-bg-opacity,1))}.hover\:bg-blue-700:hover{--tw-bg-opacity:1;background-color:rgb(29 78 216/var(--tw-bg-opacity,1))}.hover\:bg-emerald-600:hover{--tw-bg-opacity:1;background-color:rgb(5 150 105/var(--tw-bg-opacity,1))}.hover\:bg-gray-500:hover{--tw-bg-opacity:1;background-color:rgb(107 114 128/var(--tw-bg-opacity,1))}.hover\:bg-gray-600\/30:hover{background-color:rgba(75,85,99,.3)}.hover\:bg-green-500\/20:hover{background-color:rgba(34,197,94,.2)}.hover\:bg-green-500\/30:hover{background-color:rgba(34,197,94,.3)}.hover\:bg-green-600\/30:hover{background-color:rgba(22,163,74,.3)}.hover\:bg-green-600\/40:hover{background-color:rgba(22,163,74,.4)}.hover\:bg-orange-500\/20:hover{background-color:rgba(249,115,22,.2)}.hover\:bg-orange-500\/40:hover{background-color:rgba(249,115,22,.4)}.hover\:bg-orange-600:hover{--tw-bg-opacity:1;background-color:rgb(234 88 12/var(--tw-bg-opacity,1))}.hover\:bg-purple-500:hover{--tw-bg-opacity:1;background-color:rgb(168 85 247/var(--tw-bg-opacity,1))}.hover\:bg-purple-500\/20:hover{background-color:rgba(168,85,247,.2)}.hover\:bg-red-500\/20:hover{background-color:rgba(239,68,68,.2)}.hover\:bg-red-500\/30:hover{background-color:rgba(239,68,68,.3)}.hover\:bg-red-600:hover{--tw-bg-opacity:1;background-color:rgb(220 38 38/var(--tw-bg-opacity,1))}.hover\:bg-red-600\/40:hover{background-color:rgba(220,38,38,.4)}.hover\:bg-white\/30:hover{background-color:hsla(0,0%,100%,.3)}.hover\:bg-yellow-600\/40:hover{background-color:rgba(202,138,4,.4)}.hover\:from-orange-600:hover{--tw-gradient-from:#ea580c var(--tw-gradient-from-position);--tw-gradient-to:rgba(234,88,12,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.hover\:to-orange-700:hover{--tw-gradient-to:#c2410c var(--tw-gradient-to-position)}.hover\:text-gray-300:hover{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity,1))}.hover\:text-gray-700:hover{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity,1))}.hover\:text-green-300:hover{--tw-text-opacity:1;color:rgb(134 239 172/var(--tw-text-opacity,1))}.hover\:text-red-300:hover{--tw-text-opacity:1;color:rgb(252 165 165/var(--tw-text-opacity,1))}.hover\:text-white:hover{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.hover\:opacity-80:hover{opacity:.8}.focus\:border-green-500\/40:focus{border-color:rgba(34,197,94,.4)}.focus\:border-orange-500\/40:focus{border-color:rgba(249,115,22,.4)}.focus\:border-purple-500\/40:focus{border-color:rgba(168,85,247,.4)}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}.group:hover .group-hover\:scale-105{--tw-scale-x:1.05;--tw-scale-y:1.05}.group:hover .group-hover\:scale-105,.group:hover .group-hover\:scale-110{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.group:hover .group-hover\:scale-110{--tw-scale-x:1.1;--tw-scale-y:1.1}.group:hover .group-hover\:opacity-100{opacity:1}@media (min-width:640px){.sm\:mb-0{margin-bottom:0}.sm\:mb-3{margin-bottom:.75rem}.sm\:mr-2{margin-right:.5rem}.sm\:block{display:block}.sm\:inline{display:inline}.sm\:flex{display:flex}.sm\:h-10{height:2.5rem}.sm\:h-12{height:3rem}.sm\:w-10{width:2.5rem}.sm\:w-12{width:3rem}.sm\:w-\[24rem\]{width:24rem}.sm\:flex-row{flex-direction:row}.sm\:items-center{align-items:center}.sm\:justify-between{justify-content:space-between}.sm\:gap-4{gap:1rem}.sm\:space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.5rem*var(--tw-space-x-reverse));margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)))}.sm\:space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.75rem*var(--tw-space-x-reverse));margin-left:calc(.75rem*(1 - var(--tw-space-x-reverse)))}.sm\:space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1rem*var(--tw-space-x-reverse));margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)))}.sm\:space-y-0>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(0px*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(0px*var(--tw-space-y-reverse))}.sm\:p-4{padding:1rem}.sm\:px-0{padding-left:0;padding-right:0}.sm\:px-3{padding-left:.75rem;padding-right:.75rem}.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}.sm\:py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.sm\:text-3xl{font-size:1.875rem;line-height:2.25rem}.sm\:text-base{font-size:1rem;line-height:1.5rem}.sm\:text-sm{font-size:.875rem;line-height:1.25rem}.sm\:text-xl{font-size:1.25rem;line-height:1.75rem}}@media (min-width:768px){.md\:flex{display:flex}.md\:hidden{display:none}.md\:h-32{height:8rem}.md\:h-\[32rem\]{height:32rem}.md\:w-\[28rem\]{width:28rem}.md\:w-auto{width:auto}.md\:w-px{width:1px}.md\:flex-none{flex:none}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.md\:flex-row{flex-direction:row}.md\:flex-col{flex-direction:column}.md\:bg-gradient-to-b{background-image:linear-gradient(to bottom,var(--tw-gradient-stops))}}@media (min-width:1024px){.lg\:col-span-2{grid-column:span 2/span 2}.lg\:col-span-3{grid-column:span 3/span 3}.lg\:block{display:block}.lg\:w-\[32rem\]{width:32rem}.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}.lg\:px-8{padding-left:2rem;padding-right:2rem}} \ No newline at end of file +*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }/*! tailwindcss v3.4.17 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.-right-2{right:-.5rem}.-top-2{top:-.5rem}.bottom-0{bottom:0}.bottom-2{bottom:.5rem}.bottom-4{bottom:1rem}.bottom-6{bottom:1.5rem}.left-0{left:0}.left-1\/2{left:50%}.left-4{left:1rem}.right-0{right:0}.right-3{right:.75rem}.right-4{right:1rem}.right-6{right:1.5rem}.top-0{top:0}.top-1\/2{top:50%}.top-4{top:1rem}.z-10{z-index:10}.z-20{z-index:20}.z-40{z-index:40}.z-50{z-index:50}.mx-4{margin-left:1rem;margin-right:1rem}.mx-auto{margin-left:auto;margin-right:auto}.mb-1{margin-bottom:.25rem}.mb-12{margin-bottom:3rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-5{margin-bottom:1.25rem}.mb-6{margin-bottom:1.5rem}.mb-8{margin-bottom:2rem}.ml-2{margin-left:.5rem}.ml-6{margin-left:1.5rem}.ml-auto{margin-left:auto}.mr-1{margin-right:.25rem}.mr-2{margin-right:.5rem}.mr-3{margin-right:.75rem}.mr-4{margin-right:1rem}.mr-auto{margin-right:auto}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-12{margin-top:3rem}.mt-16{margin-top:4rem}.mt-2{margin-top:.5rem}.mt-20{margin-top:5rem}.mt-4{margin-top:1rem}.mt-6{margin-top:1.5rem}.mt-8{margin-top:2rem}.block{display:block}.inline{display:inline}.flex{display:flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-1{height:.25rem}.h-10{height:2.5rem}.h-12{height:3rem}.h-16{height:4rem}.h-2{height:.5rem}.h-28{height:7rem}.h-4{height:1rem}.h-6{height:1.5rem}.h-8{height:2rem}.h-80{height:20rem}.h-96{height:24rem}.h-\[420px\]{height:420px}.h-auto{height:auto}.h-full{height:100%}.h-px{height:1px}.max-h-\[80vh\]{max-height:80vh}.min-h-\[72px\]{min-height:72px}.min-h-\[calc\(100vh-104px\)\]{min-height:calc(100vh - 104px)}.min-h-screen{min-height:100vh}.w-10{width:2.5rem}.w-12{width:3rem}.w-16{width:4rem}.w-2{width:.5rem}.w-28{width:7rem}.w-4{width:1rem}.w-6{width:1.5rem}.w-72{width:18rem}.w-8{width:2rem}.w-\[20rem\]{width:20rem}.w-full{width:100%}.min-w-\[160px\]{min-width:160px}.min-w-\[240px\]{min-width:240px}.max-w-2xl{max-width:42rem}.max-w-3xl{max-width:48rem}.max-w-4xl{max-width:56rem}.max-w-5xl{max-width:64rem}.max-w-6xl{max-width:72rem}.max-w-7xl{max-width:80rem}.max-w-lg{max-width:32rem}.max-w-md{max-width:28rem}.max-w-none{max-width:none}.max-w-sm{max-width:24rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.border-collapse{border-collapse:collapse}.-translate-x-1\/2{--tw-translate-x:-50%}.-translate-x-1\/2,.-translate-y-1\/2{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-1\/2{--tw-translate-y:-50%}.translate-x-full{--tw-translate-x:100%}.translate-x-full,.translate-y-full{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-full{--tw-translate-y:100%}.rotate-180{--tw-rotate:180deg}.rotate-180,.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}@keyframes spin{to{transform:rotate(1turn)}}.animate-spin{animation:spin 1s linear infinite}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.resize-none{resize:none}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-center{align-items:center}.items-stretch{align-items:stretch}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-12{gap:3rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-6{gap:1.5rem}.space-x-1>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.25rem*var(--tw-space-x-reverse));margin-left:calc(.25rem*(1 - var(--tw-space-x-reverse)))}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.5rem*var(--tw-space-x-reverse));margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)))}.space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.75rem*var(--tw-space-x-reverse));margin-left:calc(.75rem*(1 - var(--tw-space-x-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1rem*var(--tw-space-x-reverse));margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem*var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem*var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem*var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem*var(--tw-space-y-reverse))}.space-y-8>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(2rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2rem*var(--tw-space-y-reverse))}.self-center{align-self:center}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.scroll-smooth{scroll-behavior:smooth}.break-words{overflow-wrap:break-word}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:1rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-t{border-top-width:1px}.border-blue-500\/20{border-color:rgba(59,130,246,.2)}.border-gray-500\/10{border-color:hsla(220,9%,46%,.1)}.border-gray-500\/20{border-color:hsla(220,9%,46%,.2)}.border-gray-600{--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity,1))}.border-gray-600\/30{border-color:rgba(75,85,99,.3)}.border-gray-700\/30{border-color:rgba(55,65,81,.3)}.border-green-500\/20{border-color:rgba(34,197,94,.2)}.border-green-500\/30{border-color:rgba(34,197,94,.3)}.border-orange-500\/20{border-color:rgba(249,115,22,.2)}.border-purple-500\/20{border-color:rgba(168,85,247,.2)}.border-red-500\/20{border-color:rgba(239,68,68,.2)}.border-yellow-500\/20{border-color:rgba(234,179,8,.2)}.bg-\[rgb\(20_20_20_\/50\%\)\]{background-color:hsla(0,0%,8%,.5)}.bg-black\/30{background-color:rgba(0,0,0,.3)}.bg-black\/50{background-color:rgba(0,0,0,.5)}.bg-black\/80{background-color:rgba(0,0,0,.8)}.bg-blue-400{--tw-bg-opacity:1;background-color:rgb(96 165 250/var(--tw-bg-opacity,1))}.bg-blue-500{--tw-bg-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity,1))}.bg-blue-500\/10{background-color:rgba(59,130,246,.1)}.bg-blue-500\/20{background-color:rgba(59,130,246,.2)}.bg-blue-500\/90{background-color:rgba(59,130,246,.9)}.bg-blue-600{--tw-bg-opacity:1;background-color:rgb(37 99 235/var(--tw-bg-opacity,1))}.bg-emerald-500{--tw-bg-opacity:1;background-color:rgb(16 185 129/var(--tw-bg-opacity,1))}.bg-gray-500\/10{background-color:hsla(220,9%,46%,.1)}.bg-gray-500\/20{background-color:hsla(220,9%,46%,.2)}.bg-gray-600{--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity,1))}.bg-gray-600\/20{background-color:rgba(75,85,99,.2)}.bg-gray-700{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity,1))}.bg-gray-700\/50{background-color:rgba(55,65,81,.5)}.bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity,1))}.bg-gray-800\/50{background-color:rgba(31,41,55,.5)}.bg-gray-800\/95{background-color:rgba(31,41,55,.95)}.bg-gray-900{--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity,1))}.bg-gray-900\/30{background-color:rgba(17,24,39,.3)}.bg-green-200{--tw-bg-opacity:1;background-color:rgb(187 247 208/var(--tw-bg-opacity,1))}.bg-green-400{--tw-bg-opacity:1;background-color:rgb(74 222 128/var(--tw-bg-opacity,1))}.bg-green-400\/20{background-color:rgba(74,222,128,.2)}.bg-green-500{--tw-bg-opacity:1;background-color:rgb(34 197 94/var(--tw-bg-opacity,1))}.bg-green-500\/10{background-color:rgba(34,197,94,.1)}.bg-green-500\/20{background-color:rgba(34,197,94,.2)}.bg-green-500\/90{background-color:rgba(34,197,94,.9)}.bg-green-600\/20{background-color:rgba(22,163,74,.2)}.bg-neutral-900{--tw-bg-opacity:1;background-color:rgb(23 23 23/var(--tw-bg-opacity,1))}.bg-orange-400{--tw-bg-opacity:1;background-color:rgb(251 146 60/var(--tw-bg-opacity,1))}.bg-orange-500{--tw-bg-opacity:1;background-color:rgb(249 115 22/var(--tw-bg-opacity,1))}.bg-orange-500\/10{background-color:rgba(249,115,22,.1)}.bg-orange-500\/15{background-color:rgba(249,115,22,.15)}.bg-orange-500\/20{background-color:rgba(249,115,22,.2)}.bg-purple-500\/10{background-color:rgba(168,85,247,.1)}.bg-purple-600{--tw-bg-opacity:1;background-color:rgb(147 51 234/var(--tw-bg-opacity,1))}.bg-red-200{--tw-bg-opacity:1;background-color:rgb(254 202 202/var(--tw-bg-opacity,1))}.bg-red-400{--tw-bg-opacity:1;background-color:rgb(248 113 113/var(--tw-bg-opacity,1))}.bg-red-500{--tw-bg-opacity:1;background-color:rgb(239 68 68/var(--tw-bg-opacity,1))}.bg-red-500\/10{background-color:rgba(239,68,68,.1)}.bg-red-500\/20{background-color:rgba(239,68,68,.2)}.bg-red-500\/90{background-color:rgba(239,68,68,.9)}.bg-red-900\/50{background-color:rgba(127,29,29,.5)}.bg-transparent{background-color:transparent}.bg-white\/20{background-color:hsla(0,0%,100%,.2)}.bg-yellow-400{--tw-bg-opacity:1;background-color:rgb(250 204 21/var(--tw-bg-opacity,1))}.bg-yellow-500{--tw-bg-opacity:1;background-color:rgb(234 179 8/var(--tw-bg-opacity,1))}.bg-yellow-500\/10{background-color:rgba(234,179,8,.1)}.bg-yellow-500\/20{background-color:rgba(234,179,8,.2)}.bg-yellow-500\/90{background-color:rgba(234,179,8,.9)}.bg-gradient-to-b{background-image:linear-gradient(to bottom,var(--tw-gradient-stops))}.bg-gradient-to-r{background-image:linear-gradient(to right,var(--tw-gradient-stops))}.bg-gradient-to-t{background-image:linear-gradient(to top,var(--tw-gradient-stops))}.from-\[\#1f1f1f\]\/90{--tw-gradient-from:rgba(31,31,31,.9) var(--tw-gradient-from-position);--tw-gradient-to:rgba(31,31,31,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-gray-800\/20{--tw-gradient-from:rgba(31,41,55,.2) var(--tw-gradient-from-position);--tw-gradient-to:rgba(31,41,55,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-orange-500{--tw-gradient-from:#f97316 var(--tw-gradient-from-position);--tw-gradient-to:rgba(249,115,22,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-transparent{--tw-gradient-from:transparent var(--tw-gradient-from-position);--tw-gradient-to:transparent var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.via-zinc-700{--tw-gradient-to:rgba(63,63,70,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),#3f3f46 var(--tw-gradient-via-position),var(--tw-gradient-to)}.to-gray-900\/20{--tw-gradient-to:rgba(17,24,39,.2) var(--tw-gradient-to-position)}.to-orange-600{--tw-gradient-to:#ea580c var(--tw-gradient-to-position)}.to-transparent{--tw-gradient-to:transparent var(--tw-gradient-to-position)}.fill-blue-500{fill:#3b82f6}.fill-white{fill:#fff}.p-1\.5{padding:.375rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.p-8{padding:2rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-14{padding-top:3.5rem;padding-bottom:3.5rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.pr-2{padding-right:.5rem}.pt-6{padding-top:1.5rem}.text-left{text-align:left}.text-center{text-align:center}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-\[3rem\]{font-size:3rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.lowercase{text-transform:lowercase}.leading-relaxed{line-height:1.625}.leading-snug{line-height:1.375}.leading-tight{line-height:1.25}.text-black{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity,1))}.text-blue-300{--tw-text-opacity:1;color:rgb(147 197 253/var(--tw-text-opacity,1))}.text-blue-400{--tw-text-opacity:1;color:rgb(96 165 250/var(--tw-text-opacity,1))}.text-blue-500{--tw-text-opacity:1;color:rgb(59 130 246/var(--tw-text-opacity,1))}.text-blue-600{--tw-text-opacity:1;color:rgb(37 99 235/var(--tw-text-opacity,1))}.text-cyan-300{--tw-text-opacity:1;color:rgb(103 232 249/var(--tw-text-opacity,1))}.text-cyan-400{--tw-text-opacity:1;color:rgb(34 211 238/var(--tw-text-opacity,1))}.text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity,1))}.text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity,1))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity,1))}.text-green-200{--tw-text-opacity:1;color:rgb(187 247 208/var(--tw-text-opacity,1))}.text-green-300{--tw-text-opacity:1;color:rgb(134 239 172/var(--tw-text-opacity,1))}.text-green-400{--tw-text-opacity:1;color:rgb(74 222 128/var(--tw-text-opacity,1))}.text-green-500{--tw-text-opacity:1;color:rgb(34 197 94/var(--tw-text-opacity,1))}.text-orange-200{--tw-text-opacity:1;color:rgb(254 215 170/var(--tw-text-opacity,1))}.text-orange-300{--tw-text-opacity:1;color:rgb(253 186 116/var(--tw-text-opacity,1))}.text-orange-400{--tw-text-opacity:1;color:rgb(251 146 60/var(--tw-text-opacity,1))}.text-orange-500{--tw-text-opacity:1;color:rgb(249 115 22/var(--tw-text-opacity,1))}.text-purple-400{--tw-text-opacity:1;color:rgb(192 132 252/var(--tw-text-opacity,1))}.text-purple-500{--tw-text-opacity:1;color:rgb(168 85 247/var(--tw-text-opacity,1))}.text-red-200{--tw-text-opacity:1;color:rgb(254 202 202/var(--tw-text-opacity,1))}.text-red-300{--tw-text-opacity:1;color:rgb(252 165 165/var(--tw-text-opacity,1))}.text-red-400{--tw-text-opacity:1;color:rgb(248 113 113/var(--tw-text-opacity,1))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.text-white\/10{color:hsla(0,0%,100%,.1)}.text-yellow-200{--tw-text-opacity:1;color:rgb(254 240 138/var(--tw-text-opacity,1))}.text-yellow-300{--tw-text-opacity:1;color:rgb(253 224 71/var(--tw-text-opacity,1))}.text-yellow-400{--tw-text-opacity:1;color:rgb(250 204 21/var(--tw-text-opacity,1))}.text-yellow-600{--tw-text-opacity:1;color:rgb(202 138 4/var(--tw-text-opacity,1))}.text-zinc-600{--tw-text-opacity:1;color:rgb(82 82 91/var(--tw-text-opacity,1))}.placeholder-gray-500::-moz-placeholder{--tw-placeholder-opacity:1;color:rgb(107 114 128/var(--tw-placeholder-opacity,1))}.placeholder-gray-500::placeholder{--tw-placeholder-opacity:1;color:rgb(107 114 128/var(--tw-placeholder-opacity,1))}.opacity-0{opacity:0}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-70{opacity:.7}.opacity-90{opacity:.9}.shadow-2xl{--tw-shadow:0 25px 50px -12px rgba(0,0,0,.25);--tw-shadow-colored:0 25px 50px -12px var(--tw-shadow-color)}.shadow-2xl,.shadow-lg{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-md{--tw-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -2px rgba(0,0,0,.1);--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.ring-2{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.blur{--tw-blur:blur(8px)}.blur,.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-md{--tw-backdrop-blur:blur(12px)}.backdrop-blur-md,.backdrop-blur-sm{-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.backdrop-blur-sm{--tw-backdrop-blur:blur(4px)}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}.duration-500{transition-duration:.5s}.\[checksum\:4\]{checksum:4}.\[data\:variable\]{data:variable}.\[name\:4\]{name:4}.\[size\:4\]{size:4}.hover\:bg-\[rgb\(20_20_20_\/30\%\)\]:hover{background-color:hsla(0,0%,8%,.3)}.hover\:bg-blue-600:hover{--tw-bg-opacity:1;background-color:rgb(37 99 235/var(--tw-bg-opacity,1))}.hover\:bg-blue-700:hover{--tw-bg-opacity:1;background-color:rgb(29 78 216/var(--tw-bg-opacity,1))}.hover\:bg-emerald-600:hover{--tw-bg-opacity:1;background-color:rgb(5 150 105/var(--tw-bg-opacity,1))}.hover\:bg-gray-500:hover{--tw-bg-opacity:1;background-color:rgb(107 114 128/var(--tw-bg-opacity,1))}.hover\:bg-gray-600\/30:hover{background-color:rgba(75,85,99,.3)}.hover\:bg-green-500\/20:hover{background-color:rgba(34,197,94,.2)}.hover\:bg-green-500\/30:hover{background-color:rgba(34,197,94,.3)}.hover\:bg-green-600\/30:hover{background-color:rgba(22,163,74,.3)}.hover\:bg-green-600\/40:hover{background-color:rgba(22,163,74,.4)}.hover\:bg-orange-500\/20:hover{background-color:rgba(249,115,22,.2)}.hover\:bg-orange-500\/40:hover{background-color:rgba(249,115,22,.4)}.hover\:bg-orange-600:hover{--tw-bg-opacity:1;background-color:rgb(234 88 12/var(--tw-bg-opacity,1))}.hover\:bg-purple-500:hover{--tw-bg-opacity:1;background-color:rgb(168 85 247/var(--tw-bg-opacity,1))}.hover\:bg-purple-500\/20:hover{background-color:rgba(168,85,247,.2)}.hover\:bg-red-500\/20:hover{background-color:rgba(239,68,68,.2)}.hover\:bg-red-500\/30:hover{background-color:rgba(239,68,68,.3)}.hover\:bg-red-600:hover{--tw-bg-opacity:1;background-color:rgb(220 38 38/var(--tw-bg-opacity,1))}.hover\:bg-red-600\/40:hover{background-color:rgba(220,38,38,.4)}.hover\:bg-white\/30:hover{background-color:hsla(0,0%,100%,.3)}.hover\:bg-yellow-600\/40:hover{background-color:rgba(202,138,4,.4)}.hover\:from-orange-600:hover{--tw-gradient-from:#ea580c var(--tw-gradient-from-position);--tw-gradient-to:rgba(234,88,12,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.hover\:to-orange-700:hover{--tw-gradient-to:#c2410c var(--tw-gradient-to-position)}.hover\:text-gray-300:hover{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity,1))}.hover\:text-gray-700:hover{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity,1))}.hover\:text-green-300:hover{--tw-text-opacity:1;color:rgb(134 239 172/var(--tw-text-opacity,1))}.hover\:text-red-300:hover{--tw-text-opacity:1;color:rgb(252 165 165/var(--tw-text-opacity,1))}.hover\:text-white:hover{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.hover\:opacity-80:hover{opacity:.8}.focus\:border-green-500\/40:focus{border-color:rgba(34,197,94,.4)}.focus\:border-orange-500\/40:focus{border-color:rgba(249,115,22,.4)}.focus\:border-purple-500\/40:focus{border-color:rgba(168,85,247,.4)}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}.group:hover .group-hover\:scale-105{--tw-scale-x:1.05;--tw-scale-y:1.05}.group:hover .group-hover\:scale-105,.group:hover .group-hover\:scale-110{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.group:hover .group-hover\:scale-110{--tw-scale-x:1.1;--tw-scale-y:1.1}.group:hover .group-hover\:opacity-100{opacity:1}@media (min-width:640px){.sm\:mb-0{margin-bottom:0}.sm\:mb-3{margin-bottom:.75rem}.sm\:mr-2{margin-right:.5rem}.sm\:block{display:block}.sm\:inline{display:inline}.sm\:flex{display:flex}.sm\:h-10{height:2.5rem}.sm\:h-12{height:3rem}.sm\:w-10{width:2.5rem}.sm\:w-12{width:3rem}.sm\:w-\[24rem\]{width:24rem}.sm\:flex-row{flex-direction:row}.sm\:items-center{align-items:center}.sm\:justify-between{justify-content:space-between}.sm\:gap-4{gap:1rem}.sm\:space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.5rem*var(--tw-space-x-reverse));margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)))}.sm\:space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.75rem*var(--tw-space-x-reverse));margin-left:calc(.75rem*(1 - var(--tw-space-x-reverse)))}.sm\:space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1rem*var(--tw-space-x-reverse));margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)))}.sm\:space-y-0>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(0px*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(0px*var(--tw-space-y-reverse))}.sm\:p-4{padding:1rem}.sm\:px-0{padding-left:0;padding-right:0}.sm\:px-3{padding-left:.75rem;padding-right:.75rem}.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}.sm\:py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.sm\:text-3xl{font-size:1.875rem;line-height:2.25rem}.sm\:text-base{font-size:1rem;line-height:1.5rem}.sm\:text-sm{font-size:.875rem;line-height:1.25rem}.sm\:text-xl{font-size:1.25rem;line-height:1.75rem}}@media (min-width:768px){.md\:flex{display:flex}.md\:hidden{display:none}.md\:h-32{height:8rem}.md\:h-\[32rem\]{height:32rem}.md\:w-\[28rem\]{width:28rem}.md\:w-auto{width:auto}.md\:w-px{width:1px}.md\:flex-none{flex:none}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.md\:flex-row{flex-direction:row}.md\:flex-col{flex-direction:column}.md\:bg-gradient-to-b{background-image:linear-gradient(to bottom,var(--tw-gradient-stops))}}@media (min-width:1024px){.lg\:col-span-2{grid-column:span 2/span 2}.lg\:col-span-3{grid-column:span 3/span 3}.lg\:block{display:block}.lg\:w-\[32rem\]{width:32rem}.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}.lg\:px-8{padding-left:2rem;padding-right:2rem}} \ No newline at end of file diff --git a/dist/app.js b/dist/app.js index 762e781..7309e85 100644 --- a/dist/app.js +++ b/dist/app.js @@ -568,7 +568,7 @@ var EnhancedConnectionSetup = ({ ]), showQRCode && qrCodeUrl && React.createElement("div", { key: "qr-container", - className: "mt-4 p-4 bg-gray-800/50 border border-gray-600/30 rounded-lg text-center" + className: "mt-4 p-4 border border-gray-600/30 rounded-lg text-center" }, [ React.createElement("h4", { key: "qr-title", @@ -939,7 +939,7 @@ var EnhancedConnectionSetup = ({ // QR Code section for answer qrCodeUrl && React.createElement("div", { key: "qr-container", - className: "mt-4 p-4 bg-gray-800/50 border border-gray-600/30 rounded-lg text-center" + className: "mt-4 p-4 border border-gray-600/30 rounded-lg text-center" }, [ React.createElement("h4", { key: "qr-title", @@ -1923,9 +1923,57 @@ var EnhancedSecureP2PChat = () => { const generateQRCode = async (data) => { try { const originalSize = typeof data === "string" ? data.length : JSON.stringify(data).length; - const payload = typeof data === "string" ? data : JSON.stringify(data); const isDesktop = typeof window !== "undefined" && (window.innerWidth || 0) >= 1024; const QR_SIZE = isDesktop ? 720 : 512; + if (typeof window.generateBinaryQRCodeFromObject === "function") { + try { + const obj = typeof data === "string" ? JSON.parse(data) : data; + const qrDataUrl = await window.generateBinaryQRCodeFromObject(obj, { errorCorrectionLevel: "M", size: QR_SIZE, margin: 2 }); + if (qrDataUrl) { + try { + if (qrAnimationRef.current && qrAnimationRef.current.timer) { + clearInterval(qrAnimationRef.current.timer); + } + } catch { + } + qrAnimationRef.current = { timer: null, chunks: [], idx: 0, active: false }; + setQrFrameIndex(0); + setQrFramesTotal(0); + setQrManualMode(false); + setQrCodeUrl(qrDataUrl); + setQrFramesTotal(1); + setQrFrameIndex(1); + return; + } + } catch (e2) { + console.warn("Binary QR generation failed, falling back to compressed:", e2?.message || e2); + } + } + if (typeof window.generateCompressedQRCode === "function") { + try { + const payload2 = typeof data === "string" ? data : JSON.stringify(data); + const qrDataUrl = await window.generateCompressedQRCode(payload2, { errorCorrectionLevel: "M", size: QR_SIZE, margin: 2 }); + if (qrDataUrl) { + try { + if (qrAnimationRef.current && qrAnimationRef.current.timer) { + clearInterval(qrAnimationRef.current.timer); + } + } catch { + } + qrAnimationRef.current = { timer: null, chunks: [], idx: 0, active: false }; + setQrFrameIndex(0); + setQrFramesTotal(0); + setQrManualMode(false); + setQrCodeUrl(qrDataUrl); + setQrFramesTotal(1); + setQrFrameIndex(1); + return; + } + } catch (e2) { + console.warn("Compressed QR generation failed, falling back to plain:", e2?.message || e2); + } + } + const payload = typeof data === "string" ? data : JSON.stringify(data); if (payload.length <= MAX_QR_LEN) { if (!window.generateQRCode) throw new Error("QR code generator unavailable"); try { @@ -2060,6 +2108,127 @@ var EnhancedSecureP2PChat = () => { }; const handleQRScan = async (scannedData) => { try { + console.log("QR Code scanned:", scannedData.substring(0, 100) + "..."); + console.log("Current buffer state:", qrChunksBufferRef.current); + if (scannedData.startsWith("SB1:bin:") || qrChunksBufferRef.current && qrChunksBufferRef.current.id) { + console.log("Binary chunk detected:", scannedData.substring(0, 50) + "..."); + if (!qrChunksBufferRef.current.id) { + console.log("Initializing buffer for binary chunks"); + qrChunksBufferRef.current = { + id: `bin_${Date.now()}`, + total: 4, + // We expect 4 chunks + seen: /* @__PURE__ */ new Set(), + items: [], + lastUpdateMs: Date.now() + }; + } + const chunkHash = scannedData.substring(0, 50); + if (qrChunksBufferRef.current.seen.has(chunkHash)) { + console.log(`Chunk already scanned, ignoring...`); + return Promise.resolve(false); + } + qrChunksBufferRef.current.seen.add(chunkHash); + qrChunksBufferRef.current.items.push(scannedData); + qrChunksBufferRef.current.lastUpdateMs = Date.now(); + try { + const uniqueCount = qrChunksBufferRef.current.seen.size; + document.dispatchEvent(new CustomEvent("qr-scan-progress", { + detail: { + id: qrChunksBufferRef.current.id, + seq: uniqueCount, + total: qrChunksBufferRef.current.total + } + })); + setQrFramesTotal(qrChunksBufferRef.current.total); + setQrFrameIndex(uniqueCount); + } catch { + } + const isComplete = qrChunksBufferRef.current.seen.size >= qrChunksBufferRef.current.total; + console.log(`Chunks collected: ${qrChunksBufferRef.current.seen.size}/${qrChunksBufferRef.current.total}, complete: ${isComplete}`); + if (!isComplete) { + console.log(`Scanned chunk ${qrChunksBufferRef.current.seen.size}/${qrChunksBufferRef.current.total}, waiting for more...`); + return Promise.resolve(false); + } + try { + const fullBinaryData = qrChunksBufferRef.current.items.join(""); + if (showOfferStep) { + setAnswerInput(fullBinaryData); + } else { + setOfferInput(fullBinaryData); + } + setMessages((prev) => [...prev, { + message: "All binary chunks captured. Payload reconstructed.", + type: "success" + }]); + qrChunksBufferRef.current = { id: null, total: 0, seen: /* @__PURE__ */ new Set(), items: [] }; + setShowQRScannerModal(false); + return Promise.resolve(true); + } catch (e2) { + console.warn("Binary chunks reconstruction failed:", e2); + return Promise.resolve(false); + } + } + if (scannedData.length > 100 && !scannedData.startsWith("{") && !scannedData.startsWith("[")) { + console.log("Detected potential binary chunk (long non-JSON string):", scannedData.substring(0, 50) + "..."); + if (!qrChunksBufferRef.current.id) { + console.log("Initializing buffer for potential binary chunks"); + qrChunksBufferRef.current = { + id: `bin_${Date.now()}`, + total: 4, + // We expect 4 chunks + seen: /* @__PURE__ */ new Set(), + items: [], + lastUpdateMs: Date.now() + }; + } + const chunkHash = scannedData.substring(0, 50); + if (qrChunksBufferRef.current.seen.has(chunkHash)) { + console.log(`Chunk already scanned, ignoring...`); + return Promise.resolve(false); + } + qrChunksBufferRef.current.seen.add(chunkHash); + qrChunksBufferRef.current.items.push(scannedData); + qrChunksBufferRef.current.lastUpdateMs = Date.now(); + try { + const uniqueCount = qrChunksBufferRef.current.seen.size; + document.dispatchEvent(new CustomEvent("qr-scan-progress", { + detail: { + id: qrChunksBufferRef.current.id, + seq: uniqueCount, + total: qrChunksBufferRef.current.total + } + })); + setQrFramesTotal(qrChunksBufferRef.current.total); + setQrFrameIndex(uniqueCount); + } catch { + } + const isComplete = qrChunksBufferRef.current.seen.size >= qrChunksBufferRef.current.total; + console.log(`Chunks collected: ${qrChunksBufferRef.current.seen.size}/${qrChunksBufferRef.current.total}, complete: ${isComplete}`); + if (!isComplete) { + console.log(`Scanned chunk ${qrChunksBufferRef.current.seen.size}/${qrChunksBufferRef.current.total}, waiting for more...`); + return Promise.resolve(false); + } + try { + const fullBinaryData = qrChunksBufferRef.current.items.join(""); + if (showOfferStep) { + setAnswerInput(fullBinaryData); + } else { + setOfferInput(fullBinaryData); + } + setMessages((prev) => [...prev, { + message: "All binary chunks captured. Payload reconstructed.", + type: "success" + }]); + qrChunksBufferRef.current = { id: null, total: 0, seen: /* @__PURE__ */ new Set(), items: [] }; + setShowQRScannerModal(false); + return Promise.resolve(true); + } catch (e2) { + console.warn("Binary chunks reconstruction failed:", e2); + return Promise.resolve(false); + } + } + console.log("Processing single QR code:", scannedData.substring(0, 50) + "..."); let parsedData; if (typeof window.decodeAnyPayload === "function") { const any = window.decodeAnyPayload(scannedData); @@ -2072,6 +2241,7 @@ var EnhancedSecureP2PChat = () => { const maybeDecompressed = typeof window.decompressIfNeeded === "function" ? window.decompressIfNeeded(scannedData) : scannedData; parsedData = JSON.parse(maybeDecompressed); } + console.log("Decoded data:", parsedData); if (parsedData.hdr && parsedData.body) { const { hdr } = parsedData; if (!qrChunksBufferRef.current.id || qrChunksBufferRef.current.id !== hdr.id) { @@ -2258,8 +2428,7 @@ var EnhancedSecureP2PChat = () => { try { if (typeof window.encodeBinaryToPrefixed === "function") { const bin = window.encodeBinaryToPrefixed(offerString); - const id = `bin_${Date.now()}_${Math.random().toString(36).slice(2)}`; - const TARGET_CHUNKS = 10; + const TARGET_CHUNKS = 4; let FRAME_MAX = Math.max(200, Math.floor(bin.length / TARGET_CHUNKS)); if (FRAME_MAX <= 0) FRAME_MAX = 200; let total = Math.ceil(bin.length / FRAME_MAX); @@ -2267,11 +2436,12 @@ var EnhancedSecureP2PChat = () => { total = 2; FRAME_MAX = Math.ceil(bin.length / 2) || 1; } + const id = `bin_${Date.now()}_${Math.random().toString(36).slice(2)}`; const chunks = []; for (let i = 0; i < total; i++) { const seq = i + 1; const part = bin.slice(i * FRAME_MAX, (i + 1) * FRAME_MAX); - chunks.push(JSON.stringify({ hdr: { v: 1, id, seq, total, rt: "bin" }, body: part })); + chunks.push(part); } const isDesktop = typeof window !== "undefined" && (window.innerWidth || 0) >= 1024; const QR_SIZE = isDesktop ? 720 : 512; @@ -2295,9 +2465,15 @@ var EnhancedSecureP2PChat = () => { setShowQRCode(true); } catch { } + } else { + await generateQRCode(offer); + try { + setShowQRCode(true); + } catch { + } } } catch (e2) { - console.warn("Offer QR precompute failed:", e2); + console.warn("Offer QR generation failed:", e2); } const existingMessages = messages.filter( (m) => m.type === "system" && (m.message.includes("Secure invitation created") || m.message.includes("Send the encrypted code")) @@ -2372,8 +2548,7 @@ var EnhancedSecureP2PChat = () => { try { if (typeof window.encodeBinaryToPrefixed === "function") { const bin = window.encodeBinaryToPrefixed(answerString); - const id = `ans_${Date.now()}_${Math.random().toString(36).slice(2)}`; - const TARGET_CHUNKS = 10; + const TARGET_CHUNKS = 4; let FRAME_MAX = Math.max(200, Math.floor(bin.length / TARGET_CHUNKS)); if (FRAME_MAX <= 0) FRAME_MAX = 200; let total = Math.ceil(bin.length / FRAME_MAX); @@ -2381,11 +2556,12 @@ var EnhancedSecureP2PChat = () => { total = 2; FRAME_MAX = Math.ceil(bin.length / 2) || 1; } + const id = `ans_${Date.now()}_${Math.random().toString(36).slice(2)}`; const chunks = []; for (let i = 0; i < total; i++) { const seq = i + 1; const part = bin.slice(i * FRAME_MAX, (i + 1) * FRAME_MAX); - chunks.push(JSON.stringify({ hdr: { v: 1, id, seq, total, rt: "bin" }, body: part })); + chunks.push(part); } const isDesktop = typeof window !== "undefined" && (window.innerWidth || 0) >= 1024; const QR_SIZE = isDesktop ? 720 : 512; @@ -2410,13 +2586,7 @@ var EnhancedSecureP2PChat = () => { } catch { } } else { - let url = ""; - if (typeof window.generateCompressedQRCode === "function") { - url = await window.generateCompressedQRCode(answerString); - } else { - url = await generateQRCode(answerString); - } - if (url) setQrCodeUrl(url); + await generateQRCode(answer); try { setShowQRCode(true); } catch { @@ -2659,6 +2829,7 @@ var EnhancedSecureP2PChat = () => { setShowQRCode(false); setShowQRScanner(false); setShowQRScannerModal(false); + qrChunksBufferRef.current = { id: null, total: 0, seen: /* @__PURE__ */ new Set(), items: [] }; if (!shouldPreserveAnswerData()) { setQrCodeUrl(""); } @@ -2750,6 +2921,89 @@ var EnhancedSecureP2PChat = () => { addMessageWithAutoScroll(" All security features enabled by default", "system"); } }, [isConnectedAndVerified, pendingSession, connectionStatus]); + React.useEffect(() => { + if (showQRScannerModal && window.Html5Qrcode) { + const html5Qrcode = new window.Html5Qrcode("qr-reader"); + const config = { + fps: 10 + // Убираем qrbox чтобы использовать всю область + }; + let isScanning = true; + html5Qrcode.start( + { facingMode: "environment" }, + // Use back camera + config, + (decodedText, decodedResult) => { + if (!isScanning) { + console.log("Scanner stopped, ignoring scan"); + return; + } + console.log("QR Code scanned:", decodedText); + console.log("Current buffer state:", qrChunksBufferRef.current); + handleQRScan(decodedText).then((success) => { + console.log("QR scan result:", success); + if (success) { + console.log("Closing scanner and modal"); + isScanning = false; + try { + console.log("Stopping scanner..."); + html5Qrcode.stop().then(() => { + console.log("Scanner stopped, clearing..."); + html5Qrcode.clear(); + setShowQRScannerModal(false); + }).catch((err) => { + console.log("Error stopping scanner:", err); + try { + html5Qrcode.clear(); + } catch (clearErr) { + console.log("Error clearing scanner:", clearErr); + } + setShowQRScannerModal(false); + }); + } catch (err) { + console.log("Error in scanner cleanup:", err); + setShowQRScannerModal(false); + } + } else { + console.log("Continuing to scan for more chunks..."); + } + }).catch((error) => { + console.error("QR scan processing error:", error); + }); + }, + (error) => { + if (isScanning) { + console.log("QR scan error (ignored):", error); + } + } + ).catch((err) => { + console.error("QR Scanner start error:", err); + setShowQRScannerModal(false); + }); + return () => { + isScanning = false; + try { + html5Qrcode.stop().then(() => { + html5Qrcode.clear(); + }).catch((err) => { + console.log("Scanner already stopped or error stopping:", err); + try { + html5Qrcode.clear(); + } catch (clearErr) { + console.log("Error clearing scanner in cleanup:", clearErr); + } + }); + } catch (err) { + console.log("Error in cleanup:", err); + try { + html5Qrcode.clear(); + } catch (clearErr) { + console.log("Error clearing scanner in cleanup:", clearErr); + } + } + }; + } + }, [showQRScannerModal]); return React.createElement("div", { className: "minimal-bg min-h-screen" }, [ @@ -2822,7 +3076,81 @@ var EnhancedSecureP2PChat = () => { // PAKE passwords removed - using SAS verification instead markAnswerCreated }) - ) + ), + // QR Scanner Modal + showQRScannerModal && React.createElement("div", { + key: "qr-scanner-modal", + className: "fixed inset-0 bg-black/80 flex items-center justify-center z-50" + }, [ + React.createElement("div", { + key: "scanner-container", + className: "bg-gray-900 rounded-lg p-4 max-w-2xl w-full mx-4" + }, [ + React.createElement("div", { + key: "scanner-header", + className: "flex items-center justify-between mb-4" + }, [ + React.createElement("h3", { + key: "scanner-title", + className: "text-lg font-medium text-white" + }, "QR Code Scanner"), + React.createElement("button", { + key: "close-btn", + onClick: () => { + setShowQRScannerModal(false); + qrChunksBufferRef.current = { id: null, total: 0, seen: /* @__PURE__ */ new Set(), items: [] }; + }, + className: "text-gray-400 hover:text-white" + }, [ + React.createElement("i", { + key: "close-icon", + className: "fas fa-times" + }) + ]) + ]), + React.createElement("div", { + key: "scanner-content", + className: "text-center" + }, [ + React.createElement("p", { + key: "scanner-description", + className: "text-gray-400 mb-4" + }, "Point your camera at the QR code to scan"), + qrChunksBufferRef.current && qrChunksBufferRef.current.id && React.createElement("div", { + key: "progress-indicator", + className: "mb-4 p-3 bg-blue-500/10 border border-blue-500/20 rounded-lg" + }, [ + React.createElement("p", { + key: "progress-text", + className: "text-blue-400 text-sm" + }, `Scanned: ${qrChunksBufferRef.current.seen.size}/${qrChunksBufferRef.current.total} parts`), + React.createElement("div", { + key: "progress-bar", + className: "w-full bg-gray-700 rounded-full h-2 mt-2" + }, [ + React.createElement("div", { + key: "progress-fill", + className: "bg-blue-500 h-2 rounded-full transition-all duration-300", + style: { + width: `${qrChunksBufferRef.current.seen.size / qrChunksBufferRef.current.total * 100}%` + } + }) + ]) + ]), + React.createElement("div", { + key: "scanner-placeholder", + id: "qr-reader", + className: "w-full h-96 bg-gray-800 rounded-lg flex items-center justify-center", + style: { minHeight: "400px" } + }, [ + React.createElement("p", { + key: "scanner-placeholder-text", + className: "text-gray-500" + }, "Camera will start here...") + ]) + ]) + ]) + ]) ]); }; function initializeApp() { diff --git a/dist/app.js.map b/dist/app.js.map index 45e8cb4..af281f2 100644 --- a/dist/app.js.map +++ b/dist/app.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../src/app.jsx"], - "sourcesContent": ["\r\n // Enhanced Copy Button with better UX\r\n const EnhancedCopyButton = ({ text, className = \"\", children }) => {\r\n const [copied, setCopied] = React.useState(false);\r\n \r\n const handleCopy = async () => {\r\n try {\r\n await navigator.clipboard.writeText(text);\r\n setCopied(true);\r\n setTimeout(() => setCopied(false), 2000);\r\n } catch (error) {\r\n console.error('Copy failed:', error);\r\n // Fallback for older browsers\r\n const textArea = document.createElement('textarea');\r\n textArea.value = text;\r\n document.body.appendChild(textArea);\r\n textArea.select();\r\n document.execCommand('copy');\r\n document.body.removeChild(textArea);\r\n setCopied(true);\r\n setTimeout(() => setCopied(false), 2000);\r\n }\r\n };\r\n \r\n return React.createElement('button', {\r\n onClick: handleCopy,\r\n className: `${className} transition-all duration-200`\r\n }, [\r\n React.createElement('i', {\r\n key: 'icon',\r\n className: `${copied ? 'fas fa-check accent-green' : 'fas fa-copy text-secondary'} mr-2`\r\n }),\r\n copied ? 'Copied!' : children\r\n ]);\r\n };\r\n \r\n // Verification Component\r\n const VerificationStep = ({ verificationCode, onConfirm, onReject, localConfirmed, remoteConfirmed, bothConfirmed }) => {\r\n return React.createElement('div', {\r\n className: \"card-minimal rounded-xl p-6 border-purple-500/20\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'header',\r\n className: \"flex items-center mb-4\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'icon',\r\n className: \"w-10 h-10 bg-purple-500/10 border border-purple-500/20 rounded-lg flex items-center justify-center mr-3\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-shield-alt accent-purple'\r\n })\r\n ]),\r\n React.createElement('h3', {\r\n key: 'title',\r\n className: \"text-lg font-medium text-primary\"\r\n }, \"Security verification\")\r\n ]),\r\n React.createElement('div', {\r\n key: 'content',\r\n className: \"space-y-4\"\r\n }, [\r\n React.createElement('p', {\r\n key: 'description',\r\n className: \"text-secondary text-sm\"\r\n }, \"Verify the security code with your contact via another communication channel (voice, SMS, etc.):\"),\r\n React.createElement('div', {\r\n key: 'code-display',\r\n className: \"text-center\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'code',\r\n className: \"verification-code text-2xl py-4\"\r\n }, verificationCode)\r\n ]),\r\n // Verification status indicators\r\n React.createElement('div', {\r\n key: 'verification-status',\r\n className: \"space-y-2\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'local-status',\r\n className: `flex items-center justify-between p-2 rounded-lg ${localConfirmed ? 'bg-green-500/10 border border-green-500/20' : 'bg-gray-500/10 border border-gray-500/20'}`\r\n }, [\r\n React.createElement('span', {\r\n key: 'local-label',\r\n className: \"text-sm text-secondary\"\r\n }, \"Your confirmation:\"),\r\n React.createElement('div', {\r\n key: 'local-indicator',\r\n className: \"flex items-center\"\r\n }, [\r\n React.createElement('i', {\r\n key: 'local-icon',\r\n className: `fas ${localConfirmed ? 'fa-check-circle text-green-400' : 'fa-clock text-gray-400'} mr-2`\r\n }),\r\n React.createElement('span', {\r\n key: 'local-text',\r\n className: `text-sm ${localConfirmed ? 'text-green-400' : 'text-gray-400'}`\r\n }, localConfirmed ? 'Confirmed' : 'Pending')\r\n ])\r\n ]),\r\n React.createElement('div', {\r\n key: 'remote-status',\r\n className: `flex items-center justify-between p-2 rounded-lg ${remoteConfirmed ? 'bg-green-500/10 border border-green-500/20' : 'bg-gray-500/10 border border-gray-500/20'}`\r\n }, [\r\n React.createElement('span', {\r\n key: 'remote-label',\r\n className: \"text-sm text-secondary\"\r\n }, \"Peer confirmation:\"),\r\n React.createElement('div', {\r\n key: 'remote-indicator',\r\n className: \"flex items-center\"\r\n }, [\r\n React.createElement('i', {\r\n key: 'remote-icon',\r\n className: `fas ${remoteConfirmed ? 'fa-check-circle text-green-400' : 'fa-clock text-gray-400'} mr-2`\r\n }),\r\n React.createElement('span', {\r\n key: 'remote-text',\r\n className: `text-sm ${remoteConfirmed ? 'text-green-400' : 'text-gray-400'}`\r\n }, remoteConfirmed ? 'Confirmed' : 'Pending')\r\n ])\r\n ])\r\n ]),\r\n React.createElement('div', {\r\n key: 'warning',\r\n className: \"p-3 bg-yellow-500/10 border border-yellow-500/20 rounded-lg\"\r\n }, [\r\n React.createElement('p', {\r\n className: \"text-yellow-400 text-sm flex items-center\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-exclamation-triangle mr-2'\r\n }),\r\n 'Make sure the codes match exactly.!'\r\n ])\r\n ]),\r\n React.createElement('div', {\r\n key: 'buttons',\r\n className: \"flex space-x-3\"\r\n }, [\r\n React.createElement('button', {\r\n key: 'confirm',\r\n onClick: onConfirm,\r\n disabled: localConfirmed,\r\n className: `flex-1 py-3 px-4 rounded-lg font-medium transition-all duration-200 ${localConfirmed ? 'bg-gray-500/20 text-gray-400 cursor-not-allowed' : 'btn-verify text-white'}`\r\n }, [\r\n React.createElement('i', {\r\n className: `fas ${localConfirmed ? 'fa-check-circle' : 'fa-check'} mr-2`\r\n }),\r\n localConfirmed ? 'Confirmed' : 'The codes match'\r\n ]),\r\n React.createElement('button', {\r\n key: 'reject',\r\n onClick: onReject,\r\n className: \"flex-1 bg-red-500/10 hover:bg-red-500/20 text-red-400 border border-red-500/20 py-3 px-4 rounded-lg font-medium transition-all duration-200\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-times mr-2'\r\n }),\r\n 'The codes do not match'\r\n ])\r\n ])\r\n ])\r\n ]);\r\n };\r\n \r\n // Enhanced Chat Message with better security indicators\r\n const EnhancedChatMessage = ({ message, type, timestamp }) => {\r\n const formatTime = (ts) => {\r\n return new Date(ts).toLocaleTimeString('ru-RU', { \r\n hour: '2-digit', \r\n minute: '2-digit',\r\n second: '2-digit'\r\n });\r\n };\r\n \r\n const getMessageStyle = () => {\r\n switch (type) {\r\n case 'sent':\r\n return {\r\n container: \"ml-auto bg-orange-500/15 border-orange-500/20 text-primary\",\r\n icon: \"fas fa-lock accent-orange\",\r\n label: \"Encrypted\"\r\n };\r\n case 'received':\r\n return {\r\n container: \"mr-auto card-minimal text-primary\",\r\n icon: \"fas fa-unlock-alt accent-green\",\r\n label: \"Decrypted\"\r\n };\r\n case 'system':\r\n return {\r\n container: \"mx-auto bg-yellow-500/10 border border-yellow-500/20 text-yellow-400\",\r\n icon: \"fas fa-info-circle accent-yellow\",\r\n label: \"System\"\r\n };\r\n default:\r\n return {\r\n container: \"mx-auto card-minimal text-secondary\",\r\n icon: \"fas fa-circle text-muted\",\r\n label: \"Unknown\"\r\n };\r\n }\r\n };\r\n \r\n const style = getMessageStyle();\r\n \r\n return React.createElement('div', {\r\n className: `message-slide mb-3 p-3 rounded-lg max-w-md break-words ${style.container} border`\r\n }, [\r\n React.createElement('div', {\r\n key: 'content',\r\n className: \"flex items-start space-x-2\"\r\n }, [\r\n React.createElement('i', {\r\n key: 'icon',\r\n className: `${style.icon} text-sm mt-0.5 opacity-70`\r\n }),\r\n React.createElement('div', {\r\n key: 'text',\r\n className: \"flex-1\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'message',\r\n className: \"text-sm\"\r\n }, message),\r\n timestamp && React.createElement('div', {\r\n key: 'meta',\r\n className: \"flex items-center justify-between mt-1 text-xs opacity-50\"\r\n }, [\r\n React.createElement('span', {\r\n key: 'time'\r\n }, formatTime(timestamp)),\r\n React.createElement('span', {\r\n key: 'status',\r\n className: \"text-xs\"\r\n }, style.label)\r\n ])\r\n ])\r\n ])\r\n ]);\r\n };\r\n \r\n // Enhanced Connection Setup with verification\r\n const EnhancedConnectionSetup = ({\r\n messages, \r\n onCreateOffer, \r\n onCreateAnswer, \r\n onConnect, \r\n onClearData,\r\n onVerifyConnection,\r\n connectionStatus,\r\n offerData,\r\n answerData,\r\n offerInput,\r\n setOfferInput,\r\n answerInput,\r\n setAnswerInput,\r\n showOfferStep,\r\n showAnswerStep,\r\n verificationCode,\r\n showVerification,\r\n showQRCode,\r\n qrCodeUrl,\r\n showQRScanner,\r\n setShowQRCode,\r\n setShowQRScanner,\r\n setShowQRScannerModal,\r\n offerPassword,\r\n answerPassword,\r\n localVerificationConfirmed,\r\n remoteVerificationConfirmed,\r\n bothVerificationsConfirmed,\r\n // QR control props\r\n qrFramesTotal,\r\n qrFrameIndex,\r\n qrManualMode,\r\n toggleQrManualMode,\r\n nextQrFrame,\r\n prevQrFrame,\r\n markAnswerCreated\r\n }) => {\r\n const [mode, setMode] = React.useState('select');\r\n \r\n const resetToSelect = () => {\r\n setMode('select');\r\n onClearData();\r\n };\r\n \r\n const handleVerificationConfirm = () => {\r\n onVerifyConnection(true);\r\n };\r\n \r\n const handleVerificationReject = () => {\r\n onVerifyConnection(false);\r\n };\r\n \r\n if (showVerification) {\r\n return React.createElement('div', {\r\n className: \"min-h-[calc(100vh-104px)] flex items-center justify-center p-4\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'verification',\r\n className: \"w-full max-w-md\"\r\n }, [\r\n React.createElement(VerificationStep, {\r\n verificationCode: verificationCode,\r\n onConfirm: handleVerificationConfirm,\r\n onReject: handleVerificationReject,\r\n localConfirmed: localVerificationConfirmed,\r\n remoteConfirmed: remoteVerificationConfirmed,\r\n bothConfirmed: bothVerificationsConfirmed\r\n })\r\n ])\r\n ]);\r\n }\r\n \r\n if (mode === 'select') {\r\n return React.createElement('div', {\r\n className: \"min-h-[calc(100vh-104px)] flex items-center justify-center p-4\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'selector',\r\n className: \"w-full max-w-4xl\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'header',\r\n className: \"text-center mb-8\"\r\n }, [\r\n React.createElement('h2', {\r\n key: 'title',\r\n className: \"text-2xl font-semibold text-primary mb-3\"\r\n }, 'Start secure communication'),\r\n React.createElement('p', {\r\n key: 'subtitle',\r\n className: \"text-secondary max-w-2xl mx-auto\"\r\n }, \"Choose a connection method for a secure channel with ECDH encryption and Perfect Forward Secrecy.\")\r\n ]),\r\n \r\n React.createElement('div', {\r\n key: 'options',\r\n className: \"flex flex-col md:flex-row items-center justify-center gap-6 max-w-3xl mx-auto\"\r\n }, [\r\n // Create Connection\r\n React.createElement('div', {\r\n key: 'create',\r\n onClick: () => setMode('create'),\r\n className: \"card-minimal rounded-xl p-6 cursor-pointer group flex-1 create\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'icon',\r\n className: \"w-12 h-12 bg-blue-500/10 border border-blue-500/20 rounded-lg flex items-center justify-center mx-auto mb-4\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-plus text-xl text-blue-400'\r\n })\r\n ]),\r\n React.createElement('h3', {\r\n key: 'title',\r\n className: \"text-lg font-semibold text-primary text-center mb-3\"\r\n }, \"Create channel\"),\r\n React.createElement('p', {\r\n key: 'description',\r\n className: \"text-secondary text-center text-sm mb-4\"\r\n }, \"Initiate a new secure connection\"),\r\n React.createElement('div', {\r\n key: 'features',\r\n className: \"space-y-2\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'f1',\r\n className: \"flex items-center text-sm text-muted\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-key accent-orange mr-2 text-xs'\r\n }),\r\n 'Generating ECDH keys'\r\n ]),\r\n React.createElement('div', {\r\n key: 'f2',\r\n className: \"flex items-center text-sm text-muted\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-shield-alt accent-orange mr-2 text-xs'\r\n }),\r\n 'Verification code'\r\n ]),\r\n React.createElement('div', {\r\n key: 'f3',\r\n className: \"flex items-center text-sm text-muted\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-sync-alt accent-purple mr-2 text-xs'\r\n }),\r\n 'PFS key rotation'\r\n ])\r\n ])\r\n ]),\r\n React.createElement('div', {\r\n key: 'divider',\r\n className: \"flex flex-row md:flex-col items-center gap-4 px-4 w-full md:w-auto\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'line-a',\r\n className: \"h-px flex-1 bg-gradient-to-r from-transparent via-zinc-700 to-transparent md:h-32 md:w-px md:flex-none md:bg-gradient-to-b\"\r\n }),\r\n React.createElement('div', {\r\n key: 'or-text',\r\n className: \"text-zinc-600 text-sm font-medium px-3\"\r\n }, \"OR\"),\r\n React.createElement('div', {\r\n key: 'line-b',\r\n className: \"h-px flex-1 bg-gradient-to-r from-transparent via-zinc-700 to-transparent md:h-32 md:w-px md:flex-none md:bg-gradient-to-b\"\r\n })\r\n ]),\r\n // Join Connection\r\n React.createElement('div', {\r\n key: 'join',\r\n onClick: () => setMode('join'),\r\n className: \"card-minimal rounded-xl p-6 cursor-pointer group flex-1 join\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'icon',\r\n className: \"w-12 h-12 bg-green-500/10 border border-green-500/20 rounded-lg flex items-center justify-center mx-auto mb-4\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-link text-xl accent-green'\r\n })\r\n ]),\r\n React.createElement('h3', {\r\n key: 'title',\r\n className: \"text-lg font-semibold text-primary text-center mb-3\"\r\n }, \"Join\"),\r\n React.createElement('p', {\r\n key: 'description',\r\n className: \"text-secondary text-center text-sm mb-4\"\r\n }, \"Connect to an existing secure channel\"),\r\n React.createElement('div', {\r\n key: 'features',\r\n className: \"space-y-2\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'f1',\r\n className: \"flex items-center text-sm text-muted\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-paste accent-green mr-2 text-xs'\r\n }),\r\n 'Paste Offer invitation'\r\n ]),\r\n React.createElement('div', {\r\n key: 'f2',\r\n className: \"flex items-center text-sm text-muted\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-check-circle accent-green mr-2 text-xs'\r\n }),\r\n 'Automatic verification'\r\n ]),\r\n React.createElement('div', {\r\n key: 'f3',\r\n className: \"flex items-center text-sm text-muted\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-sync-alt accent-purple mr-2 text-xs'\r\n }),\r\n 'PFS protection'\r\n ])\r\n ])\r\n ])\r\n ]),\r\n \r\n \r\n React.createElement(SecurityFeatures, { key: 'security-features' }),\r\n\r\n React.createElement(Testimonials, { key: 'testimonials' }),\r\n \r\n React.createElement(UniqueFeatureSlider, { key: 'unique-features-slider' }),\r\n \r\n React.createElement(DownloadApps, { key: 'download-apps' }),\r\n \r\n React.createElement(ComparisonTable, { key: 'comparison-table' }), \r\n \r\n React.createElement(Roadmap, { key: 'roadmap' }),\r\n ])\r\n ]);\r\n }\r\n \r\n if (mode === 'create') {\r\n return React.createElement('div', {\r\n className: \"min-h-[calc(100vh-104px)] flex items-center justify-center p-4\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'create-flow',\r\n className: \"w-full max-w-3xl space-y-6\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'header',\r\n className: \"text-center\"\r\n }, [\r\n React.createElement('button', {\r\n key: 'back',\r\n onClick: resetToSelect,\r\n className: \"mb-4 text-secondary hover:text-primary transition-colors flex items-center mx-auto text-sm\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-arrow-left mr-2'\r\n }),\r\n 'Back to selection'\r\n ]),\r\n React.createElement('h2', {\r\n key: 'title',\r\n className: \"text-xl font-semibold text-primary mb-2\"\r\n }, 'Creating a secure channel')\r\n ]),\r\n \r\n // Step 1\r\n !showAnswerStep && React.createElement('div', {\r\n key: 'step1',\r\n className: \"card-minimal rounded-xl p-6\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'step-header',\r\n className: \"flex items-center mb-4\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'number',\r\n className: \"step-number mr-3\"\r\n }, '1'),\r\n React.createElement('h3', {\r\n key: 'title',\r\n className: \"text-lg font-medium text-primary\"\r\n }, \"Generating ECDH keys and verification code\")\r\n ]),\r\n React.createElement('p', {\r\n key: 'description',\r\n className: \"text-secondary text-sm mb-4\"\r\n }, \"Creating cryptographically strong keys and codes to protect against attacks\"),\r\n !showOfferStep && React.createElement('button', {\r\n key: 'create-btn',\r\n onClick: onCreateOffer,\r\n disabled: connectionStatus === 'connecting',\r\n className: `w-full btn-primary text-white py-3 px-4 rounded-lg font-medium transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed`\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-shield-alt mr-2'\r\n }),\r\n 'Create secure keys'\r\n ]),\r\n \r\n showOfferStep && React.createElement('div', {\r\n key: 'offer-result',\r\n className: \"mt-6 space-y-4\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'success',\r\n className: \"p-3 bg-green-500/10 border border-green-500/20 rounded-lg\"\r\n }, [\r\n React.createElement('p', {\r\n className: \"text-green-400 text-sm font-medium flex items-center\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-check-circle mr-2'\r\n }),\r\n 'Secure invitation created! Send the code to your contact'\r\n ])\r\n ]),\r\n React.createElement('div', {\r\n key: 'offer-data',\r\n className: \"space-y-3\"\r\n }, [\r\n // Raw JSON hidden intentionally; users copy compressed string or use QR\r\n React.createElement('div', {\r\n key: 'buttons',\r\n className: \"flex gap-2\"\r\n }, [\r\n React.createElement(EnhancedCopyButton, {\r\n key: 'copy',\r\n text: (() => {\r\n try {\r\n const min = typeof offerData === 'object' ? JSON.stringify(offerData) : (offerData || '');\r\n if (typeof window.encodeBinaryToPrefixed === 'function') {\r\n return window.encodeBinaryToPrefixed(min);\r\n }\r\n if (typeof window.compressToPrefixedGzip === 'function') {\r\n return window.compressToPrefixedGzip(min);\r\n }\r\n return min;\r\n } catch { return typeof offerData === 'object' ? JSON.stringify(offerData) : (offerData || ''); }\r\n })(),\r\n className: \"flex-1 px-3 py-2 bg-orange-500/10 hover:bg-orange-500/20 text-orange-400 border border-orange-500/20 rounded text-sm font-medium\"\r\n }, 'Copy invitation code')\r\n ]),\r\n showQRCode && qrCodeUrl && React.createElement('div', {\r\n key: 'qr-container',\r\n className: \"mt-4 p-4 bg-gray-800/50 border border-gray-600/30 rounded-lg text-center\"\r\n }, [\r\n React.createElement('h4', {\r\n key: 'qr-title',\r\n className: \"text-sm font-medium text-primary mb-3\"\r\n }, 'Scan QR code to connect'),\r\n React.createElement('div', {\r\n key: 'qr-wrapper',\r\n className: \"flex justify-center\"\r\n }, [\r\n React.createElement('img', {\r\n key: 'qr-image',\r\n src: qrCodeUrl,\r\n alt: \"QR Code for secure connection\",\r\n className: \"max-w-none h-auto border border-gray-600/30 rounded w-[20rem] sm:w-[24rem] md:w-[28rem] lg:w-[32rem]\"\r\n })\r\n ]),\r\n\r\n ((qrFramesTotal || 0) >= 1) && React.createElement('div', {\r\n key: 'qr-controls-below',\r\n className: \"mt-4 flex flex-col items-center gap-2\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'frame-indicator',\r\n className: \"text-xs text-gray-300\"\r\n }, `Frame ${Math.max(1, (qrFrameIndex || 1))}/${qrFramesTotal || 1}`),\r\n React.createElement('div', {\r\n key: 'control-buttons',\r\n className: \"flex gap-1\"\r\n }, [\r\n (qrFramesTotal || 0) > 1 && React.createElement('button', {\r\n key: 'prev-frame',\r\n onClick: prevQrFrame,\r\n className: \"w-6 h-6 bg-gray-600 hover:bg-gray-500 text-white rounded text-xs flex items-center justify-center\"\r\n }, '\u25C0'),\r\n React.createElement('button', {\r\n key: 'toggle-manual',\r\n onClick: toggleQrManualMode,\r\n className: `px-2 py-1 rounded text-xs font-medium ${\r\n (qrManualMode || false)\r\n ? 'bg-blue-500 text-white' \r\n : 'bg-gray-600 text-gray-300 hover:bg-gray-500'\r\n }`\r\n }, (qrManualMode || false) ? 'Manual' : 'Auto'),\r\n (qrFramesTotal || 0) > 1 && React.createElement('button', {\r\n key: 'next-frame',\r\n onClick: nextQrFrame,\r\n className: \"w-6 h-6 bg-gray-600 hover:bg-gray-500 text-white rounded text-xs flex items-center justify-center\"\r\n }, '\u25B6')\r\n ])\r\n ]),\r\n React.createElement('p', {\r\n key: 'qr-description',\r\n className: \"text-xs text-gray-400 mt-2\"\r\n }, 'Your contact can scan this QR code to quickly join the secure session')\r\n ])\r\n ])\r\n ])\r\n ]),\r\n \r\n // Step 2 - Session Type Selection\r\n // showOfferStep && React.createElement('div', {\r\n // key: 'step2',\r\n // className: \"card-minimal rounded-xl p-6\"\r\n // }, [\r\n // React.createElement('div', {\r\n // key: 'step-header',\r\n // className: \"flex items-center mb-4\"\r\n // }, [\r\n // React.createElement('div', {\r\n // key: 'number',\r\n // className: \"w-8 h-8 bg-green-500 text-white rounded-lg flex items-center justify-center font-semibold text-sm mr-3\"\r\n // }, '2'),\r\n // React.createElement('h3', {\r\n // key: 'title',\r\n // className: \"text-lg font-medium text-primary\"\r\n // }, \"Select session type\")\r\n // ]),\r\n // React.createElement('p', {\r\n // key: 'description',\r\n // className: \"text-secondary text-sm mb-4\"\r\n // }, \"Choose a session plan or use limited demo mode for testing.\"),\r\n // React.createElement(SessionTypeSelector, {\r\n // key: 'session-selector',\r\n // onSelectType: (sessionType) => {\r\n // // Save the selected session type\r\n // setSelectedSessionType(sessionType);\r\n // console.log('\uD83C\uDFAF Session type selected:', sessionType);\r\n \r\n // // FIX: For demo sessions, we immediately call automatic activation\r\n // if (sessionType === 'demo') {\r\n // console.log('\uD83C\uDFAE Demo session selected, scheduling automatic activation...');\r\n // // Delay activation for 2 seconds to stabilize\r\n // setTimeout(() => {\r\n // if (sessionManager) {\r\n // console.log('\uD83D\uDE80 Triggering demo session activation from selection...');\r\n // handleDemoVerification();\r\n // }\r\n // }, 2000);\r\n // }\r\n \r\n // // Open a modal payment window\r\n // if (typeof window.showPaymentModal === 'function') {\r\n // window.showPaymentModal(sessionType);\r\n // } else {\r\n // // Fallback - show session information\r\n // console.log('Selected session type:', sessionType);\r\n // }\r\n // },\r\n // onCancel: resetToSelect,\r\n // sessionManager: window.sessionManager\r\n // })\r\n // ]),\r\n \r\n // Step 3 - Waiting for response\r\n showOfferStep && React.createElement('div', {\r\n key: 'step2',\r\n className: \"card-minimal rounded-xl p-6\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'step-header',\r\n className: \"flex items-center mb-4\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'number',\r\n className: \"w-8 h-8 bg-blue-500 text-white rounded-lg flex items-center justify-center font-semibold text-sm mr-3\"\r\n }, '2'),\r\n React.createElement('h3', {\r\n key: 'title',\r\n className: \"text-lg font-medium text-primary\"\r\n }, \"Waiting for the peer's response\")\r\n ]),\r\n React.createElement('p', {\r\n key: 'description',\r\n className: \"text-secondary text-sm mb-4\"\r\n }, \"Paste the encrypted invitation code from your contact.\"),\r\n React.createElement('div', {\r\n key: 'buttons',\r\n className: \"flex gap-2 mb-4\"\r\n }, [\r\n React.createElement('button', {\r\n key: 'scan-btn',\r\n onClick: () => setShowQRScannerModal(true),\r\n className: \"px-4 py-2 bg-purple-500/10 hover:bg-purple-500/20 text-purple-400 border border-purple-500/20 rounded text-sm font-medium transition-all duration-200\"\r\n }, [\r\n React.createElement('i', {\r\n key: 'icon',\r\n className: 'fas fa-qrcode mr-2'\r\n }),\r\n 'Scan QR Code'\r\n ])\r\n ]),\r\n React.createElement('textarea', {\r\n key: 'input',\r\n value: answerInput,\r\n onChange: (e) => {\r\n setAnswerInput(e.target.value);\r\n // Mark answer as created when user manually enters data\r\n if (e.target.value.trim().length > 0) {\r\n if (typeof markAnswerCreated === 'function') {\r\n markAnswerCreated();\r\n }\r\n }\r\n\r\n },\r\n rows: 6,\r\n placeholder: \"Paste the encrypted response code from your contact or scan QR code...\",\r\n className: \"w-full p-3 bg-custom-bg border border-gray-500/20 rounded-lg resize-none mb-4 text-secondary placeholder-gray-500 focus:border-orange-500/40 focus:outline-none transition-all custom-scrollbar text-sm\"\r\n }),\r\n React.createElement('button', {\r\n key: 'connect-btn',\r\n onClick: onConnect,\r\n disabled: !answerInput.trim(),\r\n className: \"w-full btn-secondary text-white py-3 px-4 rounded-lg font-medium transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-rocket mr-2'\r\n }),\r\n 'Establish connection'\r\n ])\r\n ])\r\n ])\r\n ]);\r\n }\r\n \r\n if (mode === 'join') {\r\n return React.createElement('div', {\r\n className: \"min-h-[calc(100vh-104px)] flex items-center justify-center p-4\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'join-flow',\r\n className: \"w-full max-w-3xl space-y-6\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'header',\r\n className: \"text-center\"\r\n }, [\r\n React.createElement('button', {\r\n key: 'back',\r\n onClick: resetToSelect,\r\n className: \"mb-4 text-secondary hover:text-primary transition-colors flex items-center mx-auto text-sm\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-arrow-left mr-2'\r\n }),\r\n 'Back to selection'\r\n ]),\r\n React.createElement('h2', {\r\n key: 'title',\r\n className: \"text-xl font-semibold text-primary mb-2\"\r\n }, 'Joining the secure channel')\r\n ]),\r\n \r\n (showAnswerStep ? null : React.createElement('div', {\r\n key: 'step1',\r\n className: \"card-minimal rounded-xl p-6\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'step-header',\r\n className: \"flex items-center mb-4\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'number',\r\n className: \"w-8 h-8 bg-green-500 text-white rounded-lg flex items-center justify-center font-semibold text-sm mr-3\"\r\n }, '1'),\r\n React.createElement('h3', {\r\n key: 'title',\r\n className: \"text-lg font-medium text-primary\"\r\n }, \"Paste secure invitation\")\r\n ]),\r\n React.createElement('p', {\r\n key: 'description',\r\n className: \"text-secondary text-sm mb-4\"\r\n }, \"Copy and paste the encrypted invitation code from the initiator.\"),\r\n React.createElement('textarea', {\r\n key: 'input',\r\n value: offerInput,\r\n onChange: (e) => {\r\n setOfferInput(e.target.value);\r\n if (e.target.value.trim().length > 0) {\r\n if (typeof markAnswerCreated === 'function') {\r\n markAnswerCreated();\r\n }\r\n }\r\n },\r\n rows: 8,\r\n placeholder: \"Paste the encrypted invitation code or scan QR code...\",\r\n className: \"w-full p-3 bg-custom-bg border border-gray-500/20 rounded-lg resize-none mb-4 text-secondary placeholder-gray-500 focus:border-green-500/40 focus:outline-none transition-all custom-scrollbar text-sm\"\r\n }),\r\n React.createElement('div', {\r\n key: 'buttons',\r\n className: \"flex gap-2 mb-4\"\r\n }, [\r\n React.createElement('button', {\r\n key: 'scan-btn',\r\n onClick: () => setShowQRScannerModal(true),\r\n className: \"px-4 py-2 bg-purple-500/10 hover:bg-purple-500/20 text-purple-400 border border-purple-500/20 rounded text-sm font-medium transition-all duration-200\"\r\n }, [\r\n React.createElement('i', {\r\n key: 'icon',\r\n className: 'fas fa-qrcode mr-2'\r\n }),\r\n 'Scan QR Code'\r\n ]),\r\n React.createElement('button', {\r\n key: 'process-btn',\r\n onClick: onCreateAnswer,\r\n disabled: !offerInput.trim() || connectionStatus === 'connecting',\r\n className: \"flex-1 btn-secondary text-white py-2 px-4 rounded-lg font-medium transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-cogs mr-2'\r\n }),\r\n 'Process invitation'\r\n ])\r\n ]),\r\n showQRScanner && React.createElement('div', {\r\n key: 'qr-scanner',\r\n className: \"p-4 bg-gray-800/50 border border-gray-600/30 rounded-lg text-center\"\r\n }, [\r\n React.createElement('h4', {\r\n key: 'scanner-title',\r\n className: \"text-sm font-medium text-primary mb-3\"\r\n }, 'QR Code Scanner'),\r\n React.createElement('p', {\r\n key: 'scanner-description',\r\n className: \"text-xs text-gray-400 mb-3\"\r\n }, 'Use your device camera to scan the QR code from the invitation'),\r\n React.createElement('button', {\r\n key: 'open-scanner',\r\n onClick: () => {\r\n if (typeof setShowQRScannerModal === 'function') {\r\n setShowQRScannerModal(true);\r\n } else {\r\n console.error('setShowQRScannerModal is not a function:', setShowQRScannerModal);\r\n }\r\n },\r\n className: \"w-full px-4 py-3 bg-purple-600 hover:bg-purple-500 text-white rounded-lg font-medium transition-all duration-200 mb-3\"\r\n }, [\r\n React.createElement('i', {\r\n key: 'camera-icon',\r\n className: 'fas fa-camera mr-2'\r\n }),\r\n 'Open Camera Scanner'\r\n ]),\r\n React.createElement('button', {\r\n key: 'test-qr',\r\n onClick: async () => {\r\n console.log('Creating test QR code...');\r\n if (window.generateQRCode) {\r\n const testData = '{\"type\":\"test\",\"message\":\"Hello QR Scanner!\"}';\r\n const qrUrl = await window.generateQRCode(testData);\r\n console.log('Test QR code generated:', qrUrl);\r\n const newWindow = window.open();\r\n newWindow.document.write(``);\r\n }\r\n },\r\n className: \"px-3 py-1 bg-green-600/20 hover:bg-green-600/30 text-green-300 border border-green-500/20 rounded text-xs font-medium transition-all duration-200 mr-2\"\r\n }, 'Test QR'),\r\n React.createElement('button', {\r\n key: 'close-scanner',\r\n onClick: () => setShowQRScanner(false),\r\n className: \"px-3 py-1 bg-gray-600/20 hover:bg-gray-600/30 text-gray-300 border border-gray-500/20 rounded text-xs font-medium transition-all duration-200\"\r\n }, 'Close Scanner')\r\n ])\r\n ])),\r\n \r\n // Step 2\r\n showAnswerStep && React.createElement('div', {\r\n key: 'step2',\r\n className: \"card-minimal rounded-xl p-6\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'step-header',\r\n className: \"flex items-center mb-4\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'number',\r\n className: \"step-number mr-3\"\r\n }, '2'),\r\n React.createElement('h3', {\r\n key: 'title',\r\n className: \"text-lg font-medium text-primary\"\r\n }, \"Sending a secure response\")\r\n ]),\r\n React.createElement('div', {\r\n key: 'success',\r\n className: \"p-3 bg-green-500/10 border border-green-500/20 rounded-lg mb-4\"\r\n }, [\r\n React.createElement('p', {\r\n className: \"text-green-400 text-sm font-medium flex items-center\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-check-circle mr-2'\r\n }),\r\n 'Secure response created! Send this code to the initiator:'\r\n ])\r\n ]),\r\n React.createElement('div', {\r\n key: 'answer-data',\r\n className: \"space-y-3 mb-4\"\r\n }, [\r\n // Raw JSON hidden intentionally; users copy compressed string or use QR\r\n React.createElement(EnhancedCopyButton, {\r\n key: 'copy',\r\n text: (() => {\r\n try {\r\n const min = typeof answerData === 'object' ? JSON.stringify(answerData) : (answerData || '');\r\n if (typeof window.encodeBinaryToPrefixed === 'function') {\r\n return window.encodeBinaryToPrefixed(min);\r\n }\r\n if (typeof window.compressToPrefixedGzip === 'function') {\r\n return window.compressToPrefixedGzip(min);\r\n }\r\n return min;\r\n } catch { return typeof answerData === 'object' ? JSON.stringify(answerData) : (answerData || ''); }\r\n })(),\r\n className: \"w-full px-3 py-2 bg-green-500/10 hover:bg-green-500/20 text-green-400 border border-green-500/20 rounded text-sm font-medium\"\r\n }, 'Copy response code')\r\n ]),\r\n // QR Code section for answer\r\n qrCodeUrl && React.createElement('div', {\r\n key: 'qr-container',\r\n className: \"mt-4 p-4 bg-gray-800/50 border border-gray-600/30 rounded-lg text-center\"\r\n }, [\r\n React.createElement('h4', {\r\n key: 'qr-title',\r\n className: \"text-sm font-medium text-primary mb-3\"\r\n }, 'Scan QR code to complete connection'),\r\n React.createElement('div', {\r\n key: 'qr-wrapper',\r\n className: \"flex justify-center\"\r\n }, [\r\n React.createElement('img', {\r\n key: 'qr-image',\r\n src: qrCodeUrl,\r\n alt: \"QR Code for secure response\",\r\n className: \"max-w-none h-auto border border-gray-600/30 rounded w-[20rem] sm:w-[24rem] md:w-[28rem] lg:w-[32rem]\"\r\n })\r\n ]),\r\n\r\n ((qrFramesTotal || 0) >= 1) && React.createElement('div', {\r\n key: 'qr-controls-below',\r\n className: \"mt-4 flex flex-col items-center gap-2\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'frame-indicator',\r\n className: \"text-xs text-gray-300\"\r\n }, `Frame ${Math.max(1, (qrFrameIndex || 1))}/${qrFramesTotal || 1}`),\r\n React.createElement('div', {\r\n key: 'control-buttons',\r\n className: \"flex gap-1\"\r\n }, [\r\n (qrFramesTotal || 0) > 1 && React.createElement('button', {\r\n key: 'prev-frame',\r\n onClick: prevQrFrame,\r\n className: \"w-6 h-6 bg-gray-600 hover:bg-gray-500 text-white rounded text-xs flex items-center justify-center\"\r\n }, '\u25C0'),\r\n React.createElement('button', {\r\n key: 'toggle-manual',\r\n onClick: toggleQrManualMode,\r\n className: `px-2 py-1 rounded text-xs font-medium ${\r\n qrManualMode \r\n ? 'bg-blue-500 text-white' \r\n : 'bg-gray-600 text-gray-300 hover:bg-gray-500'\r\n }`\r\n }, qrManualMode ? 'Manual' : 'Auto'),\r\n (qrFramesTotal || 0) > 1 && React.createElement('button', {\r\n key: 'next-frame',\r\n onClick: nextQrFrame,\r\n className: \"w-6 h-6 bg-gray-600 hover:bg-gray-500 text-white rounded text-xs flex items-center justify-center\"\r\n }, '\u25B6')\r\n ])\r\n ]),\r\n React.createElement('p', {\r\n key: 'qr-description',\r\n className: \"text-xs text-gray-400 mt-2\"\r\n }, 'The initiator can scan this QR code to complete the secure connection')\r\n ]),\r\n React.createElement('div', {\r\n key: 'info',\r\n className: \"p-3 bg-purple-500/10 border border-purple-500/20 rounded-lg\"\r\n }, [\r\n React.createElement('p', {\r\n className: \"text-purple-400 text-sm flex items-center justify-center\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-shield-alt mr-2'\r\n }),\r\n 'The connection will be established with verification'\r\n ])\r\n ])\r\n ])\r\n ])\r\n ]);\r\n }\r\n };\r\n \r\n // Global scroll function - defined outside components to ensure availability\r\n const createScrollToBottomFunction = (chatMessagesRef) => {\r\n return () => {\r\n if (chatMessagesRef && chatMessagesRef.current) {\r\n const scrollAttempt = () => {\r\n if (chatMessagesRef.current) {\r\n chatMessagesRef.current.scrollTo({\r\n top: chatMessagesRef.current.scrollHeight,\r\n behavior: 'smooth'\r\n });\r\n }\r\n };\r\n scrollAttempt();\r\n \r\n setTimeout(scrollAttempt, 50);\r\n setTimeout(scrollAttempt, 150);\r\n setTimeout(scrollAttempt, 300);\r\n \r\n requestAnimationFrame(() => {\r\n setTimeout(scrollAttempt, 100);\r\n });\r\n }\r\n };\r\n };\r\n \r\n const EnhancedChatInterface = ({\r\n messages,\r\n messageInput,\r\n setMessageInput,\r\n onSendMessage,\r\n onDisconnect,\r\n keyFingerprint,\r\n isVerified,\r\n chatMessagesRef,\r\n scrollToBottom,\r\n webrtcManager\r\n }) => {\r\n const [showScrollButton, setShowScrollButton] = React.useState(false);\r\n const [showFileTransfer, setShowFileTransfer] = React.useState(false);\r\n\r\n React.useEffect(() => {\r\n if (chatMessagesRef.current && messages.length > 0) {\r\n const { scrollTop, scrollHeight, clientHeight } = chatMessagesRef.current;\r\n const isNearBottom = scrollHeight - scrollTop - clientHeight < 100;\r\n if (isNearBottom) {\r\n const smoothScroll = () => {\r\n if (chatMessagesRef.current) {\r\n chatMessagesRef.current.scrollTo({\r\n top: chatMessagesRef.current.scrollHeight,\r\n behavior: 'smooth'\r\n });\r\n }\r\n };\r\n smoothScroll();\r\n setTimeout(smoothScroll, 50);\r\n setTimeout(smoothScroll, 150);\r\n }\r\n }\r\n }, [messages, chatMessagesRef]);\r\n \r\n // \u041E\u0431\u0440\u0430\u0431\u043E\u0442\u0447\u0438\u043A \u0441\u043A\u0440\u043E\u043B\u043B\u0430\r\n const handleScroll = () => {\r\n if (chatMessagesRef.current) {\r\n const { scrollTop, scrollHeight, clientHeight } = chatMessagesRef.current;\r\n const isNearBottom = scrollHeight - scrollTop - clientHeight < 100;\r\n setShowScrollButton(!isNearBottom);\r\n }\r\n };\r\n \r\n // \u041F\u0440\u043E\u043A\u0440\u0443\u0442\u043A\u0430 \u0432\u043D\u0438\u0437 \u043F\u043E \u043A\u043D\u043E\u043F\u043A\u0435\r\n const handleScrollToBottom = () => {\r\n console.log('\uD83D\uDD0D handleScrollToBottom called, scrollToBottom type:', typeof scrollToBottom);\r\n if (typeof scrollToBottom === 'function') {\r\n scrollToBottom();\r\n setShowScrollButton(false);\r\n } else {\r\n console.error('scrollToBottom is not a function:', scrollToBottom);\r\n // Fallback: direct scroll\r\n if (chatMessagesRef.current) {\r\n chatMessagesRef.current.scrollTo({\r\n top: chatMessagesRef.current.scrollHeight,\r\n behavior: 'smooth'\r\n });\r\n }\r\n setShowScrollButton(false);\r\n }\r\n };\r\n\r\n const handleKeyPress = (e) => {\r\n if (e.key === 'Enter' && !e.shiftKey) {\r\n e.preventDefault();\r\n onSendMessage();\r\n }\r\n };\r\n\r\n const isFileTransferReady = () => {\r\n if (!webrtcManager) return false;\r\n \r\n const connected = webrtcManager.isConnected ? webrtcManager.isConnected() : false;\r\n const verified = webrtcManager.isVerified || false;\r\n const hasDataChannel = webrtcManager.dataChannel && webrtcManager.dataChannel.readyState === 'open';\r\n \r\n return connected && verified && hasDataChannel;\r\n };\r\n \r\n // \u0412\u043E\u0437\u0432\u0440\u0430\u0442 JSX \u0447\u0435\u0440\u0435\u0437 React.createElement\r\n return React.createElement(\r\n 'div',\r\n {\r\n className: \"chat-container flex flex-col\",\r\n style: { backgroundColor: '#272827', height: 'calc(100vh - 64px)' }\r\n },\r\n [\r\n // \u041E\u0431\u043B\u0430\u0441\u0442\u044C \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0439\r\n React.createElement(\r\n 'div',\r\n { className: \"flex-1 flex flex-col overflow-hidden\" },\r\n React.createElement(\r\n 'div',\r\n { className: \"flex-1 max-w-4xl mx-auto w-full p-4 overflow-hidden\" },\r\n React.createElement(\r\n 'div',\r\n {\r\n ref: chatMessagesRef,\r\n onScroll: handleScroll,\r\n className: \"h-full overflow-y-auto space-y-3 hide-scrollbar pr-2 scroll-smooth\"\r\n },\r\n messages.length === 0 ?\r\n React.createElement(\r\n 'div',\r\n { className: \"flex items-center justify-center h-full\" },\r\n React.createElement(\r\n 'div',\r\n { className: \"text-center max-w-md\" },\r\n [\r\n React.createElement(\r\n 'div',\r\n { className: \"w-16 h-16 bg-green-500/10 border border-green-500/20 rounded-xl flex items-center justify-center mx-auto mb-4\" },\r\n React.createElement(\r\n 'svg',\r\n { className: \"w-8 h-8 text-green-500\", fill: \"none\", stroke: \"currentColor\", viewBox: \"0 0 24 24\" },\r\n React.createElement('path', {\r\n strokeLinecap: \"round\",\r\n strokeLinejoin: \"round\",\r\n strokeWidth: 2,\r\n d: \"M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z\"\r\n })\r\n )\r\n ),\r\n React.createElement('h3', { className: \"text-lg font-medium text-gray-300 mb-2\" }, \"Secure channel is ready!\"),\r\n React.createElement('p', { className: \"text-gray-400 text-sm mb-4\" }, \"All messages are protected by modern cryptographic algorithms\"),\r\n React.createElement(\r\n 'div',\r\n { className: \"text-left space-y-2\" },\r\n [\r\n ['End-to-end encryption', 'M5 13l4 4L19 7'],\r\n ['Protection against replay attacks', 'M5 13l4 4L19 7'],\r\n ['Integrity verification', 'M5 13l4 4L19 7'],\r\n ['Perfect Forward Secrecy', 'M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15']\r\n ].map(([text, d], i) =>\r\n React.createElement(\r\n 'div',\r\n { key: `f${i}`, className: \"flex items-center text-sm text-gray-400\" },\r\n [\r\n React.createElement(\r\n 'svg',\r\n {\r\n className: `w-4 h-4 mr-3 ${i === 3 ? 'text-purple-500' : 'text-green-500'}`,\r\n fill: \"none\",\r\n stroke: \"currentColor\",\r\n viewBox: \"0 0 24 24\"\r\n },\r\n React.createElement('path', {\r\n strokeLinecap: \"round\",\r\n strokeLinejoin: \"round\",\r\n strokeWidth: 2,\r\n d: d\r\n })\r\n ),\r\n text\r\n ]\r\n )\r\n )\r\n )\r\n ]\r\n )\r\n ) :\r\n messages.map((msg) =>\r\n React.createElement(EnhancedChatMessage, {\r\n key: msg.id,\r\n message: msg.message,\r\n type: msg.type,\r\n timestamp: msg.timestamp\r\n })\r\n )\r\n )\r\n )\r\n ),\r\n \r\n // \u041A\u043D\u043E\u043F\u043A\u0430 \u043F\u0440\u043E\u043A\u0440\u0443\u0442\u043A\u0438 \u0432\u043D\u0438\u0437\r\n showScrollButton &&\r\n React.createElement(\r\n 'button',\r\n {\r\n onClick: handleScrollToBottom,\r\n className: \"fixed right-6 w-12 h-12 bg-green-500/20 hover:bg-green-500/30 border border-green-500/30 text-green-400 rounded-full flex items-center justify-center transition-all duration-200 shadow-lg z-50\",\r\n style: { bottom: '160px' }\r\n },\r\n React.createElement(\r\n 'svg',\r\n { className: \"w-6 h-6\", fill: \"none\", stroke: \"currentColor\", viewBox: \"0 0 24 24\" },\r\n React.createElement('path', {\r\n strokeLinecap: \"round\",\r\n strokeLinejoin: \"round\",\r\n strokeWidth: 2,\r\n d: \"M19 14l-7 7m0 0l-7-7m7 7V3\"\r\n })\r\n )\r\n ),\r\n\r\n React.createElement(\r\n 'div',\r\n {\r\n className: \"flex-shrink-0 border-t border-gray-500/10\",\r\n style: { backgroundColor: '#272827' }\r\n },\r\n React.createElement(\r\n 'div',\r\n { className: \"max-w-4xl mx-auto px-4\" },\r\n [\r\n React.createElement(\r\n 'button',\r\n {\r\n onClick: () => setShowFileTransfer(!showFileTransfer),\r\n className: `flex items-center text-sm text-gray-400 hover:text-gray-300 transition-colors py-4 ${showFileTransfer ? 'mb-4' : ''}`\r\n },\r\n [\r\n React.createElement(\r\n 'svg',\r\n {\r\n className: `w-4 h-4 mr-2 transform transition-transform ${showFileTransfer ? 'rotate-180' : ''}`,\r\n fill: \"none\",\r\n stroke: \"currentColor\",\r\n viewBox: \"0 0 24 24\"\r\n },\r\n showFileTransfer ?\r\n React.createElement('path', {\r\n strokeLinecap: \"round\",\r\n strokeLinejoin: \"round\",\r\n strokeWidth: 2,\r\n d: \"M5 15l7-7 7 7\"\r\n }) :\r\n React.createElement('path', {\r\n strokeLinecap: \"round\",\r\n strokeLinejoin: \"round\",\r\n strokeWidth: 2,\r\n d: \"M15.172 7l-6.586 6.586a2 2 0 102.828 2.828l6.414-6.586a4 4 0 00-5.656-5.656l-6.415 6.585a6 6 0 108.486 8.486L20.5 13\"\r\n })\r\n ),\r\n showFileTransfer ? 'Hide file transfer' : 'Send files'\r\n ]\r\n ),\r\n showFileTransfer &&\r\n React.createElement(window.FileTransferComponent || (() => \r\n React.createElement('div', {\r\n className: \"p-4 text-center text-red-400\"\r\n }, 'FileTransferComponent not loaded')\r\n ), {\r\n webrtcManager: webrtcManager,\r\n isConnected: isFileTransferReady()\r\n })\r\n ]\r\n )\r\n ),\r\n\r\n React.createElement(\r\n 'div',\r\n { className: \"border-t border-gray-500/10\" },\r\n React.createElement(\r\n 'div',\r\n { className: \"max-w-4xl mx-auto p-4\" },\r\n React.createElement(\r\n 'div',\r\n { className: \"flex items-stretch space-x-3\" },\r\n [\r\n React.createElement(\r\n 'div',\r\n { className: \"flex-1 relative\" },\r\n [\r\n React.createElement('textarea', {\r\n value: messageInput,\r\n onChange: (e) => setMessageInput(e.target.value),\r\n onKeyDown: handleKeyPress,\r\n placeholder: \"Enter message to encrypt...\",\r\n rows: 2,\r\n maxLength: 2000,\r\n style: { backgroundColor: '#272827' },\r\n className: \"w-full p-3 border border-gray-600 rounded-lg resize-none text-gray-300 placeholder-gray-500 focus:border-green-500/40 focus:outline-none transition-all custom-scrollbar text-sm\"\r\n }),\r\n React.createElement(\r\n 'div',\r\n { className: \"absolute bottom-2 right-3 flex items-center space-x-2 text-xs text-gray-400\" },\r\n [\r\n React.createElement('span', null, `${messageInput.length}/2000`),\r\n React.createElement('span', null, \"\u2022 Enter to send\")\r\n ]\r\n )\r\n ]\r\n ),\r\n React.createElement(\r\n 'button',\r\n {\r\n onClick: onSendMessage,\r\n disabled: !messageInput.trim(),\r\n className: \"bg-green-400/20 text-green-400 p-3 rounded-lg transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center min-h-[72px]\"\r\n },\r\n React.createElement(\r\n 'svg',\r\n { className: \"w-6 h-6\", fill: \"none\", stroke: \"currentColor\", viewBox: \"0 0 24 24\" },\r\n React.createElement('path', {\r\n strokeLinecap: \"round\",\r\n strokeLinejoin: \"round\",\r\n strokeWidth: 2,\r\n d: \"M12 19l9 2-9-18-9 18 9-2zm0 0v-8\"\r\n })\r\n )\r\n )\r\n ]\r\n )\r\n )\r\n )\r\n ]\r\n );\r\n };\r\n \r\n \r\n // Main Enhanced Application Component\r\n const EnhancedSecureP2PChat = () => {\r\n\r\n const [messages, setMessages] = React.useState([]);\r\n const [connectionStatus, setConnectionStatus] = React.useState('disconnected');\r\n \r\n // Moved scrollToBottom logic to be available globally\r\n const [messageInput, setMessageInput] = React.useState('');\r\n const [offerData, setOfferData] = React.useState('');\r\n const [answerData, setAnswerData] = React.useState('');\r\n const [offerInput, setOfferInput] = React.useState('');\r\n const [answerInput, setAnswerInput] = React.useState('');\r\n const [keyFingerprint, setKeyFingerprint] = React.useState('');\r\n const [verificationCode, setVerificationCode] = React.useState('');\r\n const [showOfferStep, setShowOfferStep] = React.useState(false);\r\n const [showAnswerStep, setShowAnswerStep] = React.useState(false);\r\n const [showVerification, setShowVerification] = React.useState(false);\r\n const [showQRCode, setShowQRCode] = React.useState(false);\r\n const [qrCodeUrl, setQrCodeUrl] = React.useState('');\r\n const [showQRScanner, setShowQRScanner] = React.useState(false);\r\n const [showQRScannerModal, setShowQRScannerModal] = React.useState(false);\r\n const [isVerified, setIsVerified] = React.useState(false);\r\n const [securityLevel, setSecurityLevel] = React.useState(null);\r\n \r\n // Mutual verification states\r\n const [localVerificationConfirmed, setLocalVerificationConfirmed] = React.useState(false);\r\n const [remoteVerificationConfirmed, setRemoteVerificationConfirmed] = React.useState(false);\r\n const [bothVerificationsConfirmed, setBothVerificationsConfirmed] = React.useState(false);\r\n \r\n // PAKE password states removed - using SAS verification instead\r\n \r\n // Session state - all security features enabled by default\r\n const [sessionTimeLeft, setSessionTimeLeft] = React.useState(0);\r\n const [pendingSession, setPendingSession] = React.useState(null);\r\n \r\n // All security features are enabled by default - no payment required\r\n \r\n \r\n \r\n // ============================================\r\n // CENTRALIZED CONNECTION STATE MANAGEMENT\r\n // ============================================\r\n \r\n const [connectionState, setConnectionState] = React.useState({\r\n status: 'disconnected',\r\n hasActiveAnswer: false,\r\n answerCreatedAt: null,\r\n isUserInitiatedDisconnect: false\r\n });\r\n \r\n // Centralized connection state handler\r\n const updateConnectionState = (newState, options = {}) => {\r\n const { preserveAnswer = false, isUserAction = false } = options;\r\n \r\n setConnectionState(prev => ({\r\n ...prev,\r\n ...newState,\r\n isUserInitiatedDisconnect: isUserAction,\r\n hasActiveAnswer: preserveAnswer ? prev.hasActiveAnswer : false,\r\n answerCreatedAt: preserveAnswer ? prev.answerCreatedAt : null\r\n }));\r\n };\r\n \r\n // Check if we should preserve answer data\r\n const shouldPreserveAnswerData = () => {\r\n const now = Date.now();\r\n const answerAge = now - (connectionState.answerCreatedAt || 0);\r\n const maxPreserveTime = 300000;\r\n \r\n\r\n const hasAnswerData = (answerData && answerData.trim().length > 0) || \r\n (answerInput && answerInput.trim().length > 0);\r\n\r\n const hasAnswerQR = qrCodeUrl && qrCodeUrl.trim().length > 0;\r\n \r\n const shouldPreserve = (connectionState.hasActiveAnswer && \r\n answerAge < maxPreserveTime && \r\n !connectionState.isUserInitiatedDisconnect) ||\r\n (hasAnswerData && answerAge < maxPreserveTime && \r\n !connectionState.isUserInitiatedDisconnect) ||\r\n (hasAnswerQR && answerAge < maxPreserveTime && \r\n !connectionState.isUserInitiatedDisconnect);\r\n \r\n \r\n return shouldPreserve;\r\n };\r\n \r\n // Mark answer as created\r\n const markAnswerCreated = () => {\r\n updateConnectionState({\r\n hasActiveAnswer: true,\r\n answerCreatedAt: Date.now()\r\n });\r\n };\r\n \r\n // Global functions for cleanup\r\n React.useEffect(() => {\r\n window.forceCleanup = () => {\r\n handleClearData();\r\n if (webrtcManagerRef.current) {\r\n webrtcManagerRef.current.disconnect();\r\n }\r\n };\r\n\r\n window.clearLogs = () => {\r\n if (typeof console.clear === 'function') {\r\n console.clear();\r\n }\r\n };\r\n \r\n return () => {\r\n delete window.forceCleanup;\r\n delete window.clearLogs;\r\n };\r\n }, []);\r\n \r\n const webrtcManagerRef = React.useRef(null);\r\n // Expose for modules/UI that run outside this closure (e.g., inline handlers)\r\n // Safe because it's a ref object and we maintain it centrally here\r\n window.webrtcManagerRef = webrtcManagerRef;\r\n \r\n const addMessageWithAutoScroll = React.useCallback((message, type) => {\r\n const newMessage = {\r\n message,\r\n type,\r\n id: Date.now() + Math.random(),\r\n timestamp: Date.now()\r\n };\r\n \r\n setMessages(prev => {\r\n const updated = [...prev, newMessage];\r\n \r\n setTimeout(() => {\r\n if (chatMessagesRef?.current) {\r\n const container = chatMessagesRef.current;\r\n try {\r\n const { scrollTop, scrollHeight, clientHeight } = container;\r\n const isNearBottom = scrollHeight - scrollTop - clientHeight < 100;\r\n \r\n if (isNearBottom || prev.length === 0) {\r\n requestAnimationFrame(() => {\r\n if (container && container.scrollTo) {\r\n container.scrollTo({\r\n top: container.scrollHeight,\r\n behavior: 'smooth'\r\n });\r\n }\r\n });\r\n }\r\n } catch (error) {\r\n console.warn('Scroll error:', error);\r\n container.scrollTop = container.scrollHeight;\r\n }\r\n }\r\n }, 50);\r\n \r\n return updated;\r\n });\r\n }, []);\r\n \r\n // Update security level based on real verification\r\n const updateSecurityLevel = React.useCallback(async () => {\r\n if (window.isUpdatingSecurity) {\r\n return;\r\n }\r\n \r\n window.isUpdatingSecurity = true;\r\n \r\n try {\r\n if (webrtcManagerRef.current) {\r\n // All security features are enabled by default - always show MAXIMUM level\r\n setSecurityLevel({\r\n level: 'MAXIMUM',\r\n score: 100,\r\n color: 'green',\r\n details: 'All security features enabled by default',\r\n passedChecks: 10,\r\n totalChecks: 10,\r\n isRealData: true\r\n });\r\n \r\n if (window.DEBUG_MODE) {\r\n const currentLevel = webrtcManagerRef.current.ecdhKeyPair && webrtcManagerRef.current.ecdsaKeyPair \r\n ? await webrtcManagerRef.current.calculateSecurityLevel()\r\n : {\r\n level: 'MAXIMUM',\r\n score: 100,\r\n sessionType: 'premium',\r\n passedChecks: 10,\r\n totalChecks: 10\r\n };\r\n }\r\n }\r\n } catch (error) {\r\n console.error('Failed to update security level:', error);\r\n setSecurityLevel({\r\n level: 'ERROR',\r\n score: 0,\r\n color: 'red',\r\n details: 'Verification failed'\r\n });\r\n } finally {\r\n setTimeout(() => {\r\n window.isUpdatingSecurity = false;\r\n }, 2000);\r\n }\r\n }, []);\r\n \r\n // Session time ticker - unlimited sessions\r\n React.useEffect(() => {\r\n const timer = setInterval(() => {\r\n // Sessions are unlimited - no time restrictions\r\n setSessionTimeLeft(0);\r\n }, 1000);\r\n return () => clearInterval(timer);\r\n }, []);\r\n \r\n // Sessions are unlimited - no expiration handler needed\r\n \r\n // All security features are enabled by default - no demo sessions needed\r\n const chatMessagesRef = React.useRef(null);\r\n \r\n // Create scroll function using global helper\r\n const scrollToBottom = createScrollToBottomFunction(chatMessagesRef);\r\n \r\n // Auto-scroll when messages change\r\n React.useEffect(() => {\r\n if (messages.length > 0 && chatMessagesRef.current) {\r\n scrollToBottom();\r\n setTimeout(scrollToBottom, 50);\r\n setTimeout(scrollToBottom, 150);\r\n }\r\n }, [messages]);\r\n \r\n // PAKE password functions removed - using SAS verification instead\r\n \r\n React.useEffect(() => {\r\n // Prevent multiple initializations\r\n if (webrtcManagerRef.current) {\r\n console.log('\u26A0\uFE0F WebRTC Manager already initialized, skipping...');\r\n return;\r\n }\r\n \r\n const handleMessage = (message, type) => {\r\n if (typeof message === 'string' && message.trim().startsWith('{')) {\r\n try {\r\n const parsedMessage = JSON.parse(message);\r\n const blockedTypes = [\r\n 'file_transfer_start',\r\n 'file_transfer_response',\r\n 'file_chunk',\r\n 'chunk_confirmation',\r\n 'file_transfer_complete',\r\n 'file_transfer_error',\r\n 'heartbeat',\r\n 'verification',\r\n 'verification_response',\r\n 'verification_confirmed',\r\n 'verification_both_confirmed',\r\n 'peer_disconnect',\r\n 'key_rotation_signal',\r\n 'key_rotation_ready',\r\n 'security_upgrade'\r\n ];\r\n if (parsedMessage.type && blockedTypes.includes(parsedMessage.type)) {\r\n console.log(`Blocked system/file message from chat: ${parsedMessage.type}`);\r\n return; \r\n }\r\n } catch (parseError) {\r\n\r\n }\r\n }\r\n \r\n addMessageWithAutoScroll(message, type);\r\n };\r\n \r\n const handleStatusChange = (status) => {\r\n setConnectionStatus(status);\r\n \r\n if (status === 'connected') {\r\n document.dispatchEvent(new CustomEvent('new-connection'));\r\n \r\n // \u041D\u0435 \u0441\u043A\u0440\u044B\u0432\u0430\u0435\u043C \u0432\u0435\u0440\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u044E \u043F\u0440\u0438 'connected' - \u0442\u043E\u043B\u044C\u043A\u043E \u043F\u0440\u0438 'verified'\r\n // setIsVerified(true);\r\n // setShowVerification(false);\r\n if (!window.isUpdatingSecurity) {\r\n updateSecurityLevel().catch(console.error);\r\n }\r\n } else if (status === 'verifying') {\r\n setShowVerification(true);\r\n if (!window.isUpdatingSecurity) {\r\n updateSecurityLevel().catch(console.error);\r\n }\r\n } else if (status === 'verified') {\r\n setIsVerified(true);\r\n setShowVerification(false);\r\n setBothVerificationsConfirmed(true);\r\n setConnectionStatus('connected');\r\n // Force immediate update of isVerified state\r\n setTimeout(() => {\r\n setIsVerified(true);\r\n }, 0);\r\n if (!window.isUpdatingSecurity) {\r\n updateSecurityLevel().catch(console.error);\r\n }\r\n } else if (status === 'connecting') {\r\n if (!window.isUpdatingSecurity) {\r\n updateSecurityLevel().catch(console.error);\r\n }\r\n } else if (status === 'disconnected') {\r\n updateConnectionState({ status: 'disconnected' });\r\n setConnectionStatus('disconnected');\r\n\r\n if (shouldPreserveAnswerData()) {\r\n setIsVerified(false);\r\n setShowVerification(false);\r\n return;\r\n }\r\n\r\n setIsVerified(false);\r\n setShowVerification(false);\r\n \r\n // Dispatch disconnected event for SessionTimer\r\n document.dispatchEvent(new CustomEvent('disconnected'));\r\n \r\n // Clear verification states\r\n setLocalVerificationConfirmed(false);\r\n setRemoteVerificationConfirmed(false);\r\n setBothVerificationsConfirmed(false);\r\n \r\n // Clear connection data\r\n setOfferData(null);\r\n setAnswerData(null);\r\n setOfferInput('');\r\n setAnswerInput('');\r\n setShowOfferStep(false);\r\n setShowAnswerStep(false);\r\n setKeyFingerprint('');\r\n setVerificationCode('');\r\n setSecurityLevel(null);\r\n \r\n // Reset session and timer\r\n setSessionTimeLeft(0);\r\n \r\n // Return to main page after a short delay\r\n setTimeout(() => {\r\n setConnectionStatus('disconnected');\r\n setShowVerification(false);\r\n \r\n setOfferData(null);\r\n setAnswerData(null);\r\n setOfferInput('');\r\n setAnswerInput('');\r\n setShowOfferStep(false);\r\n setShowAnswerStep(false);\r\n setMessages([]);\r\n }, 1000);\r\n\r\n } else if (status === 'peer_disconnected') {\r\n setSessionTimeLeft(0);\r\n \r\n document.dispatchEvent(new CustomEvent('peer-disconnect'));\r\n \r\n // A short delay before clearing to display the status\r\n setTimeout(() => {\r\n setKeyFingerprint('');\r\n setVerificationCode('');\r\n setSecurityLevel(null);\r\n setIsVerified(false);\r\n setShowVerification(false);\r\n setConnectionStatus('disconnected');\r\n \r\n // Clear verification states\r\n setLocalVerificationConfirmed(false);\r\n setRemoteVerificationConfirmed(false);\r\n setBothVerificationsConfirmed(false);\r\n \r\n // Clear connection data\r\n setOfferData(null);\r\n setAnswerData(null);\r\n setOfferInput('');\r\n setAnswerInput('');\r\n setShowOfferStep(false);\r\n setShowAnswerStep(false);\r\n setMessages([]);\r\n \r\n\r\n if (typeof console.clear === 'function') {\r\n console.clear();\r\n }\r\n\r\n }, 2000);\r\n }\r\n };\r\n \r\n const handleKeyExchange = (fingerprint) => {\r\n if (fingerprint === '') {\r\n setKeyFingerprint('');\r\n } else {\r\n setKeyFingerprint(fingerprint);\r\n }\r\n };\r\n \r\n const handleVerificationRequired = (code) => {\r\n if (code === '') {\r\n setVerificationCode('');\r\n setShowVerification(false);\r\n } else {\r\n setVerificationCode(code);\r\n setShowVerification(true);\r\n }\r\n };\r\n \r\n const handleVerificationStateChange = (state) => {\r\n setLocalVerificationConfirmed(state.localConfirmed);\r\n setRemoteVerificationConfirmed(state.remoteConfirmed);\r\n setBothVerificationsConfirmed(state.bothConfirmed);\r\n };\r\n \r\n // Callback for handling response errors\r\n const handleAnswerError = (errorType, errorMessage) => {\r\n if (errorType === 'replay_attack') {\r\n // Reset the session upon replay attack\r\n setSessionTimeLeft(0);\r\n setPendingSession(null);\r\n \r\n addMessageWithAutoScroll('\uD83D\uDCA1 Data is outdated. Please create a new invitation or use a current response code.', 'system');\r\n \r\n if (typeof console.clear === 'function') {\r\n console.clear();\r\n }\r\n } else if (errorType === 'security_violation') {\r\n // Reset the session upon security breach\r\n setSessionTimeLeft(0);\r\n setPendingSession(null);\r\n \r\n addMessageWithAutoScroll(` Security breach: ${errorMessage}`, 'system');\r\n \r\n if (typeof console.clear === 'function') {\r\n console.clear();\r\n }\r\n }\r\n };\r\n \r\n \r\n if (typeof console.clear === 'function') {\r\n console.clear();\r\n }\r\n \r\n webrtcManagerRef.current = new EnhancedSecureWebRTCManager(\r\n handleMessage, \r\n handleStatusChange, \r\n handleKeyExchange,\r\n handleVerificationRequired,\r\n handleAnswerError,\r\n handleVerificationStateChange\r\n );\r\n \r\n handleMessage(' SecureBit.chat Enhanced Security Edition v4.2.12 - 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');\r\n \r\n const handleBeforeUnload = (event) => {\r\n if (event.type === 'beforeunload' && !isTabSwitching) {\r\n \r\n if (webrtcManagerRef.current && webrtcManagerRef.current.isConnected()) {\r\n try {\r\n webrtcManagerRef.current.sendSystemMessage({\r\n type: 'peer_disconnect',\r\n reason: 'user_disconnect',\r\n timestamp: Date.now()\r\n });\r\n } catch (error) {\r\n }\r\n \r\n setTimeout(() => {\r\n if (webrtcManagerRef.current) {\r\n webrtcManagerRef.current.disconnect();\r\n }\r\n }, 100);\r\n } else if (webrtcManagerRef.current) {\r\n webrtcManagerRef.current.disconnect();\r\n }\r\n } else if (isTabSwitching) {\r\n event.preventDefault();\r\n event.returnValue = '';\r\n }\r\n };\r\n \r\n window.addEventListener('beforeunload', handleBeforeUnload);\r\n \r\n let isTabSwitching = false;\r\n let tabSwitchTimeout = null;\r\n \r\n const handleVisibilityChange = () => {\r\n if (document.visibilityState === 'hidden') {\r\n isTabSwitching = true;\r\n \r\n if (tabSwitchTimeout) {\r\n clearTimeout(tabSwitchTimeout);\r\n }\r\n \r\n tabSwitchTimeout = setTimeout(() => {\r\n isTabSwitching = false;\r\n }, 5000); \r\n \r\n } else if (document.visibilityState === 'visible') {\r\n isTabSwitching = false;\r\n \r\n if (tabSwitchTimeout) {\r\n clearTimeout(tabSwitchTimeout);\r\n tabSwitchTimeout = null;\r\n }\r\n }\r\n };\r\n \r\n document.addEventListener('visibilitychange', handleVisibilityChange);\r\n \r\n // Setup file transfer callbacks\r\n if (webrtcManagerRef.current) {\r\n webrtcManagerRef.current.setFileTransferCallbacks(\r\n // Progress callback\r\n (progress) => {\r\n console.log('File progress:', progress);\r\n },\r\n \r\n // File received callback\r\n (fileData) => {\r\n const sizeMb = Math.max(1, Math.round((fileData.fileSize || 0) / (1024 * 1024)));\r\n const downloadMessage = React.createElement('div', {\r\n className: 'flex items-center space-x-2'\r\n }, [\r\n React.createElement('span', { key: 'label' }, ` File received: ${fileData.fileName} (${sizeMb} MB)`),\r\n React.createElement('button', {\r\n key: 'btn',\r\n className: 'px-3 py-1 rounded bg-blue-600 hover:bg-blue-700 text-white text-xs',\r\n onClick: async () => {\r\n try {\r\n const url = await fileData.getObjectURL();\r\n const a = document.createElement('a');\r\n a.href = url;\r\n a.download = fileData.fileName;\r\n a.click();\r\n setTimeout(() => fileData.revokeObjectURL(url), 15000);\r\n } catch (e) {\r\n console.error('Download failed:', e);\r\n addMessageWithAutoScroll(` File upload error: ${String(e?.message || e)}`, 'system');\r\n }\r\n }\r\n }, 'Download')\r\n ]);\r\n \r\n addMessageWithAutoScroll(downloadMessage, 'system');\r\n },\r\n \r\n // Error callback\r\n (error) => {\r\n console.error('File transfer error:', error);\r\n \r\n if (error.includes('Connection not ready')) {\r\n addMessageWithAutoScroll(` File transfer error: connection not ready. Try again later.`, 'system');\r\n } else if (error.includes('File too large')) {\r\n addMessageWithAutoScroll(` File is too big. Maximum size: 100 MB`, 'system');\r\n } else {\r\n addMessageWithAutoScroll(` File transfer error: ${error}`, 'system');\r\n }\r\n }\r\n );\r\n }\r\n \r\n return () => {\r\n window.removeEventListener('beforeunload', handleBeforeUnload);\r\n document.removeEventListener('visibilitychange', handleVisibilityChange);\r\n \r\n if (tabSwitchTimeout) {\r\n clearTimeout(tabSwitchTimeout);\r\n tabSwitchTimeout = null;\r\n }\r\n \r\n if (webrtcManagerRef.current) {\r\n webrtcManagerRef.current.disconnect();\r\n webrtcManagerRef.current = null;\r\n }\r\n };\r\n }, []); // Empty dependency array to run only once\r\n \r\n // All security features are enabled by default - no session purchase needed\r\n \r\n const compressOfferData = (offerData) => {\r\n try {\r\n // Parse the offer data if it's a string\r\n const offer = typeof offerData === 'string' ? JSON.parse(offerData) : offerData;\r\n \r\n // Create a minimal version with only the most essential data\r\n const minimalOffer = {\r\n type: offer.type,\r\n version: offer.version,\r\n timestamp: offer.timestamp,\r\n sessionId: offer.sessionId,\r\n connectionId: offer.connectionId,\r\n verificationCode: offer.verificationCode,\r\n salt: offer.salt,\r\n // Use only key fingerprints instead of full keys\r\n keyFingerprints: offer.keyFingerprints,\r\n // Add a reference to get full data\r\n fullDataAvailable: true,\r\n compressionLevel: 'minimal'\r\n };\r\n \r\n return JSON.stringify(minimalOffer);\r\n } catch (error) {\r\n console.error('Error compressing offer data:', error);\r\n return offerData; // Return original if compression fails\r\n }\r\n };\r\n\r\n const createQRReference = (offerData) => {\r\n try {\r\n // Create a unique reference ID for this offer\r\n const referenceId = `offer_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\r\n \r\n // Store the full offer data in localStorage with the reference ID\r\n localStorage.setItem(`qr_offer_${referenceId}`, JSON.stringify(offerData));\r\n \r\n // Create a minimal QR code with just the reference\r\n const qrReference = {\r\n type: 'secure_offer_reference',\r\n referenceId: referenceId,\r\n timestamp: Date.now(),\r\n message: 'Scan this QR code and use the reference ID to get full offer data'\r\n };\r\n \r\n return JSON.stringify(qrReference);\r\n } catch (error) {\r\n console.error('Error creating QR reference:', error);\r\n return null;\r\n }\r\n };\r\n\r\n const createTemplateOffer = (offer) => {\r\n // Minimal template to keep QR within single image capacity\r\n const templateOffer = {\r\n type: 'enhanced_secure_offer_template',\r\n version: '4.0',\r\n sessionId: offer.sessionId,\r\n connectionId: offer.connectionId,\r\n verificationCode: offer.verificationCode,\r\n timestamp: offer.timestamp,\r\n // Avoid bulky fields (SDP, raw keys); keep only fingerprints and essentials\r\n keyFingerprints: offer.keyFingerprints,\r\n // Keep concise auth hints (omit large nonces)\r\n authChallenge: offer?.authChallenge?.challenge,\r\n // Optionally include a compact capability hint if small\r\n capabilities: Array.isArray(offer.capabilities) && offer.capabilities.length <= 5\r\n ? offer.capabilities\r\n : undefined\r\n };\r\n \r\n return templateOffer;\r\n };\r\n\r\n // Conservative QR payload limits (characters). Adjust per error correction level.\r\n const MAX_QR_LEN = 800; // for JSON/plain/gzip\r\n const BIN_MAX_QR_LEN = 400; // stricter for SB1:bin to improve scan reliability\r\n const [qrFramesTotal, setQrFramesTotal] = React.useState(0);\r\n const [qrFrameIndex, setQrFrameIndex] = React.useState(0);\r\n const [qrManualMode, setQrManualMode] = React.useState(false);\r\n\r\n // Animated QR state (for multi-chunk COSE)\r\n const qrAnimationRef = React.useRef({ timer: null, chunks: [], idx: 0, active: false });\r\n const stopQrAnimation = () => {\r\n try { if (qrAnimationRef.current.timer) { clearInterval(qrAnimationRef.current.timer); } } catch {}\r\n qrAnimationRef.current = { timer: null, chunks: [], idx: 0, active: false };\r\n setQrFrameIndex(0);\r\n setQrFramesTotal(0);\r\n setQrManualMode(false);\r\n };\r\n\r\n // Render frame at current index (no index mutation)\r\n const renderCurrent = async () => {\r\n const { chunks, idx } = qrAnimationRef.current || {};\r\n if (!chunks || !chunks.length) return;\r\n const current = chunks[idx % chunks.length];\r\n try {\r\n const isDesktop = (typeof window !== 'undefined') && ((window.innerWidth || 0) >= 1024);\r\n const QR_SIZE = isDesktop ? 720 : 512;\r\n const url = await (window.generateQRCode ? window.generateQRCode(current, { errorCorrectionLevel: 'M', margin: 2, size: QR_SIZE }) : Promise.resolve(''));\r\n if (url) setQrCodeUrl(url);\r\n } catch (e) {\r\n console.warn('Animated QR render error (current):', e);\r\n }\r\n setQrFrameIndex(((qrAnimationRef.current?.idx || 0) % (qrAnimationRef.current?.chunks?.length || 1)) + 1);\r\n };\r\n\r\n // Render current frame, then advance index by 1\r\n const renderAndAdvance = async () => {\r\n await renderCurrent();\r\n const len = qrAnimationRef.current?.chunks?.length || 0;\r\n if (len > 0) {\r\n const nextIdx = ((qrAnimationRef.current?.idx || 0) + 1) % len;\r\n qrAnimationRef.current.idx = nextIdx;\r\n setQrFrameIndex(nextIdx + 1);\r\n }\r\n };\r\n\r\n const toggleQrManualMode = () => {\r\n const newManualMode = !qrManualMode;\r\n setQrManualMode(newManualMode);\r\n \r\n if (newManualMode) {\r\n\r\n if (qrAnimationRef.current.timer) {\r\n clearInterval(qrAnimationRef.current.timer);\r\n qrAnimationRef.current.timer = null;\r\n }\r\n console.log('QR Manual mode enabled - auto-scroll stopped');\r\n } else {\r\n if (qrAnimationRef.current.chunks.length > 1) {\r\n const intervalMs = 3000;\r\n qrAnimationRef.current.active = true;\r\n clearInterval(qrAnimationRef.current.timer);\r\n qrAnimationRef.current.timer = setInterval(renderAndAdvance, intervalMs);\r\n }\r\n console.log('QR Manual mode disabled - auto-scroll resumed');\r\n }\r\n };\r\n\r\n const nextQrFrame = async () => {\r\n console.log('\uD83C\uDFAE nextQrFrame called, qrFramesTotal:', qrFramesTotal, 'qrAnimationRef.current:', qrAnimationRef.current);\r\n if (qrAnimationRef.current.chunks.length > 1) {\r\n const nextIdx = (qrAnimationRef.current.idx + 1) % qrAnimationRef.current.chunks.length;\r\n qrAnimationRef.current.idx = nextIdx;\r\n setQrFrameIndex(nextIdx + 1);\r\n console.log('\uD83C\uDFAE Next frame index:', nextIdx + 1);\r\n // Ensure auto-advance timer runs in manual mode too\r\n try { clearInterval(qrAnimationRef.current.timer); } catch {}\r\n qrAnimationRef.current.timer = null;\r\n await renderCurrent();\r\n // If not in manual mode, restart auto timer\r\n if (!qrManualMode && qrAnimationRef.current.chunks.length > 1) {\r\n const intervalMs = 3000;\r\n qrAnimationRef.current.active = true;\r\n qrAnimationRef.current.timer = setInterval(renderAndAdvance, intervalMs);\r\n } else {\r\n qrAnimationRef.current.active = false;\r\n }\r\n } else {\r\n console.log('\uD83C\uDFAE No multiple frames to navigate');\r\n }\r\n };\r\n\r\n const prevQrFrame = async () => {\r\n console.log('\uD83C\uDFAE prevQrFrame called, qrFramesTotal:', qrFramesTotal, 'qrAnimationRef.current:', qrAnimationRef.current);\r\n if (qrAnimationRef.current.chunks.length > 1) {\r\n const prevIdx = (qrAnimationRef.current.idx - 1 + qrAnimationRef.current.chunks.length) % qrAnimationRef.current.chunks.length;\r\n qrAnimationRef.current.idx = prevIdx;\r\n setQrFrameIndex(prevIdx + 1);\r\n console.log('\uD83C\uDFAE Previous frame index:', prevIdx + 1);\r\n try { clearInterval(qrAnimationRef.current.timer); } catch {}\r\n qrAnimationRef.current.timer = null;\r\n await renderCurrent();\r\n if (!qrManualMode && qrAnimationRef.current.chunks.length > 1) {\r\n const intervalMs = 3000;\r\n qrAnimationRef.current.active = true;\r\n qrAnimationRef.current.timer = setInterval(renderAndAdvance, intervalMs);\r\n } else {\r\n qrAnimationRef.current.active = false;\r\n }\r\n } else {\r\n console.log('\uD83C\uDFAE No multiple frames to navigate');\r\n }\r\n };\r\n\r\n // Buffer for assembling scanned COSE chunks\r\n const qrChunksBufferRef = React.useRef({ id: null, total: 0, seen: new Set(), items: [] });\r\n\r\n const generateQRCode = async (data) => {\r\n try {\r\n const originalSize = typeof data === 'string' ? data.length : JSON.stringify(data).length;\r\n // Small payload: \u043F\u0440\u044F\u043C\u043E\u0439 JSON \u0432 \u043E\u0434\u0438\u043D QR (\u0431\u0435\u0437 \u0441\u0436\u0430\u0442\u0438\u044F, \u0431\u0435\u0437 \u043E\u0431\u0451\u0440\u0442\u043E\u043A)\r\n const payload = typeof data === 'string' ? data : JSON.stringify(data);\r\n const isDesktop = (typeof window !== 'undefined') && ((window.innerWidth || 0) >= 1024);\r\n const QR_SIZE = isDesktop ? 720 : 512;\r\n if (payload.length <= MAX_QR_LEN) {\r\n if (!window.generateQRCode) throw new Error('QR code generator unavailable');\r\n try { if (qrAnimationRef.current && qrAnimationRef.current.timer) { clearInterval(qrAnimationRef.current.timer); } } catch {}\r\n qrAnimationRef.current = { timer: null, chunks: [], idx: 0, active: false };\r\n setQrFrameIndex(0);\r\n setQrFramesTotal(0);\r\n setQrManualMode(false);\r\n const qrDataUrl = await window.generateQRCode(payload, { errorCorrectionLevel: 'M', size: QR_SIZE, margin: 2 });\r\n setQrCodeUrl(qrDataUrl);\r\n setQrFramesTotal(1);\r\n setQrFrameIndex(1);\r\n return;\r\n }\r\n\r\n try { if (qrAnimationRef.current && qrAnimationRef.current.timer) { clearInterval(qrAnimationRef.current.timer); } } catch {}\r\n qrAnimationRef.current = { timer: null, chunks: [], idx: 0, active: false };\r\n setQrFrameIndex(0);\r\n setQrFramesTotal(0);\r\n setQrManualMode(false);\r\n const id = `raw_${Date.now()}_${Math.random().toString(36).slice(2)}`;\r\n\r\n const TARGET_CHUNKS = 10;\r\n const FRAME_MAX = Math.max(200, Math.floor(payload.length / TARGET_CHUNKS));\r\n const total = Math.ceil(payload.length / FRAME_MAX);\r\n const rawChunks = [];\r\n for (let i = 0; i < total; i++) {\r\n const seq = i + 1;\r\n const part = payload.slice(i * FRAME_MAX, (i + 1) * FRAME_MAX);\r\n rawChunks.push(JSON.stringify({ hdr: { v: 1, id, seq, total, rt: 'raw' }, body: part }));\r\n }\r\n if (!window.generateQRCode) throw new Error('QR code generator unavailable');\r\n if (rawChunks.length === 1) {\r\n const url = await window.generateQRCode(rawChunks[0], { errorCorrectionLevel: 'M', margin: 2, size: QR_SIZE });\r\n setQrCodeUrl(url);\r\n setQrFramesTotal(1);\r\n setQrFrameIndex(1);\r\n return;\r\n }\r\n qrAnimationRef.current.chunks = rawChunks;\r\n qrAnimationRef.current.idx = 0;\r\n qrAnimationRef.current.active = true;\r\n setQrFramesTotal(rawChunks.length);\r\n setQrFrameIndex(1);\r\n const EC_OPTS = { errorCorrectionLevel: 'M', margin: 2, size: QR_SIZE };\r\n await renderNext();\r\n\r\n if (!qrManualMode) {\r\n const intervalMs = 4000; // 4 seconds per frame for better readability\r\n qrAnimationRef.current.active = true;\r\n qrAnimationRef.current.timer = setInterval(renderAndAdvance, intervalMs);\r\n }\r\n return;\r\n } catch (error) {\r\n console.error('QR code generation failed:', error);\r\n setMessages(prev => [...prev, {\r\n message: ` QR code generation failed: ${error.message}`,\r\n type: 'error'\r\n }]);\r\n }\r\n };\r\n\r\n const reconstructFromTemplate = (templateData) => {\r\n // Reconstruct full offer from template\r\n const fullOffer = {\r\n type: \"enhanced_secure_offer\",\r\n version: templateData.version,\r\n timestamp: templateData.timestamp,\r\n sessionId: templateData.sessionId,\r\n connectionId: templateData.connectionId,\r\n verificationCode: templateData.verificationCode,\r\n salt: templateData.salt,\r\n sdp: templateData.sdp,\r\n keyFingerprints: templateData.keyFingerprints,\r\n capabilities: templateData.capabilities,\r\n \r\n // Reconstruct ECDH key object\r\n ecdhPublicKey: {\r\n keyType: \"ECDH\",\r\n keyData: templateData.ecdhKeyData,\r\n timestamp: templateData.timestamp - 1000, // Approximate\r\n version: templateData.version,\r\n signature: templateData.ecdhSignature\r\n },\r\n \r\n // Reconstruct ECDSA key object\r\n ecdsaPublicKey: {\r\n keyType: \"ECDSA\",\r\n keyData: templateData.ecdsaKeyData,\r\n timestamp: templateData.timestamp - 999, // Approximate\r\n version: templateData.version,\r\n signature: templateData.ecdsaSignature\r\n },\r\n \r\n // Reconstruct auth challenge\r\n authChallenge: {\r\n challenge: templateData.authChallenge,\r\n timestamp: templateData.timestamp,\r\n nonce: templateData.authNonce,\r\n version: templateData.version\r\n },\r\n \r\n // Generate security level (can be recalculated)\r\n securityLevel: {\r\n level: \"CRITICAL\",\r\n score: 20,\r\n color: \"red\",\r\n verificationResults: {\r\n encryption: { passed: false, details: \"Encryption not working\", points: 0 },\r\n keyExchange: { passed: true, details: \"Simple key exchange verified\", points: 15 },\r\n messageIntegrity: { passed: false, details: \"Message integrity failed\", points: 0 },\r\n rateLimiting: { passed: true, details: \"Rate limiting active\", points: 5 },\r\n ecdsa: { passed: false, details: \"Enhanced session required - feature not available\", points: 0 },\r\n metadataProtection: { passed: false, details: \"Enhanced session required - feature not available\", points: 0 },\r\n pfs: { passed: false, details: \"Enhanced session required - feature not available\", points: 0 },\r\n nestedEncryption: { passed: false, details: \"Enhanced session required - feature not available\", points: 0 },\r\n packetPadding: { passed: false, details: \"Enhanced session required - feature not available\", points: 0 },\r\n advancedFeatures: { passed: false, details: \"Premium session required - feature not available\", points: 0 }\r\n },\r\n timestamp: templateData.timestamp,\r\n details: \"Real verification: 20/100 security checks passed (2/4 available)\",\r\n isRealData: true,\r\n passedChecks: 2,\r\n totalChecks: 4,\r\n sessionType: \"demo\",\r\n maxPossibleScore: 50\r\n }\r\n };\r\n \r\n return fullOffer;\r\n };\r\n\r\n const handleQRScan = async (scannedData) => {\r\n try {\r\n // Prefer binary (CBOR) decode, else gzip JSON, else raw JSON\r\n let parsedData;\r\n if (typeof window.decodeAnyPayload === 'function') {\r\n const any = window.decodeAnyPayload(scannedData);\r\n if (typeof any === 'string') {\r\n parsedData = JSON.parse(any);\r\n } else {\r\n parsedData = any; // object from binary\r\n }\r\n } else {\r\n const maybeDecompressed = (typeof window.decompressIfNeeded === 'function') ? window.decompressIfNeeded(scannedData) : scannedData;\r\n parsedData = JSON.parse(maybeDecompressed);\r\n }\r\n \r\n // QR with hdr/body: COSE or RAW/BIN animated frames\r\n if (parsedData.hdr && parsedData.body) {\r\n const { hdr } = parsedData;\r\n // Initialize/rotate buffer by id\r\n if (!qrChunksBufferRef.current.id || qrChunksBufferRef.current.id !== hdr.id) {\r\n qrChunksBufferRef.current = { id: hdr.id, total: hdr.total || 1, seen: new Set(), items: [], lastUpdateMs: Date.now() };\r\n try {\r\n document.dispatchEvent(new CustomEvent('qr-scan-progress', { detail: { id: hdr.id, seq: 0, total: hdr.total || 1 } }));\r\n } catch {}\r\n }\r\n // Deduplicate & record\r\n if (!qrChunksBufferRef.current.seen.has(hdr.seq)) {\r\n qrChunksBufferRef.current.seen.add(hdr.seq);\r\n qrChunksBufferRef.current.items.push(scannedData);\r\n qrChunksBufferRef.current.lastUpdateMs = Date.now();\r\n }\r\n // Emit progress based on unique frames captured\r\n try {\r\n const uniqueCount = qrChunksBufferRef.current.seen.size;\r\n document.dispatchEvent(new CustomEvent('qr-scan-progress', { detail: { id: hdr.id, seq: uniqueCount, total: qrChunksBufferRef.current.total || hdr.total || 0 } }));\r\n } catch {}\r\n const isComplete = qrChunksBufferRef.current.seen.size >= (qrChunksBufferRef.current.total || 1);\r\n if (!isComplete) {\r\n // Explicitly keep scanner open\r\n return Promise.resolve(false);\r\n }\r\n // Completed: decide RAW vs BIN vs COSE\r\n if (hdr.rt === 'raw') {\r\n try {\r\n // Sort by seq and concatenate bodies\r\n const parts = qrChunksBufferRef.current.items\r\n .map(s => JSON.parse(s))\r\n .sort((a, b) => (a.hdr.seq || 0) - (b.hdr.seq || 0))\r\n .map(p => p.body || '');\r\n const fullText = parts.join('');\r\n const payloadObj = JSON.parse(fullText);\r\n if (showOfferStep) {\r\n setAnswerInput(JSON.stringify(payloadObj, null, 2));\r\n } else {\r\n setOfferInput(JSON.stringify(payloadObj, null, 2));\r\n }\r\n setMessages(prev => [...prev, { message: 'All frames captured. RAW payload reconstructed.', type: 'success' }]);\r\n try { document.dispatchEvent(new CustomEvent('qr-scan-complete', { detail: { id: hdr.id } })); } catch {}\r\n // Close scanner from caller by returning true\r\n qrChunksBufferRef.current = { id: null, total: 0, seen: new Set(), items: [] };\r\n setShowQRScannerModal(false);\r\n return Promise.resolve(true);\r\n } catch (e) {\r\n console.warn('RAW multi-frame reconstruction failed:', e);\r\n return Promise.resolve(false);\r\n }\r\n } else if (hdr.rt === 'bin') {\r\n try {\r\n const parts = qrChunksBufferRef.current.items\r\n .map(s => JSON.parse(s))\r\n .sort((a, b) => (a.hdr.seq || 0) - (b.hdr.seq || 0))\r\n .map(p => p.body || '');\r\n const fullText = parts.join(''); // SB1:bin:...\r\n let payloadObj;\r\n if (typeof window.decodeAnyPayload === 'function') {\r\n const any = window.decodeAnyPayload(fullText);\r\n payloadObj = (typeof any === 'string') ? JSON.parse(any) : any;\r\n } else {\r\n payloadObj = JSON.parse(fullText);\r\n }\r\n if (showOfferStep) {\r\n setAnswerInput(JSON.stringify(payloadObj, null, 2));\r\n } else {\r\n setOfferInput(JSON.stringify(payloadObj, null, 2));\r\n }\r\n setMessages(prev => [...prev, { message: 'All frames captured. BIN payload reconstructed.', type: 'success' }]);\r\n try { document.dispatchEvent(new CustomEvent('qr-scan-complete', { detail: { id: hdr.id } })); } catch {}\r\n qrChunksBufferRef.current = { id: null, total: 0, seen: new Set(), items: [] };\r\n setShowQRScannerModal(false);\r\n return Promise.resolve(true);\r\n } catch (e) {\r\n console.warn('BIN multi-frame reconstruction failed:', e);\r\n return Promise.resolve(false);\r\n }\r\n } else if (window.receiveAndProcess) {\r\n try {\r\n const results = await window.receiveAndProcess(qrChunksBufferRef.current.items);\r\n if (results.length > 0) {\r\n const { payloadObj } = results[0];\r\n if (showOfferStep) {\r\n setAnswerInput(JSON.stringify(payloadObj, null, 2));\r\n } else {\r\n setOfferInput(JSON.stringify(payloadObj, null, 2));\r\n }\r\n setMessages(prev => [...prev, { message: 'All frames captured. COSE payload reconstructed.', type: 'success' }]);\r\n try { document.dispatchEvent(new CustomEvent('qr-scan-complete', { detail: { id: hdr.id } })); } catch {}\r\n qrChunksBufferRef.current = { id: null, total: 0, seen: new Set(), items: [] };\r\n setShowQRScannerModal(false);\r\n return Promise.resolve(true);\r\n }\r\n } catch (e) {\r\n console.warn('COSE multi-chunk processing failed:', e);\r\n }\r\n return Promise.resolve(false);\r\n } else {\r\n return Promise.resolve(false);\r\n }\r\n }\r\n \r\n // Check if this is a template-based QR code\r\n if (parsedData.type === 'enhanced_secure_offer_template') {\r\n console.log('QR scan: Template-based offer detected, reconstructing...');\r\n const fullOffer = reconstructFromTemplate(parsedData);\r\n \r\n // Determine which input to populate based on current mode\r\n if (showOfferStep) {\r\n // In \"Waiting for peer's response\" mode - populate answerInput\r\n setAnswerInput(JSON.stringify(fullOffer, null, 2));\r\n console.log('\uD83D\uDCF1 Template data populated to answerInput (waiting for response mode)');\r\n } else {\r\n // In \"Paste secure invitation\" mode - populate offerInput\r\n setOfferInput(JSON.stringify(fullOffer, null, 2));\r\n console.log('\uD83D\uDCF1 Template data populated to offerInput (paste invitation mode)');\r\n }\r\n setMessages(prev => [...prev, {\r\n message: '\uD83D\uDCF1 QR code scanned successfully! Full offer reconstructed from template.',\r\n type: 'success'\r\n }]);\r\n setShowQRScannerModal(false); // Close QR scanner modal\r\n return true;\r\n }\r\n // Check if this is a reference-based QR code\r\n else if (parsedData.type === 'secure_offer_reference' && parsedData.referenceId) {\r\n // Try to get the full offer data from localStorage\r\n const fullOfferData = localStorage.getItem(`qr_offer_${parsedData.referenceId}`);\r\n if (fullOfferData) {\r\n const fullOffer = JSON.parse(fullOfferData);\r\n // Determine which input to populate based on current mode\r\n if (showOfferStep) {\r\n // In \"Waiting for peer's response\" mode - populate answerInput\r\n setAnswerInput(JSON.stringify(fullOffer, null, 2));\r\n } else {\r\n // In \"Paste secure invitation\" mode - populate offerInput\r\n setOfferInput(JSON.stringify(fullOffer, null, 2));\r\n }\r\n setMessages(prev => [...prev, {\r\n message: '\uD83D\uDCF1 QR code scanned successfully! Full offer data retrieved.',\r\n type: 'success'\r\n }]);\r\n setShowQRScannerModal(false); // Close QR scanner modal\r\n return true;\r\n } else {\r\n setMessages(prev => [...prev, {\r\n message: 'QR code reference found but full data not available. Please use copy/paste.',\r\n type: 'error'\r\n }]);\r\n return false;\r\n }\r\n } else {\r\n // If payload was compressed, it's already decompressed above; keep legacy warning only when clearly incomplete\r\n if (!parsedData.sdp && parsedData.type === 'enhanced_secure_offer') {\r\n setMessages(prev => [...prev, {\r\n message: 'Compressed QR may omit SDP for brevity. Use copy/paste if connection fails.',\r\n type: 'warning'\r\n }]);\r\n }\r\n \r\n // Determine which input to populate based on current mode\r\n if (showOfferStep) {\r\n // In \"Waiting for peer's response\" mode - populate answerInput\r\n console.log('QR scan: Populating answerInput with:', parsedData);\r\n setAnswerInput(JSON.stringify(parsedData, null, 2));\r\n } else {\r\n // In \"Paste secure invitation\" mode - populate offerInput\r\n console.log('QR scan: Populating offerInput with:', parsedData);\r\n setOfferInput(JSON.stringify(parsedData, null, 2));\r\n }\r\n setMessages(prev => [...prev, {\r\n message: '\uD83D\uDCF1 QR code scanned successfully!',\r\n type: 'success'\r\n }]);\r\n setShowQRScannerModal(false);\r\n return true;\r\n }\r\n } catch (error) {\r\n // If not JSON, use as plain text\r\n if (showOfferStep) {\r\n // In \"Waiting for peer's response\" mode - populate answerInput\r\n setAnswerInput(scannedData);\r\n } else {\r\n // In \"Paste secure invitation\" mode - populate offerInput\r\n setOfferInput(scannedData);\r\n }\r\n setMessages(prev => [...prev, {\r\n message: '\uD83D\uDCF1 QR code scanned successfully!',\r\n type: 'success'\r\n }]);\r\n setShowQRScannerModal(false);\r\n return true;\r\n }\r\n };\r\n \r\n const handleCreateOffer = async () => {\r\n try {\r\n // All security features are enabled by default\r\n \r\n setOfferData('');\r\n setShowOfferStep(false);\r\n setShowQRCode(false);\r\n setQrCodeUrl('');\r\n \r\n const offer = await webrtcManagerRef.current.createSecureOffer();\r\n \r\n // Store offer data directly (no encryption needed with SAS)\r\n setOfferData(offer);\r\n setShowOfferStep(true);\r\n \r\n // Do not auto-generate single QR; prepare animated binary frames when user opens QR\r\n const offerString = typeof offer === 'object' ? JSON.stringify(offer) : offer;\r\n try {\r\n if (typeof window.encodeBinaryToPrefixed === 'function') {\r\n const bin = window.encodeBinaryToPrefixed(offerString);\r\n // Precompute frames to be ready instantly on show\r\n const id = `bin_${Date.now()}_${Math.random().toString(36).slice(2)}`;\r\n const TARGET_CHUNKS = 10;\r\n let FRAME_MAX = Math.max(200, Math.floor(bin.length / TARGET_CHUNKS));\r\n if (FRAME_MAX <= 0) FRAME_MAX = 200;\r\n let total = Math.ceil(bin.length / FRAME_MAX);\r\n if (total < 2) { total = 2; FRAME_MAX = Math.ceil(bin.length / 2) || 1; }\r\n const chunks = [];\r\n for (let i = 0; i < total; i++) {\r\n const seq = i + 1;\r\n const part = bin.slice(i * FRAME_MAX, (i + 1) * FRAME_MAX);\r\n chunks.push(JSON.stringify({ hdr: { v: 1, id, seq, total, rt: 'bin' }, body: part }));\r\n }\r\n // Seed first frame and start auto-advance immediately\r\n const isDesktop = (typeof window !== 'undefined') && ((window.innerWidth || 0) >= 1024);\r\n const QR_SIZE = isDesktop ? 720 : 512;\r\n if (window.generateQRCode && chunks.length > 0) {\r\n const firstUrl = await window.generateQRCode(chunks[0], { errorCorrectionLevel: 'M', size: QR_SIZE, margin: 2 });\r\n if (firstUrl) setQrCodeUrl(firstUrl);\r\n }\r\n // Store precomputed chunks to ref, ready for animation\r\n try { if (qrAnimationRef.current && qrAnimationRef.current.timer) { clearInterval(qrAnimationRef.current.timer); } } catch {}\r\n qrAnimationRef.current = { timer: null, chunks, idx: 0, active: true };\r\n setQrFramesTotal(chunks.length);\r\n setQrFrameIndex(1);\r\n setQrManualMode(false);\r\n // Start auto-advance loop for Offer immediately\r\n const intervalMs = 3000;\r\n qrAnimationRef.current.timer = setInterval(renderAndAdvance, intervalMs);\r\n // Show QR immediately for Offer flow\r\n try { setShowQRCode(true); } catch {}\r\n }\r\n } catch (e) {\r\n console.warn('Offer QR precompute failed:', e);\r\n }\r\n \r\n const existingMessages = messages.filter(m => \r\n m.type === 'system' && \r\n (m.message.includes('Secure invitation created') || m.message.includes('Send the encrypted code'))\r\n );\r\n \r\n if (existingMessages.length === 0) {\r\n setMessages(prev => [...prev, { \r\n message: 'Secure invitation created and encrypted!', \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n \r\n setMessages(prev => [...prev, { \r\n message: '\uD83D\uDCE4 Send the invitation code to your interlocutor via a secure channel (voice call, SMS, etc.)..', \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n \r\n }\r\n \r\n if (!window.isUpdatingSecurity) {\r\n updateSecurityLevel().catch(console.error);\r\n }\r\n } catch (error) {\r\n setMessages(prev => [...prev, { \r\n message: `Error creating invitation: ${error.message}`, \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n }\r\n };\r\n \r\n const handleCreateAnswer = async () => {\r\n try {\r\n \r\n if (!offerInput.trim()) {\r\n setMessages(prev => [...prev, { \r\n message: 'You need to insert the invitation code from your interlocutor.', \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n return;\r\n }\r\n \r\n try {\r\n setMessages(prev => [...prev, { \r\n message: 'Processing the secure invitation...', \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n \r\n let offer;\r\n try {\r\n // Prefer binary decode first, then gzip JSON\r\n if (typeof window.decodeAnyPayload === 'function') {\r\n const any = window.decodeAnyPayload(offerInput.trim());\r\n offer = (typeof any === 'string') ? JSON.parse(any) : any;\r\n } else {\r\n const rawText = (typeof window.decompressIfNeeded === 'function') ? window.decompressIfNeeded(offerInput.trim()) : offerInput.trim();\r\n offer = JSON.parse(rawText);\r\n }\r\n } catch (parseError) {\r\n throw new Error(`Invalid invitation format: ${parseError.message}`);\r\n }\r\n \r\n if (!offer || typeof offer !== 'object') {\r\n throw new Error('The invitation must be an object');\r\n }\r\n \r\n // Support both compact and legacy offer formats\r\n const isValidOfferType = (offer.t === 'offer') || (offer.type === 'enhanced_secure_offer');\r\n if (!isValidOfferType) {\r\n throw new Error('Invalid invitation type. Expected offer or enhanced_secure_offer');\r\n }\r\n\r\n const answer = await webrtcManagerRef.current.createSecureAnswer(offer);\r\n \r\n // Store answer data directly (no encryption needed with SAS)\r\n setAnswerData(answer);\r\n setShowAnswerStep(true);\r\n \r\n // Answer QR: precompute binary frames and start animation immediately\r\n const answerString = typeof answer === 'object' ? JSON.stringify(answer) : answer;\r\n try {\r\n if (typeof window.encodeBinaryToPrefixed === 'function') {\r\n const bin = window.encodeBinaryToPrefixed(answerString);\r\n const id = `ans_${Date.now()}_${Math.random().toString(36).slice(2)}`;\r\n const TARGET_CHUNKS = 10;\r\n let FRAME_MAX = Math.max(200, Math.floor(bin.length / TARGET_CHUNKS));\r\n if (FRAME_MAX <= 0) FRAME_MAX = 200;\r\n let total = Math.ceil(bin.length / FRAME_MAX);\r\n if (total < 2) { total = 2; FRAME_MAX = Math.ceil(bin.length / 2) || 1; }\r\n const chunks = [];\r\n for (let i = 0; i < total; i++) {\r\n const seq = i + 1;\r\n const part = bin.slice(i * FRAME_MAX, (i + 1) * FRAME_MAX);\r\n chunks.push(JSON.stringify({ hdr: { v: 1, id, seq, total, rt: 'bin' }, body: part }));\r\n }\r\n const isDesktop = (typeof window !== 'undefined') && ((window.innerWidth || 0) >= 1024);\r\n const QR_SIZE = isDesktop ? 720 : 512;\r\n if (window.generateQRCode && chunks.length > 0) {\r\n const firstUrl = await window.generateQRCode(chunks[0], { errorCorrectionLevel: 'M', size: QR_SIZE, margin: 2 });\r\n if (firstUrl) setQrCodeUrl(firstUrl);\r\n }\r\n try { if (qrAnimationRef.current && qrAnimationRef.current.timer) { clearInterval(qrAnimationRef.current.timer); } } catch {}\r\n qrAnimationRef.current = { timer: null, chunks, idx: 0, active: true };\r\n setQrFramesTotal(chunks.length);\r\n setQrFrameIndex(1);\r\n setQrManualMode(false);\r\n const intervalMs = 3000;\r\n qrAnimationRef.current.timer = setInterval(renderAndAdvance, intervalMs);\r\n try { setShowQRCode(true); } catch {}\r\n } else {\r\n // Fallback: single QR compressed or plain\r\n let url = '';\r\n if (typeof window.generateCompressedQRCode === 'function') {\r\n url = await window.generateCompressedQRCode(answerString);\r\n } else {\r\n url = await generateQRCode(answerString);\r\n }\r\n if (url) setQrCodeUrl(url);\r\n try { setShowQRCode(true); } catch {}\r\n }\r\n } catch (e) {\r\n console.warn('Answer QR generation failed:', e);\r\n }\r\n \r\n // Mark answer as created for state management\r\n if (e.target.value.trim().length > 0) {\r\n if (typeof markAnswerCreated === 'function') {\r\n markAnswerCreated();\r\n }\r\n }\r\n\r\n \r\n const existingResponseMessages = messages.filter(m => \r\n m.type === 'system' && \r\n (m.message.includes('Secure response created') || m.message.includes('Send the response'))\r\n );\r\n \r\n if (existingResponseMessages.length === 0) {\r\n setMessages(prev => [...prev, { \r\n message: 'Secure response created!', \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n \r\n setMessages(prev => [...prev, { \r\n message: 'Send the response code to the initiator via a secure channel or let them scan the QR code below.', \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n \r\n }\r\n \r\n // Update security level after creating answer\r\n if (!window.isUpdatingSecurity) {\r\n updateSecurityLevel().catch(console.error);\r\n }\r\n } catch (error) {\r\n console.error('Error in handleCreateAnswer:', error);\r\n setMessages(prev => [...prev, { \r\n message: `Error processing the invitation: ${error.message}`, \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n }\r\n } catch (error) {\r\n console.error('Error in handleCreateAnswer:', error);\r\n setMessages(prev => [...prev, { \r\n message: `Invitation processing error: ${error.message}`, \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n }\r\n };\r\n \r\n const handleConnect = async () => {\r\n try {\r\n if (!answerInput.trim()) {\r\n setMessages(prev => [...prev, { \r\n message: 'You need to insert the response code from your interlocutor.', \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n return;\r\n }\r\n \r\n try {\r\n setMessages(prev => [...prev, { \r\n message: 'Processing the secure response...', \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n \r\n let answer;\r\n try {\r\n // Prefer binary decode first, then gzip JSON\r\n if (typeof window.decodeAnyPayload === 'function') {\r\n const anyAnswer = window.decodeAnyPayload(answerInput.trim());\r\n answer = (typeof anyAnswer === 'string') ? JSON.parse(anyAnswer) : anyAnswer;\r\n } else {\r\n const rawText = (typeof window.decompressIfNeeded === 'function') ? window.decompressIfNeeded(answerInput.trim()) : answerInput.trim();\r\n answer = JSON.parse(rawText);\r\n }\r\n } catch (parseError) {\r\n throw new Error(`Invalid response format: ${parseError.message}`);\r\n }\r\n \r\n if (!answer || typeof answer !== 'object') {\r\n throw new Error('The response must be an object');\r\n }\r\n \r\n // Support both compact and legacy formats\r\n const answerType = answer.t || answer.type;\r\n if (!answerType || (answerType !== 'answer' && answerType !== 'enhanced_secure_answer')) {\r\n throw new Error('Invalid response type. Expected answer or enhanced_secure_answer');\r\n }\r\n \r\n await webrtcManagerRef.current.handleSecureAnswer(answer);\r\n \r\n // All security features are enabled by default - no session activation needed\r\n if (pendingSession) {\r\n setPendingSession(null);\r\n setMessages(prev => [...prev, { \r\n message: `All security features enabled by default`, \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n }\r\n \r\n setMessages(prev => [...prev, { \r\n message: 'Finalizing the secure connection...', \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n \r\n // Update security level after handling answer\r\n if (!window.isUpdatingSecurity) {\r\n updateSecurityLevel().catch(console.error);\r\n }\r\n } catch (error) {\r\n console.error('Error in handleConnect inner try:', error);\r\n \r\n // \u0411\u043E\u043B\u0435\u0435 \u0434\u0435\u0442\u0430\u043B\u044C\u043D\u0430\u044F \u043E\u0431\u0440\u0430\u0431\u043E\u0442\u043A\u0430 \u043E\u0448\u0438\u0431\u043E\u043A\r\n let errorMessage = 'Connection setup error';\r\n if (error.message.includes('CRITICAL SECURITY FAILURE')) {\r\n if (error.message.includes('ECDH public key structure')) {\r\n errorMessage = 'Invalid response code - missing or corrupted cryptographic key. Please check the code and try again.';\r\n } else if (error.message.includes('ECDSA public key structure')) {\r\n errorMessage = 'Invalid response code - missing signature verification key. Please check the code and try again.';\r\n } else {\r\n errorMessage = 'Security validation failed - possible attack detected';\r\n }\r\n } else if (error.message.includes('too old') || error.message.includes('replay')) {\r\n errorMessage = 'Response data is outdated - please use a fresh invitation';\r\n } else if (error.message.includes('MITM') || error.message.includes('signature')) {\r\n errorMessage = 'Security breach detected - connection rejected';\r\n } else if (error.message.includes('Invalid') || error.message.includes('format')) {\r\n errorMessage = 'Invalid response format - please check the code';\r\n } else {\r\n errorMessage = ` ${error.message}`;\r\n }\r\n \r\n setMessages(prev => [...prev, { \r\n message: errorMessage, \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now(),\r\n showRetryButton: true\r\n }]);\r\n\r\n if (!error.message.includes('too old') && !error.message.includes('replay')) {\r\n setPendingSession(null);\r\n setSessionTimeLeft(0);\r\n }\r\n\r\n setConnectionStatus('failed');\r\n \r\n } \r\n } catch (error) {\r\n console.error('Error in handleConnect outer try:', error);\r\n\r\n let errorMessage = 'Connection setup error';\r\n if (error.message.includes('CRITICAL SECURITY FAILURE')) {\r\n if (error.message.includes('ECDH public key structure')) {\r\n errorMessage = 'Invalid response code - missing or corrupted cryptographic key. Please check the code and try again.';\r\n } else if (error.message.includes('ECDSA public key structure')) {\r\n errorMessage = 'Invalid response code - missing signature verification key. Please check the code and try again.';\r\n } else {\r\n errorMessage = 'Security validation failed - possible attack detected';\r\n }\r\n } else if (error.message.includes('too old') || error.message.includes('replay')) {\r\n errorMessage = 'Response data is outdated - please use a fresh invitation';\r\n } else if (error.message.includes('MITM') || error.message.includes('signature')) {\r\n errorMessage = 'Security breach detected - connection rejected';\r\n } else if (error.message.includes('Invalid') || error.message.includes('format')) {\r\n errorMessage = 'Invalid response format - please check the code';\r\n } else {\r\n errorMessage = `${error.message}`;\r\n }\r\n \r\n setMessages(prev => [...prev, { \r\n message: errorMessage, \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now(),\r\n showRetryButton: true\r\n }]);\r\n\r\n if (!error.message.includes('too old') && !error.message.includes('replay')) {\r\n setPendingSession(null);\r\n setSessionTimeLeft(0);\r\n }\r\n\r\n setConnectionStatus('failed');\r\n }\r\n };\r\n \r\n const handleVerifyConnection = (isValid) => {\r\n if (isValid) {\r\n webrtcManagerRef.current.confirmVerification();\r\n // Mark local verification as confirmed\r\n setLocalVerificationConfirmed(true);\r\n } else {\r\n setMessages(prev => [...prev, { \r\n message: ' Verification rejected. The connection is unsafe! Session reset..', \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n \r\n // Clear verification states\r\n setLocalVerificationConfirmed(false);\r\n setRemoteVerificationConfirmed(false);\r\n setBothVerificationsConfirmed(false);\r\n setShowVerification(false);\r\n setVerificationCode('');\r\n \r\n // Reset UI to initial state\r\n setConnectionStatus('disconnected');\r\n setOfferData(null);\r\n setAnswerData(null);\r\n setOfferInput('');\r\n setAnswerInput('');\r\n setShowOfferStep(false);\r\n setShowAnswerStep(false);\r\n setKeyFingerprint('');\r\n setSecurityLevel(null);\r\n setIsVerified(false);\r\n setMessages([]);\r\n \r\n setSessionTimeLeft(0);\r\n setPendingSession(null);\r\n \r\n // Dispatch disconnected event for SessionTimer\r\n document.dispatchEvent(new CustomEvent('disconnected'));\r\n \r\n handleDisconnect();\r\n }\r\n };\r\n \r\n const handleSendMessage = async () => {\r\n if (!messageInput.trim()) {\r\n return;\r\n }\r\n \r\n if (!webrtcManagerRef.current) {\r\n return;\r\n }\r\n \r\n if (!webrtcManagerRef.current.isConnected()) {\r\n return;\r\n }\r\n \r\n try {\r\n \r\n // Add the message to local messages immediately (sent message)\r\n addMessageWithAutoScroll(messageInput.trim(), 'sent');\r\n \r\n // Use sendMessage for simple text messages instead of sendSecureMessage\r\n await webrtcManagerRef.current.sendMessage(messageInput);\r\n setMessageInput('');\r\n } catch (error) {\r\n const msg = String(error?.message || error);\r\n if (!/queued for sending|Data channel not ready/i.test(msg)) {\r\n addMessageWithAutoScroll(`Sending error: ${msg}`,'system');\r\n }\r\n }\r\n };\r\n \r\n const handleClearData = () => {\r\n setOfferData('');\r\n setAnswerData('');\r\n setOfferInput('');\r\n setAnswerInput('');\r\n setShowOfferStep(false);\r\n\r\n if (!shouldPreserveAnswerData()) {\r\n setShowAnswerStep(false);\r\n }\r\n \r\n setShowVerification(false);\r\n setShowQRCode(false);\r\n setShowQRScanner(false);\r\n setShowQRScannerModal(false);\r\n\r\n if (!shouldPreserveAnswerData()) {\r\n setQrCodeUrl('');\r\n }\r\n \r\n setVerificationCode('');\r\n setIsVerified(false);\r\n setKeyFingerprint('');\r\n setSecurityLevel(null);\r\n setConnectionStatus('disconnected');\r\n setMessages([]);\r\n setMessageInput('');\r\n \r\n // Clear verification states\r\n setLocalVerificationConfirmed(false);\r\n setRemoteVerificationConfirmed(false);\r\n setBothVerificationsConfirmed(false);\r\n \r\n // PAKE passwords removed - using SAS verification instead \r\n\r\n if (typeof console.clear === 'function') {\r\n console.clear();\r\n }\r\n \r\n // Cleanup session state\r\n setSessionTimeLeft(0);\r\n \r\n setPendingSession(null);\r\n document.dispatchEvent(new CustomEvent('peer-disconnect'));\r\n // Session manager removed - all features enabled by default\r\n };\r\n \r\n const handleDisconnect = () => {\r\n setSessionTimeLeft(0);\r\n \r\n // Mark as user-initiated disconnect\r\n updateConnectionState({ \r\n status: 'disconnected',\r\n isUserInitiatedDisconnect: true \r\n });\r\n \r\n // Cleanup session state\r\n if (webrtcManagerRef.current) {\r\n webrtcManagerRef.current.disconnect();\r\n }\r\n \r\n setKeyFingerprint('');\r\n setVerificationCode('');\r\n setSecurityLevel(null);\r\n setIsVerified(false);\r\n setShowVerification(false);\r\n setConnectionStatus('disconnected');\r\n \r\n // Clear verification states\r\n setLocalVerificationConfirmed(false);\r\n setRemoteVerificationConfirmed(false);\r\n setBothVerificationsConfirmed(false);\r\n \r\n // Reset UI to initial state (user-initiated disconnect always clears data)\r\n setConnectionStatus('disconnected');\r\n setShowVerification(false);\r\n setOfferData(null);\r\n setAnswerData(null);\r\n setOfferInput('');\r\n setAnswerInput('');\r\n setShowOfferStep(false);\r\n setShowAnswerStep(false);\r\n setKeyFingerprint('');\r\n setVerificationCode('');\r\n setSecurityLevel(null);\r\n setIsVerified(false);\r\n \r\n setMessages([]);\r\n \r\n if (typeof console.clear === 'function') {\r\n console.clear();\r\n }\r\n \r\n document.dispatchEvent(new CustomEvent('peer-disconnect'));\r\n document.dispatchEvent(new CustomEvent('disconnected'));\r\n \r\n document.dispatchEvent(new CustomEvent('session-cleanup', {\r\n detail: { \r\n timestamp: Date.now(),\r\n reason: 'manual_disconnect'\r\n }\r\n }));\r\n \r\n setTimeout(() => {\r\n setSessionTimeLeft(0);\r\n }, 500);\r\n \r\n handleClearData();\r\n \r\n setTimeout(() => {\r\n // Session manager removed - all features enabled by default\r\n }, 1000);\r\n };\r\n \r\n const handleSessionActivated = (session) => {\r\n let message;\r\n if (session.type === 'demo') {\r\n message = ` Demo session activated for 6 minutes. You can create invitations!`;\r\n } else {\r\n message = ` All security features enabled by default. You can create invitations!`;\r\n }\r\n \r\n addMessageWithAutoScroll(message, 'system');\r\n \r\n };\r\n \r\n React.useEffect(() => {\r\n if (connectionStatus === 'connected' && isVerified) {\r\n addMessageWithAutoScroll(' Secure connection successfully established and verified! You can now communicate safely with full protection against MITM attacks and Perfect Forward Secrecy..', 'system');\r\n \r\n }\r\n }, [connectionStatus, isVerified]);\r\n \r\n const isConnectedAndVerified = (connectionStatus === 'connected' || connectionStatus === 'verified') && isVerified;\r\n \r\n React.useEffect(() => {\r\n // All security features are enabled by default - no session activation needed\r\n if (isConnectedAndVerified && pendingSession && connectionStatus !== 'failed') {\r\n setPendingSession(null);\r\n setSessionTimeLeft(0); \r\n addMessageWithAutoScroll(' All security features enabled by default', 'system');\r\n }\r\n }, [isConnectedAndVerified, pendingSession, connectionStatus]);\r\n \r\n return React.createElement('div', { \r\n className: \"minimal-bg min-h-screen\" \r\n }, [\r\n React.createElement(EnhancedMinimalHeader, {\r\n key: 'header',\r\n status: connectionStatus,\r\n fingerprint: keyFingerprint,\r\n verificationCode: verificationCode,\r\n onDisconnect: handleDisconnect,\r\n isConnected: isConnectedAndVerified,\r\n securityLevel: securityLevel,\r\n // sessionManager removed - all features enabled by default\r\n sessionTimeLeft: sessionTimeLeft,\r\n webrtcManager: webrtcManagerRef.current\r\n }),\r\n \r\n React.createElement('main', {\r\n key: 'main'\r\n }, \r\n (() => {\r\n return isConnectedAndVerified;\r\n })()\r\n ? (() => {\r\n return React.createElement(EnhancedChatInterface, {\r\n messages: messages,\r\n messageInput: messageInput,\r\n setMessageInput: setMessageInput,\r\n onSendMessage: handleSendMessage,\r\n onDisconnect: handleDisconnect,\r\n keyFingerprint: keyFingerprint,\r\n isVerified: isVerified,\r\n chatMessagesRef: chatMessagesRef,\r\n scrollToBottom: scrollToBottom,\r\n webrtcManager: webrtcManagerRef.current\r\n });\r\n })()\r\n : React.createElement(EnhancedConnectionSetup, {\r\n onCreateOffer: handleCreateOffer,\r\n onCreateAnswer: handleCreateAnswer,\r\n onConnect: handleConnect,\r\n onClearData: handleClearData,\r\n onVerifyConnection: handleVerifyConnection,\r\n connectionStatus: connectionStatus,\r\n offerData: offerData,\r\n answerData: answerData,\r\n offerInput: offerInput,\r\n setOfferInput: setOfferInput,\r\n answerInput: answerInput,\r\n setAnswerInput: setAnswerInput,\r\n showOfferStep: showOfferStep,\r\n showAnswerStep: showAnswerStep,\r\n verificationCode: verificationCode,\r\n showVerification: showVerification,\r\n showQRCode: showQRCode,\r\n qrCodeUrl: qrCodeUrl,\r\n showQRScanner: showQRScanner,\r\n setShowQRCode: setShowQRCode,\r\n setShowQRScanner: setShowQRScanner,\r\n setShowQRScannerModal: setShowQRScannerModal,\r\n messages: messages,\r\n localVerificationConfirmed: localVerificationConfirmed,\r\n remoteVerificationConfirmed: remoteVerificationConfirmed,\r\n bothVerificationsConfirmed: bothVerificationsConfirmed,\r\n // QR control props\r\n qrFramesTotal: qrFramesTotal,\r\n qrFrameIndex: qrFrameIndex,\r\n qrManualMode: qrManualMode,\r\n toggleQrManualMode: toggleQrManualMode,\r\n nextQrFrame: nextQrFrame,\r\n prevQrFrame: prevQrFrame,\r\n // PAKE passwords removed - using SAS verification instead\r\n markAnswerCreated: markAnswerCreated\r\n })\r\n ),\r\n \r\n ]);\r\n };\r\n function initializeApp() {\r\n if (window.EnhancedSecureCryptoUtils && window.EnhancedSecureWebRTCManager) {\r\n ReactDOM.render(React.createElement(EnhancedSecureP2PChat), document.getElementById('root'));\r\n } else {\r\n console.error('\u041C\u043E\u0434\u0443\u043B\u0438 \u043D\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043D\u044B:', {\r\n hasCrypto: !!window.EnhancedSecureCryptoUtils,\r\n hasWebRTC: !!window.EnhancedSecureWebRTCManager\r\n });\r\n }\r\n }\r\n\r\n if (typeof window !== 'undefined') {\r\n\r\n window.addEventListener('unhandledrejection', (event) => {\r\n console.error('Unhandled promise rejection:', event.reason);\r\n event.preventDefault(); \r\n });\r\n \r\n\r\n window.addEventListener('error', (event) => {\r\n console.error('Global error:', event.error);\r\n event.preventDefault(); \r\n });\r\n \r\n if (!window.initializeApp) {\r\n window.initializeApp = initializeApp;\r\n }\r\n }\r\n // Render Enhanced Application\r\n ReactDOM.render(React.createElement(EnhancedSecureP2PChat), document.getElementById('root'));"], - "mappings": "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", - "names": ["e", "offerData"] + "sourcesContent": ["\r\n // Enhanced Copy Button with better UX\r\n const EnhancedCopyButton = ({ text, className = \"\", children }) => {\r\n const [copied, setCopied] = React.useState(false);\r\n \r\n const handleCopy = async () => {\r\n try {\r\n await navigator.clipboard.writeText(text);\r\n setCopied(true);\r\n setTimeout(() => setCopied(false), 2000);\r\n } catch (error) {\r\n console.error('Copy failed:', error);\r\n // Fallback for older browsers\r\n const textArea = document.createElement('textarea');\r\n textArea.value = text;\r\n document.body.appendChild(textArea);\r\n textArea.select();\r\n document.execCommand('copy');\r\n document.body.removeChild(textArea);\r\n setCopied(true);\r\n setTimeout(() => setCopied(false), 2000);\r\n }\r\n };\r\n \r\n return React.createElement('button', {\r\n onClick: handleCopy,\r\n className: `${className} transition-all duration-200`\r\n }, [\r\n React.createElement('i', {\r\n key: 'icon',\r\n className: `${copied ? 'fas fa-check accent-green' : 'fas fa-copy text-secondary'} mr-2`\r\n }),\r\n copied ? 'Copied!' : children\r\n ]);\r\n };\r\n \r\n // Verification Component\r\n const VerificationStep = ({ verificationCode, onConfirm, onReject, localConfirmed, remoteConfirmed, bothConfirmed }) => {\r\n return React.createElement('div', {\r\n className: \"card-minimal rounded-xl p-6 border-purple-500/20\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'header',\r\n className: \"flex items-center mb-4\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'icon',\r\n className: \"w-10 h-10 bg-purple-500/10 border border-purple-500/20 rounded-lg flex items-center justify-center mr-3\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-shield-alt accent-purple'\r\n })\r\n ]),\r\n React.createElement('h3', {\r\n key: 'title',\r\n className: \"text-lg font-medium text-primary\"\r\n }, \"Security verification\")\r\n ]),\r\n React.createElement('div', {\r\n key: 'content',\r\n className: \"space-y-4\"\r\n }, [\r\n React.createElement('p', {\r\n key: 'description',\r\n className: \"text-secondary text-sm\"\r\n }, \"Verify the security code with your contact via another communication channel (voice, SMS, etc.):\"),\r\n React.createElement('div', {\r\n key: 'code-display',\r\n className: \"text-center\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'code',\r\n className: \"verification-code text-2xl py-4\"\r\n }, verificationCode)\r\n ]),\r\n // Verification status indicators\r\n React.createElement('div', {\r\n key: 'verification-status',\r\n className: \"space-y-2\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'local-status',\r\n className: `flex items-center justify-between p-2 rounded-lg ${localConfirmed ? 'bg-green-500/10 border border-green-500/20' : 'bg-gray-500/10 border border-gray-500/20'}`\r\n }, [\r\n React.createElement('span', {\r\n key: 'local-label',\r\n className: \"text-sm text-secondary\"\r\n }, \"Your confirmation:\"),\r\n React.createElement('div', {\r\n key: 'local-indicator',\r\n className: \"flex items-center\"\r\n }, [\r\n React.createElement('i', {\r\n key: 'local-icon',\r\n className: `fas ${localConfirmed ? 'fa-check-circle text-green-400' : 'fa-clock text-gray-400'} mr-2`\r\n }),\r\n React.createElement('span', {\r\n key: 'local-text',\r\n className: `text-sm ${localConfirmed ? 'text-green-400' : 'text-gray-400'}`\r\n }, localConfirmed ? 'Confirmed' : 'Pending')\r\n ])\r\n ]),\r\n React.createElement('div', {\r\n key: 'remote-status',\r\n className: `flex items-center justify-between p-2 rounded-lg ${remoteConfirmed ? 'bg-green-500/10 border border-green-500/20' : 'bg-gray-500/10 border border-gray-500/20'}`\r\n }, [\r\n React.createElement('span', {\r\n key: 'remote-label',\r\n className: \"text-sm text-secondary\"\r\n }, \"Peer confirmation:\"),\r\n React.createElement('div', {\r\n key: 'remote-indicator',\r\n className: \"flex items-center\"\r\n }, [\r\n React.createElement('i', {\r\n key: 'remote-icon',\r\n className: `fas ${remoteConfirmed ? 'fa-check-circle text-green-400' : 'fa-clock text-gray-400'} mr-2`\r\n }),\r\n React.createElement('span', {\r\n key: 'remote-text',\r\n className: `text-sm ${remoteConfirmed ? 'text-green-400' : 'text-gray-400'}`\r\n }, remoteConfirmed ? 'Confirmed' : 'Pending')\r\n ])\r\n ])\r\n ]),\r\n React.createElement('div', {\r\n key: 'warning',\r\n className: \"p-3 bg-yellow-500/10 border border-yellow-500/20 rounded-lg\"\r\n }, [\r\n React.createElement('p', {\r\n className: \"text-yellow-400 text-sm flex items-center\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-exclamation-triangle mr-2'\r\n }),\r\n 'Make sure the codes match exactly.!'\r\n ])\r\n ]),\r\n React.createElement('div', {\r\n key: 'buttons',\r\n className: \"flex space-x-3\"\r\n }, [\r\n React.createElement('button', {\r\n key: 'confirm',\r\n onClick: onConfirm,\r\n disabled: localConfirmed,\r\n className: `flex-1 py-3 px-4 rounded-lg font-medium transition-all duration-200 ${localConfirmed ? 'bg-gray-500/20 text-gray-400 cursor-not-allowed' : 'btn-verify text-white'}`\r\n }, [\r\n React.createElement('i', {\r\n className: `fas ${localConfirmed ? 'fa-check-circle' : 'fa-check'} mr-2`\r\n }),\r\n localConfirmed ? 'Confirmed' : 'The codes match'\r\n ]),\r\n React.createElement('button', {\r\n key: 'reject',\r\n onClick: onReject,\r\n className: \"flex-1 bg-red-500/10 hover:bg-red-500/20 text-red-400 border border-red-500/20 py-3 px-4 rounded-lg font-medium transition-all duration-200\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-times mr-2'\r\n }),\r\n 'The codes do not match'\r\n ])\r\n ])\r\n ])\r\n ]);\r\n };\r\n \r\n // Enhanced Chat Message with better security indicators\r\n const EnhancedChatMessage = ({ message, type, timestamp }) => {\r\n const formatTime = (ts) => {\r\n return new Date(ts).toLocaleTimeString('ru-RU', { \r\n hour: '2-digit', \r\n minute: '2-digit',\r\n second: '2-digit'\r\n });\r\n };\r\n \r\n const getMessageStyle = () => {\r\n switch (type) {\r\n case 'sent':\r\n return {\r\n container: \"ml-auto bg-orange-500/15 border-orange-500/20 text-primary\",\r\n icon: \"fas fa-lock accent-orange\",\r\n label: \"Encrypted\"\r\n };\r\n case 'received':\r\n return {\r\n container: \"mr-auto card-minimal text-primary\",\r\n icon: \"fas fa-unlock-alt accent-green\",\r\n label: \"Decrypted\"\r\n };\r\n case 'system':\r\n return {\r\n container: \"mx-auto bg-yellow-500/10 border border-yellow-500/20 text-yellow-400\",\r\n icon: \"fas fa-info-circle accent-yellow\",\r\n label: \"System\"\r\n };\r\n default:\r\n return {\r\n container: \"mx-auto card-minimal text-secondary\",\r\n icon: \"fas fa-circle text-muted\",\r\n label: \"Unknown\"\r\n };\r\n }\r\n };\r\n \r\n const style = getMessageStyle();\r\n \r\n return React.createElement('div', {\r\n className: `message-slide mb-3 p-3 rounded-lg max-w-md break-words ${style.container} border`\r\n }, [\r\n React.createElement('div', {\r\n key: 'content',\r\n className: \"flex items-start space-x-2\"\r\n }, [\r\n React.createElement('i', {\r\n key: 'icon',\r\n className: `${style.icon} text-sm mt-0.5 opacity-70`\r\n }),\r\n React.createElement('div', {\r\n key: 'text',\r\n className: \"flex-1\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'message',\r\n className: \"text-sm\"\r\n }, message),\r\n timestamp && React.createElement('div', {\r\n key: 'meta',\r\n className: \"flex items-center justify-between mt-1 text-xs opacity-50\"\r\n }, [\r\n React.createElement('span', {\r\n key: 'time'\r\n }, formatTime(timestamp)),\r\n React.createElement('span', {\r\n key: 'status',\r\n className: \"text-xs\"\r\n }, style.label)\r\n ])\r\n ])\r\n ])\r\n ]);\r\n };\r\n \r\n // Enhanced Connection Setup with verification\r\n const EnhancedConnectionSetup = ({\r\n messages, \r\n onCreateOffer, \r\n onCreateAnswer, \r\n onConnect, \r\n onClearData,\r\n onVerifyConnection,\r\n connectionStatus,\r\n offerData,\r\n answerData,\r\n offerInput,\r\n setOfferInput,\r\n answerInput,\r\n setAnswerInput,\r\n showOfferStep,\r\n showAnswerStep,\r\n verificationCode,\r\n showVerification,\r\n showQRCode,\r\n qrCodeUrl,\r\n showQRScanner,\r\n setShowQRCode,\r\n setShowQRScanner,\r\n setShowQRScannerModal,\r\n offerPassword,\r\n answerPassword,\r\n localVerificationConfirmed,\r\n remoteVerificationConfirmed,\r\n bothVerificationsConfirmed,\r\n // QR control props\r\n qrFramesTotal,\r\n qrFrameIndex,\r\n qrManualMode,\r\n toggleQrManualMode,\r\n nextQrFrame,\r\n prevQrFrame,\r\n markAnswerCreated\r\n }) => {\r\n const [mode, setMode] = React.useState('select');\r\n \r\n const resetToSelect = () => {\r\n setMode('select');\r\n onClearData();\r\n };\r\n \r\n const handleVerificationConfirm = () => {\r\n onVerifyConnection(true);\r\n };\r\n \r\n const handleVerificationReject = () => {\r\n onVerifyConnection(false);\r\n };\r\n \r\n if (showVerification) {\r\n return React.createElement('div', {\r\n className: \"min-h-[calc(100vh-104px)] flex items-center justify-center p-4\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'verification',\r\n className: \"w-full max-w-md\"\r\n }, [\r\n React.createElement(VerificationStep, {\r\n verificationCode: verificationCode,\r\n onConfirm: handleVerificationConfirm,\r\n onReject: handleVerificationReject,\r\n localConfirmed: localVerificationConfirmed,\r\n remoteConfirmed: remoteVerificationConfirmed,\r\n bothConfirmed: bothVerificationsConfirmed\r\n })\r\n ])\r\n ]);\r\n }\r\n \r\n if (mode === 'select') {\r\n return React.createElement('div', {\r\n className: \"min-h-[calc(100vh-104px)] flex items-center justify-center p-4\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'selector',\r\n className: \"w-full max-w-4xl\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'header',\r\n className: \"text-center mb-8\"\r\n }, [\r\n React.createElement('h2', {\r\n key: 'title',\r\n className: \"text-2xl font-semibold text-primary mb-3\"\r\n }, 'Start secure communication'),\r\n React.createElement('p', {\r\n key: 'subtitle',\r\n className: \"text-secondary max-w-2xl mx-auto\"\r\n }, \"Choose a connection method for a secure channel with ECDH encryption and Perfect Forward Secrecy.\")\r\n ]),\r\n \r\n React.createElement('div', {\r\n key: 'options',\r\n className: \"flex flex-col md:flex-row items-center justify-center gap-6 max-w-3xl mx-auto\"\r\n }, [\r\n // Create Connection\r\n React.createElement('div', {\r\n key: 'create',\r\n onClick: () => setMode('create'),\r\n className: \"card-minimal rounded-xl p-6 cursor-pointer group flex-1 create\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'icon',\r\n className: \"w-12 h-12 bg-blue-500/10 border border-blue-500/20 rounded-lg flex items-center justify-center mx-auto mb-4\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-plus text-xl text-blue-400'\r\n })\r\n ]),\r\n React.createElement('h3', {\r\n key: 'title',\r\n className: \"text-lg font-semibold text-primary text-center mb-3\"\r\n }, \"Create channel\"),\r\n React.createElement('p', {\r\n key: 'description',\r\n className: \"text-secondary text-center text-sm mb-4\"\r\n }, \"Initiate a new secure connection\"),\r\n React.createElement('div', {\r\n key: 'features',\r\n className: \"space-y-2\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'f1',\r\n className: \"flex items-center text-sm text-muted\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-key accent-orange mr-2 text-xs'\r\n }),\r\n 'Generating ECDH keys'\r\n ]),\r\n React.createElement('div', {\r\n key: 'f2',\r\n className: \"flex items-center text-sm text-muted\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-shield-alt accent-orange mr-2 text-xs'\r\n }),\r\n 'Verification code'\r\n ]),\r\n React.createElement('div', {\r\n key: 'f3',\r\n className: \"flex items-center text-sm text-muted\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-sync-alt accent-purple mr-2 text-xs'\r\n }),\r\n 'PFS key rotation'\r\n ])\r\n ])\r\n ]),\r\n React.createElement('div', {\r\n key: 'divider',\r\n className: \"flex flex-row md:flex-col items-center gap-4 px-4 w-full md:w-auto\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'line-a',\r\n className: \"h-px flex-1 bg-gradient-to-r from-transparent via-zinc-700 to-transparent md:h-32 md:w-px md:flex-none md:bg-gradient-to-b\"\r\n }),\r\n React.createElement('div', {\r\n key: 'or-text',\r\n className: \"text-zinc-600 text-sm font-medium px-3\"\r\n }, \"OR\"),\r\n React.createElement('div', {\r\n key: 'line-b',\r\n className: \"h-px flex-1 bg-gradient-to-r from-transparent via-zinc-700 to-transparent md:h-32 md:w-px md:flex-none md:bg-gradient-to-b\"\r\n })\r\n ]),\r\n // Join Connection\r\n React.createElement('div', {\r\n key: 'join',\r\n onClick: () => setMode('join'),\r\n className: \"card-minimal rounded-xl p-6 cursor-pointer group flex-1 join\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'icon',\r\n className: \"w-12 h-12 bg-green-500/10 border border-green-500/20 rounded-lg flex items-center justify-center mx-auto mb-4\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-link text-xl accent-green'\r\n })\r\n ]),\r\n React.createElement('h3', {\r\n key: 'title',\r\n className: \"text-lg font-semibold text-primary text-center mb-3\"\r\n }, \"Join\"),\r\n React.createElement('p', {\r\n key: 'description',\r\n className: \"text-secondary text-center text-sm mb-4\"\r\n }, \"Connect to an existing secure channel\"),\r\n React.createElement('div', {\r\n key: 'features',\r\n className: \"space-y-2\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'f1',\r\n className: \"flex items-center text-sm text-muted\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-paste accent-green mr-2 text-xs'\r\n }),\r\n 'Paste Offer invitation'\r\n ]),\r\n React.createElement('div', {\r\n key: 'f2',\r\n className: \"flex items-center text-sm text-muted\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-check-circle accent-green mr-2 text-xs'\r\n }),\r\n 'Automatic verification'\r\n ]),\r\n React.createElement('div', {\r\n key: 'f3',\r\n className: \"flex items-center text-sm text-muted\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-sync-alt accent-purple mr-2 text-xs'\r\n }),\r\n 'PFS protection'\r\n ])\r\n ])\r\n ])\r\n ]),\r\n \r\n \r\n React.createElement(SecurityFeatures, { key: 'security-features' }),\r\n\r\n React.createElement(Testimonials, { key: 'testimonials' }),\r\n \r\n React.createElement(UniqueFeatureSlider, { key: 'unique-features-slider' }),\r\n \r\n React.createElement(DownloadApps, { key: 'download-apps' }),\r\n \r\n React.createElement(ComparisonTable, { key: 'comparison-table' }), \r\n \r\n React.createElement(Roadmap, { key: 'roadmap' }),\r\n ])\r\n ]);\r\n }\r\n \r\n if (mode === 'create') {\r\n return React.createElement('div', {\r\n className: \"min-h-[calc(100vh-104px)] flex items-center justify-center p-4\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'create-flow',\r\n className: \"w-full max-w-3xl space-y-6\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'header',\r\n className: \"text-center\"\r\n }, [\r\n React.createElement('button', {\r\n key: 'back',\r\n onClick: resetToSelect,\r\n className: \"mb-4 text-secondary hover:text-primary transition-colors flex items-center mx-auto text-sm\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-arrow-left mr-2'\r\n }),\r\n 'Back to selection'\r\n ]),\r\n React.createElement('h2', {\r\n key: 'title',\r\n className: \"text-xl font-semibold text-primary mb-2\"\r\n }, 'Creating a secure channel')\r\n ]),\r\n \r\n // Step 1\r\n !showAnswerStep && React.createElement('div', {\r\n key: 'step1',\r\n className: \"card-minimal rounded-xl p-6\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'step-header',\r\n className: \"flex items-center mb-4\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'number',\r\n className: \"step-number mr-3\"\r\n }, '1'),\r\n React.createElement('h3', {\r\n key: 'title',\r\n className: \"text-lg font-medium text-primary\"\r\n }, \"Generating ECDH keys and verification code\")\r\n ]),\r\n React.createElement('p', {\r\n key: 'description',\r\n className: \"text-secondary text-sm mb-4\"\r\n }, \"Creating cryptographically strong keys and codes to protect against attacks\"),\r\n !showOfferStep && React.createElement('button', {\r\n key: 'create-btn',\r\n onClick: onCreateOffer,\r\n disabled: connectionStatus === 'connecting',\r\n className: `w-full btn-primary text-white py-3 px-4 rounded-lg font-medium transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed`\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-shield-alt mr-2'\r\n }),\r\n 'Create secure keys'\r\n ]),\r\n \r\n showOfferStep && React.createElement('div', {\r\n key: 'offer-result',\r\n className: \"mt-6 space-y-4\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'success',\r\n className: \"p-3 bg-green-500/10 border border-green-500/20 rounded-lg\"\r\n }, [\r\n React.createElement('p', {\r\n className: \"text-green-400 text-sm font-medium flex items-center\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-check-circle mr-2'\r\n }),\r\n 'Secure invitation created! Send the code to your contact'\r\n ])\r\n ]),\r\n React.createElement('div', {\r\n key: 'offer-data',\r\n className: \"space-y-3\"\r\n }, [\r\n // Raw JSON hidden intentionally; users copy compressed string or use QR\r\n React.createElement('div', {\r\n key: 'buttons',\r\n className: \"flex gap-2\"\r\n }, [\r\n React.createElement(EnhancedCopyButton, {\r\n key: 'copy',\r\n text: (() => {\r\n try {\r\n const min = typeof offerData === 'object' ? JSON.stringify(offerData) : (offerData || '');\r\n if (typeof window.encodeBinaryToPrefixed === 'function') {\r\n return window.encodeBinaryToPrefixed(min);\r\n }\r\n if (typeof window.compressToPrefixedGzip === 'function') {\r\n return window.compressToPrefixedGzip(min);\r\n }\r\n return min;\r\n } catch { return typeof offerData === 'object' ? JSON.stringify(offerData) : (offerData || ''); }\r\n })(),\r\n className: \"flex-1 px-3 py-2 bg-orange-500/10 hover:bg-orange-500/20 text-orange-400 border border-orange-500/20 rounded text-sm font-medium\"\r\n }, 'Copy invitation code')\r\n ]),\r\n showQRCode && qrCodeUrl && React.createElement('div', {\r\n key: 'qr-container',\r\n className: \"mt-4 p-4 border border-gray-600/30 rounded-lg text-center\"\r\n }, [\r\n React.createElement('h4', {\r\n key: 'qr-title',\r\n className: \"text-sm font-medium text-primary mb-3\"\r\n }, 'Scan QR code to connect'),\r\n React.createElement('div', {\r\n key: 'qr-wrapper',\r\n className: \"flex justify-center\"\r\n }, [\r\n React.createElement('img', {\r\n key: 'qr-image',\r\n src: qrCodeUrl,\r\n alt: \"QR Code for secure connection\",\r\n className: \"max-w-none h-auto border border-gray-600/30 rounded w-[20rem] sm:w-[24rem] md:w-[28rem] lg:w-[32rem]\"\r\n })\r\n ]),\r\n\r\n ((qrFramesTotal || 0) >= 1) && React.createElement('div', {\r\n key: 'qr-controls-below',\r\n className: \"mt-4 flex flex-col items-center gap-2\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'frame-indicator',\r\n className: \"text-xs text-gray-300\"\r\n }, `Frame ${Math.max(1, (qrFrameIndex || 1))}/${qrFramesTotal || 1}`),\r\n React.createElement('div', {\r\n key: 'control-buttons',\r\n className: \"flex gap-1\"\r\n }, [\r\n (qrFramesTotal || 0) > 1 && React.createElement('button', {\r\n key: 'prev-frame',\r\n onClick: prevQrFrame,\r\n className: \"w-6 h-6 bg-gray-600 hover:bg-gray-500 text-white rounded text-xs flex items-center justify-center\"\r\n }, '\u25C0'),\r\n React.createElement('button', {\r\n key: 'toggle-manual',\r\n onClick: toggleQrManualMode,\r\n className: `px-2 py-1 rounded text-xs font-medium ${\r\n (qrManualMode || false)\r\n ? 'bg-blue-500 text-white' \r\n : 'bg-gray-600 text-gray-300 hover:bg-gray-500'\r\n }`\r\n }, (qrManualMode || false) ? 'Manual' : 'Auto'),\r\n (qrFramesTotal || 0) > 1 && React.createElement('button', {\r\n key: 'next-frame',\r\n onClick: nextQrFrame,\r\n className: \"w-6 h-6 bg-gray-600 hover:bg-gray-500 text-white rounded text-xs flex items-center justify-center\"\r\n }, '\u25B6')\r\n ])\r\n ]),\r\n React.createElement('p', {\r\n key: 'qr-description',\r\n className: \"text-xs text-gray-400 mt-2\"\r\n }, 'Your contact can scan this QR code to quickly join the secure session')\r\n ])\r\n ])\r\n ])\r\n ]),\r\n \r\n // Step 2 - Session Type Selection\r\n // showOfferStep && React.createElement('div', {\r\n // key: 'step2',\r\n // className: \"card-minimal rounded-xl p-6\"\r\n // }, [\r\n // React.createElement('div', {\r\n // key: 'step-header',\r\n // className: \"flex items-center mb-4\"\r\n // }, [\r\n // React.createElement('div', {\r\n // key: 'number',\r\n // className: \"w-8 h-8 bg-green-500 text-white rounded-lg flex items-center justify-center font-semibold text-sm mr-3\"\r\n // }, '2'),\r\n // React.createElement('h3', {\r\n // key: 'title',\r\n // className: \"text-lg font-medium text-primary\"\r\n // }, \"Select session type\")\r\n // ]),\r\n // React.createElement('p', {\r\n // key: 'description',\r\n // className: \"text-secondary text-sm mb-4\"\r\n // }, \"Choose a session plan or use limited demo mode for testing.\"),\r\n // React.createElement(SessionTypeSelector, {\r\n // key: 'session-selector',\r\n // onSelectType: (sessionType) => {\r\n // // Save the selected session type\r\n // setSelectedSessionType(sessionType);\r\n // console.log('\uD83C\uDFAF Session type selected:', sessionType);\r\n \r\n // // FIX: For demo sessions, we immediately call automatic activation\r\n // if (sessionType === 'demo') {\r\n // console.log('\uD83C\uDFAE Demo session selected, scheduling automatic activation...');\r\n // // Delay activation for 2 seconds to stabilize\r\n // setTimeout(() => {\r\n // if (sessionManager) {\r\n // console.log('\uD83D\uDE80 Triggering demo session activation from selection...');\r\n // handleDemoVerification();\r\n // }\r\n // }, 2000);\r\n // }\r\n \r\n // // Open a modal payment window\r\n // if (typeof window.showPaymentModal === 'function') {\r\n // window.showPaymentModal(sessionType);\r\n // } else {\r\n // // Fallback - show session information\r\n // console.log('Selected session type:', sessionType);\r\n // }\r\n // },\r\n // onCancel: resetToSelect,\r\n // sessionManager: window.sessionManager\r\n // })\r\n // ]),\r\n \r\n // Step 3 - Waiting for response\r\n showOfferStep && React.createElement('div', {\r\n key: 'step2',\r\n className: \"card-minimal rounded-xl p-6\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'step-header',\r\n className: \"flex items-center mb-4\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'number',\r\n className: \"w-8 h-8 bg-blue-500 text-white rounded-lg flex items-center justify-center font-semibold text-sm mr-3\"\r\n }, '2'),\r\n React.createElement('h3', {\r\n key: 'title',\r\n className: \"text-lg font-medium text-primary\"\r\n }, \"Waiting for the peer's response\")\r\n ]),\r\n React.createElement('p', {\r\n key: 'description',\r\n className: \"text-secondary text-sm mb-4\"\r\n }, \"Paste the encrypted invitation code from your contact.\"),\r\n React.createElement('div', {\r\n key: 'buttons',\r\n className: \"flex gap-2 mb-4\"\r\n }, [\r\n React.createElement('button', {\r\n key: 'scan-btn',\r\n onClick: () => setShowQRScannerModal(true),\r\n className: \"px-4 py-2 bg-purple-500/10 hover:bg-purple-500/20 text-purple-400 border border-purple-500/20 rounded text-sm font-medium transition-all duration-200\"\r\n }, [\r\n React.createElement('i', {\r\n key: 'icon',\r\n className: 'fas fa-qrcode mr-2'\r\n }),\r\n 'Scan QR Code'\r\n ])\r\n ]),\r\n React.createElement('textarea', {\r\n key: 'input',\r\n value: answerInput,\r\n onChange: (e) => {\r\n setAnswerInput(e.target.value);\r\n // Mark answer as created when user manually enters data\r\n if (e.target.value.trim().length > 0) {\r\n if (typeof markAnswerCreated === 'function') {\r\n markAnswerCreated();\r\n }\r\n }\r\n\r\n },\r\n rows: 6,\r\n placeholder: \"Paste the encrypted response code from your contact or scan QR code...\",\r\n className: \"w-full p-3 bg-custom-bg border border-gray-500/20 rounded-lg resize-none mb-4 text-secondary placeholder-gray-500 focus:border-orange-500/40 focus:outline-none transition-all custom-scrollbar text-sm\"\r\n }),\r\n React.createElement('button', {\r\n key: 'connect-btn',\r\n onClick: onConnect,\r\n disabled: !answerInput.trim(),\r\n className: \"w-full btn-secondary text-white py-3 px-4 rounded-lg font-medium transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-rocket mr-2'\r\n }),\r\n 'Establish connection'\r\n ])\r\n ])\r\n ])\r\n ]);\r\n }\r\n \r\n if (mode === 'join') {\r\n return React.createElement('div', {\r\n className: \"min-h-[calc(100vh-104px)] flex items-center justify-center p-4\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'join-flow',\r\n className: \"w-full max-w-3xl space-y-6\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'header',\r\n className: \"text-center\"\r\n }, [\r\n React.createElement('button', {\r\n key: 'back',\r\n onClick: resetToSelect,\r\n className: \"mb-4 text-secondary hover:text-primary transition-colors flex items-center mx-auto text-sm\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-arrow-left mr-2'\r\n }),\r\n 'Back to selection'\r\n ]),\r\n React.createElement('h2', {\r\n key: 'title',\r\n className: \"text-xl font-semibold text-primary mb-2\"\r\n }, 'Joining the secure channel')\r\n ]),\r\n \r\n (showAnswerStep ? null : React.createElement('div', {\r\n key: 'step1',\r\n className: \"card-minimal rounded-xl p-6\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'step-header',\r\n className: \"flex items-center mb-4\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'number',\r\n className: \"w-8 h-8 bg-green-500 text-white rounded-lg flex items-center justify-center font-semibold text-sm mr-3\"\r\n }, '1'),\r\n React.createElement('h3', {\r\n key: 'title',\r\n className: \"text-lg font-medium text-primary\"\r\n }, \"Paste secure invitation\")\r\n ]),\r\n React.createElement('p', {\r\n key: 'description',\r\n className: \"text-secondary text-sm mb-4\"\r\n }, \"Copy and paste the encrypted invitation code from the initiator.\"),\r\n React.createElement('textarea', {\r\n key: 'input',\r\n value: offerInput,\r\n onChange: (e) => {\r\n setOfferInput(e.target.value);\r\n if (e.target.value.trim().length > 0) {\r\n if (typeof markAnswerCreated === 'function') {\r\n markAnswerCreated();\r\n }\r\n }\r\n },\r\n rows: 8,\r\n placeholder: \"Paste the encrypted invitation code or scan QR code...\",\r\n className: \"w-full p-3 bg-custom-bg border border-gray-500/20 rounded-lg resize-none mb-4 text-secondary placeholder-gray-500 focus:border-green-500/40 focus:outline-none transition-all custom-scrollbar text-sm\"\r\n }),\r\n React.createElement('div', {\r\n key: 'buttons',\r\n className: \"flex gap-2 mb-4\"\r\n }, [\r\n React.createElement('button', {\r\n key: 'scan-btn',\r\n onClick: () => setShowQRScannerModal(true),\r\n className: \"px-4 py-2 bg-purple-500/10 hover:bg-purple-500/20 text-purple-400 border border-purple-500/20 rounded text-sm font-medium transition-all duration-200\"\r\n }, [\r\n React.createElement('i', {\r\n key: 'icon',\r\n className: 'fas fa-qrcode mr-2'\r\n }),\r\n 'Scan QR Code'\r\n ]),\r\n React.createElement('button', {\r\n key: 'process-btn',\r\n onClick: onCreateAnswer,\r\n disabled: !offerInput.trim() || connectionStatus === 'connecting',\r\n className: \"flex-1 btn-secondary text-white py-2 px-4 rounded-lg font-medium transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-cogs mr-2'\r\n }),\r\n 'Process invitation'\r\n ])\r\n ]),\r\n showQRScanner && React.createElement('div', {\r\n key: 'qr-scanner',\r\n className: \"p-4 bg-gray-800/50 border border-gray-600/30 rounded-lg text-center\"\r\n }, [\r\n React.createElement('h4', {\r\n key: 'scanner-title',\r\n className: \"text-sm font-medium text-primary mb-3\"\r\n }, 'QR Code Scanner'),\r\n React.createElement('p', {\r\n key: 'scanner-description',\r\n className: \"text-xs text-gray-400 mb-3\"\r\n }, 'Use your device camera to scan the QR code from the invitation'),\r\n React.createElement('button', {\r\n key: 'open-scanner',\r\n onClick: () => {\r\n if (typeof setShowQRScannerModal === 'function') {\r\n setShowQRScannerModal(true);\r\n } else {\r\n console.error('setShowQRScannerModal is not a function:', setShowQRScannerModal);\r\n }\r\n },\r\n className: \"w-full px-4 py-3 bg-purple-600 hover:bg-purple-500 text-white rounded-lg font-medium transition-all duration-200 mb-3\"\r\n }, [\r\n React.createElement('i', {\r\n key: 'camera-icon',\r\n className: 'fas fa-camera mr-2'\r\n }),\r\n 'Open Camera Scanner'\r\n ]),\r\n React.createElement('button', {\r\n key: 'test-qr',\r\n onClick: async () => {\r\n console.log('Creating test QR code...');\r\n if (window.generateQRCode) {\r\n const testData = '{\"type\":\"test\",\"message\":\"Hello QR Scanner!\"}';\r\n const qrUrl = await window.generateQRCode(testData);\r\n console.log('Test QR code generated:', qrUrl);\r\n const newWindow = window.open();\r\n newWindow.document.write(``);\r\n }\r\n },\r\n className: \"px-3 py-1 bg-green-600/20 hover:bg-green-600/30 text-green-300 border border-green-500/20 rounded text-xs font-medium transition-all duration-200 mr-2\"\r\n }, 'Test QR'),\r\n React.createElement('button', {\r\n key: 'close-scanner',\r\n onClick: () => setShowQRScanner(false),\r\n className: \"px-3 py-1 bg-gray-600/20 hover:bg-gray-600/30 text-gray-300 border border-gray-500/20 rounded text-xs font-medium transition-all duration-200\"\r\n }, 'Close Scanner')\r\n ])\r\n ])),\r\n \r\n // Step 2\r\n showAnswerStep && React.createElement('div', {\r\n key: 'step2',\r\n className: \"card-minimal rounded-xl p-6\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'step-header',\r\n className: \"flex items-center mb-4\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'number',\r\n className: \"step-number mr-3\"\r\n }, '2'),\r\n React.createElement('h3', {\r\n key: 'title',\r\n className: \"text-lg font-medium text-primary\"\r\n }, \"Sending a secure response\")\r\n ]),\r\n React.createElement('div', {\r\n key: 'success',\r\n className: \"p-3 bg-green-500/10 border border-green-500/20 rounded-lg mb-4\"\r\n }, [\r\n React.createElement('p', {\r\n className: \"text-green-400 text-sm font-medium flex items-center\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-check-circle mr-2'\r\n }),\r\n 'Secure response created! Send this code to the initiator:'\r\n ])\r\n ]),\r\n React.createElement('div', {\r\n key: 'answer-data',\r\n className: \"space-y-3 mb-4\"\r\n }, [\r\n // Raw JSON hidden intentionally; users copy compressed string or use QR\r\n React.createElement(EnhancedCopyButton, {\r\n key: 'copy',\r\n text: (() => {\r\n try {\r\n const min = typeof answerData === 'object' ? JSON.stringify(answerData) : (answerData || '');\r\n if (typeof window.encodeBinaryToPrefixed === 'function') {\r\n return window.encodeBinaryToPrefixed(min);\r\n }\r\n if (typeof window.compressToPrefixedGzip === 'function') {\r\n return window.compressToPrefixedGzip(min);\r\n }\r\n return min;\r\n } catch { return typeof answerData === 'object' ? JSON.stringify(answerData) : (answerData || ''); }\r\n })(),\r\n className: \"w-full px-3 py-2 bg-green-500/10 hover:bg-green-500/20 text-green-400 border border-green-500/20 rounded text-sm font-medium\"\r\n }, 'Copy response code')\r\n ]),\r\n // QR Code section for answer\r\n qrCodeUrl && React.createElement('div', {\r\n key: 'qr-container',\r\n className: \"mt-4 p-4 border border-gray-600/30 rounded-lg text-center\"\r\n }, [\r\n React.createElement('h4', {\r\n key: 'qr-title',\r\n className: \"text-sm font-medium text-primary mb-3\"\r\n }, 'Scan QR code to complete connection'),\r\n React.createElement('div', {\r\n key: 'qr-wrapper',\r\n className: \"flex justify-center\"\r\n }, [\r\n React.createElement('img', {\r\n key: 'qr-image',\r\n src: qrCodeUrl,\r\n alt: \"QR Code for secure response\",\r\n className: \"max-w-none h-auto border border-gray-600/30 rounded w-[20rem] sm:w-[24rem] md:w-[28rem] lg:w-[32rem]\"\r\n })\r\n ]),\r\n\r\n ((qrFramesTotal || 0) >= 1) && React.createElement('div', {\r\n key: 'qr-controls-below',\r\n className: \"mt-4 flex flex-col items-center gap-2\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'frame-indicator',\r\n className: \"text-xs text-gray-300\"\r\n }, `Frame ${Math.max(1, (qrFrameIndex || 1))}/${qrFramesTotal || 1}`),\r\n React.createElement('div', {\r\n key: 'control-buttons',\r\n className: \"flex gap-1\"\r\n }, [\r\n (qrFramesTotal || 0) > 1 && React.createElement('button', {\r\n key: 'prev-frame',\r\n onClick: prevQrFrame,\r\n className: \"w-6 h-6 bg-gray-600 hover:bg-gray-500 text-white rounded text-xs flex items-center justify-center\"\r\n }, '\u25C0'),\r\n React.createElement('button', {\r\n key: 'toggle-manual',\r\n onClick: toggleQrManualMode,\r\n className: `px-2 py-1 rounded text-xs font-medium ${\r\n qrManualMode \r\n ? 'bg-blue-500 text-white' \r\n : 'bg-gray-600 text-gray-300 hover:bg-gray-500'\r\n }`\r\n }, qrManualMode ? 'Manual' : 'Auto'),\r\n (qrFramesTotal || 0) > 1 && React.createElement('button', {\r\n key: 'next-frame',\r\n onClick: nextQrFrame,\r\n className: \"w-6 h-6 bg-gray-600 hover:bg-gray-500 text-white rounded text-xs flex items-center justify-center\"\r\n }, '\u25B6')\r\n ])\r\n ]),\r\n React.createElement('p', {\r\n key: 'qr-description',\r\n className: \"text-xs text-gray-400 mt-2\"\r\n }, 'The initiator can scan this QR code to complete the secure connection')\r\n ]),\r\n React.createElement('div', {\r\n key: 'info',\r\n className: \"p-3 bg-purple-500/10 border border-purple-500/20 rounded-lg\"\r\n }, [\r\n React.createElement('p', {\r\n className: \"text-purple-400 text-sm flex items-center justify-center\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-shield-alt mr-2'\r\n }),\r\n 'The connection will be established with verification'\r\n ])\r\n ])\r\n ])\r\n ])\r\n ]);\r\n }\r\n };\r\n \r\n // Global scroll function - defined outside components to ensure availability\r\n const createScrollToBottomFunction = (chatMessagesRef) => {\r\n return () => {\r\n if (chatMessagesRef && chatMessagesRef.current) {\r\n const scrollAttempt = () => {\r\n if (chatMessagesRef.current) {\r\n chatMessagesRef.current.scrollTo({\r\n top: chatMessagesRef.current.scrollHeight,\r\n behavior: 'smooth'\r\n });\r\n }\r\n };\r\n scrollAttempt();\r\n \r\n setTimeout(scrollAttempt, 50);\r\n setTimeout(scrollAttempt, 150);\r\n setTimeout(scrollAttempt, 300);\r\n \r\n requestAnimationFrame(() => {\r\n setTimeout(scrollAttempt, 100);\r\n });\r\n }\r\n };\r\n };\r\n \r\n const EnhancedChatInterface = ({\r\n messages,\r\n messageInput,\r\n setMessageInput,\r\n onSendMessage,\r\n onDisconnect,\r\n keyFingerprint,\r\n isVerified,\r\n chatMessagesRef,\r\n scrollToBottom,\r\n webrtcManager\r\n }) => {\r\n const [showScrollButton, setShowScrollButton] = React.useState(false);\r\n const [showFileTransfer, setShowFileTransfer] = React.useState(false);\r\n\r\n React.useEffect(() => {\r\n if (chatMessagesRef.current && messages.length > 0) {\r\n const { scrollTop, scrollHeight, clientHeight } = chatMessagesRef.current;\r\n const isNearBottom = scrollHeight - scrollTop - clientHeight < 100;\r\n if (isNearBottom) {\r\n const smoothScroll = () => {\r\n if (chatMessagesRef.current) {\r\n chatMessagesRef.current.scrollTo({\r\n top: chatMessagesRef.current.scrollHeight,\r\n behavior: 'smooth'\r\n });\r\n }\r\n };\r\n smoothScroll();\r\n setTimeout(smoothScroll, 50);\r\n setTimeout(smoothScroll, 150);\r\n }\r\n }\r\n }, [messages, chatMessagesRef]);\r\n \r\n // \u041E\u0431\u0440\u0430\u0431\u043E\u0442\u0447\u0438\u043A \u0441\u043A\u0440\u043E\u043B\u043B\u0430\r\n const handleScroll = () => {\r\n if (chatMessagesRef.current) {\r\n const { scrollTop, scrollHeight, clientHeight } = chatMessagesRef.current;\r\n const isNearBottom = scrollHeight - scrollTop - clientHeight < 100;\r\n setShowScrollButton(!isNearBottom);\r\n }\r\n };\r\n \r\n // \u041F\u0440\u043E\u043A\u0440\u0443\u0442\u043A\u0430 \u0432\u043D\u0438\u0437 \u043F\u043E \u043A\u043D\u043E\u043F\u043A\u0435\r\n const handleScrollToBottom = () => {\r\n console.log('\uD83D\uDD0D handleScrollToBottom called, scrollToBottom type:', typeof scrollToBottom);\r\n if (typeof scrollToBottom === 'function') {\r\n scrollToBottom();\r\n setShowScrollButton(false);\r\n } else {\r\n console.error('scrollToBottom is not a function:', scrollToBottom);\r\n // Fallback: direct scroll\r\n if (chatMessagesRef.current) {\r\n chatMessagesRef.current.scrollTo({\r\n top: chatMessagesRef.current.scrollHeight,\r\n behavior: 'smooth'\r\n });\r\n }\r\n setShowScrollButton(false);\r\n }\r\n };\r\n\r\n const handleKeyPress = (e) => {\r\n if (e.key === 'Enter' && !e.shiftKey) {\r\n e.preventDefault();\r\n onSendMessage();\r\n }\r\n };\r\n\r\n const isFileTransferReady = () => {\r\n if (!webrtcManager) return false;\r\n \r\n const connected = webrtcManager.isConnected ? webrtcManager.isConnected() : false;\r\n const verified = webrtcManager.isVerified || false;\r\n const hasDataChannel = webrtcManager.dataChannel && webrtcManager.dataChannel.readyState === 'open';\r\n \r\n return connected && verified && hasDataChannel;\r\n };\r\n \r\n // \u0412\u043E\u0437\u0432\u0440\u0430\u0442 JSX \u0447\u0435\u0440\u0435\u0437 React.createElement\r\n return React.createElement(\r\n 'div',\r\n {\r\n className: \"chat-container flex flex-col\",\r\n style: { backgroundColor: '#272827', height: 'calc(100vh - 64px)' }\r\n },\r\n [\r\n // \u041E\u0431\u043B\u0430\u0441\u0442\u044C \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0439\r\n React.createElement(\r\n 'div',\r\n { className: \"flex-1 flex flex-col overflow-hidden\" },\r\n React.createElement(\r\n 'div',\r\n { className: \"flex-1 max-w-4xl mx-auto w-full p-4 overflow-hidden\" },\r\n React.createElement(\r\n 'div',\r\n {\r\n ref: chatMessagesRef,\r\n onScroll: handleScroll,\r\n className: \"h-full overflow-y-auto space-y-3 hide-scrollbar pr-2 scroll-smooth\"\r\n },\r\n messages.length === 0 ?\r\n React.createElement(\r\n 'div',\r\n { className: \"flex items-center justify-center h-full\" },\r\n React.createElement(\r\n 'div',\r\n { className: \"text-center max-w-md\" },\r\n [\r\n React.createElement(\r\n 'div',\r\n { className: \"w-16 h-16 bg-green-500/10 border border-green-500/20 rounded-xl flex items-center justify-center mx-auto mb-4\" },\r\n React.createElement(\r\n 'svg',\r\n { className: \"w-8 h-8 text-green-500\", fill: \"none\", stroke: \"currentColor\", viewBox: \"0 0 24 24\" },\r\n React.createElement('path', {\r\n strokeLinecap: \"round\",\r\n strokeLinejoin: \"round\",\r\n strokeWidth: 2,\r\n d: \"M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z\"\r\n })\r\n )\r\n ),\r\n React.createElement('h3', { className: \"text-lg font-medium text-gray-300 mb-2\" }, \"Secure channel is ready!\"),\r\n React.createElement('p', { className: \"text-gray-400 text-sm mb-4\" }, \"All messages are protected by modern cryptographic algorithms\"),\r\n React.createElement(\r\n 'div',\r\n { className: \"text-left space-y-2\" },\r\n [\r\n ['End-to-end encryption', 'M5 13l4 4L19 7'],\r\n ['Protection against replay attacks', 'M5 13l4 4L19 7'],\r\n ['Integrity verification', 'M5 13l4 4L19 7'],\r\n ['Perfect Forward Secrecy', 'M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15']\r\n ].map(([text, d], i) =>\r\n React.createElement(\r\n 'div',\r\n { key: `f${i}`, className: \"flex items-center text-sm text-gray-400\" },\r\n [\r\n React.createElement(\r\n 'svg',\r\n {\r\n className: `w-4 h-4 mr-3 ${i === 3 ? 'text-purple-500' : 'text-green-500'}`,\r\n fill: \"none\",\r\n stroke: \"currentColor\",\r\n viewBox: \"0 0 24 24\"\r\n },\r\n React.createElement('path', {\r\n strokeLinecap: \"round\",\r\n strokeLinejoin: \"round\",\r\n strokeWidth: 2,\r\n d: d\r\n })\r\n ),\r\n text\r\n ]\r\n )\r\n )\r\n )\r\n ]\r\n )\r\n ) :\r\n messages.map((msg) =>\r\n React.createElement(EnhancedChatMessage, {\r\n key: msg.id,\r\n message: msg.message,\r\n type: msg.type,\r\n timestamp: msg.timestamp\r\n })\r\n )\r\n )\r\n )\r\n ),\r\n \r\n // \u041A\u043D\u043E\u043F\u043A\u0430 \u043F\u0440\u043E\u043A\u0440\u0443\u0442\u043A\u0438 \u0432\u043D\u0438\u0437\r\n showScrollButton &&\r\n React.createElement(\r\n 'button',\r\n {\r\n onClick: handleScrollToBottom,\r\n className: \"fixed right-6 w-12 h-12 bg-green-500/20 hover:bg-green-500/30 border border-green-500/30 text-green-400 rounded-full flex items-center justify-center transition-all duration-200 shadow-lg z-50\",\r\n style: { bottom: '160px' }\r\n },\r\n React.createElement(\r\n 'svg',\r\n { className: \"w-6 h-6\", fill: \"none\", stroke: \"currentColor\", viewBox: \"0 0 24 24\" },\r\n React.createElement('path', {\r\n strokeLinecap: \"round\",\r\n strokeLinejoin: \"round\",\r\n strokeWidth: 2,\r\n d: \"M19 14l-7 7m0 0l-7-7m7 7V3\"\r\n })\r\n )\r\n ),\r\n\r\n React.createElement(\r\n 'div',\r\n {\r\n className: \"flex-shrink-0 border-t border-gray-500/10\",\r\n style: { backgroundColor: '#272827' }\r\n },\r\n React.createElement(\r\n 'div',\r\n { className: \"max-w-4xl mx-auto px-4\" },\r\n [\r\n React.createElement(\r\n 'button',\r\n {\r\n onClick: () => setShowFileTransfer(!showFileTransfer),\r\n className: `flex items-center text-sm text-gray-400 hover:text-gray-300 transition-colors py-4 ${showFileTransfer ? 'mb-4' : ''}`\r\n },\r\n [\r\n React.createElement(\r\n 'svg',\r\n {\r\n className: `w-4 h-4 mr-2 transform transition-transform ${showFileTransfer ? 'rotate-180' : ''}`,\r\n fill: \"none\",\r\n stroke: \"currentColor\",\r\n viewBox: \"0 0 24 24\"\r\n },\r\n showFileTransfer ?\r\n React.createElement('path', {\r\n strokeLinecap: \"round\",\r\n strokeLinejoin: \"round\",\r\n strokeWidth: 2,\r\n d: \"M5 15l7-7 7 7\"\r\n }) :\r\n React.createElement('path', {\r\n strokeLinecap: \"round\",\r\n strokeLinejoin: \"round\",\r\n strokeWidth: 2,\r\n d: \"M15.172 7l-6.586 6.586a2 2 0 102.828 2.828l6.414-6.586a4 4 0 00-5.656-5.656l-6.415 6.585a6 6 0 108.486 8.486L20.5 13\"\r\n })\r\n ),\r\n showFileTransfer ? 'Hide file transfer' : 'Send files'\r\n ]\r\n ),\r\n showFileTransfer &&\r\n React.createElement(window.FileTransferComponent || (() => \r\n React.createElement('div', {\r\n className: \"p-4 text-center text-red-400\"\r\n }, 'FileTransferComponent not loaded')\r\n ), {\r\n webrtcManager: webrtcManager,\r\n isConnected: isFileTransferReady()\r\n })\r\n ]\r\n )\r\n ),\r\n\r\n React.createElement(\r\n 'div',\r\n { className: \"border-t border-gray-500/10\" },\r\n React.createElement(\r\n 'div',\r\n { className: \"max-w-4xl mx-auto p-4\" },\r\n React.createElement(\r\n 'div',\r\n { className: \"flex items-stretch space-x-3\" },\r\n [\r\n React.createElement(\r\n 'div',\r\n { className: \"flex-1 relative\" },\r\n [\r\n React.createElement('textarea', {\r\n value: messageInput,\r\n onChange: (e) => setMessageInput(e.target.value),\r\n onKeyDown: handleKeyPress,\r\n placeholder: \"Enter message to encrypt...\",\r\n rows: 2,\r\n maxLength: 2000,\r\n style: { backgroundColor: '#272827' },\r\n className: \"w-full p-3 border border-gray-600 rounded-lg resize-none text-gray-300 placeholder-gray-500 focus:border-green-500/40 focus:outline-none transition-all custom-scrollbar text-sm\"\r\n }),\r\n React.createElement(\r\n 'div',\r\n { className: \"absolute bottom-2 right-3 flex items-center space-x-2 text-xs text-gray-400\" },\r\n [\r\n React.createElement('span', null, `${messageInput.length}/2000`),\r\n React.createElement('span', null, \"\u2022 Enter to send\")\r\n ]\r\n )\r\n ]\r\n ),\r\n React.createElement(\r\n 'button',\r\n {\r\n onClick: onSendMessage,\r\n disabled: !messageInput.trim(),\r\n className: \"bg-green-400/20 text-green-400 p-3 rounded-lg transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center min-h-[72px]\"\r\n },\r\n React.createElement(\r\n 'svg',\r\n { className: \"w-6 h-6\", fill: \"none\", stroke: \"currentColor\", viewBox: \"0 0 24 24\" },\r\n React.createElement('path', {\r\n strokeLinecap: \"round\",\r\n strokeLinejoin: \"round\",\r\n strokeWidth: 2,\r\n d: \"M12 19l9 2-9-18-9 18 9-2zm0 0v-8\"\r\n })\r\n )\r\n )\r\n ]\r\n )\r\n )\r\n )\r\n ]\r\n );\r\n };\r\n \r\n \r\n // Main Enhanced Application Component\r\n const EnhancedSecureP2PChat = () => {\r\n\r\n const [messages, setMessages] = React.useState([]);\r\n const [connectionStatus, setConnectionStatus] = React.useState('disconnected');\r\n \r\n // Moved scrollToBottom logic to be available globally\r\n const [messageInput, setMessageInput] = React.useState('');\r\n const [offerData, setOfferData] = React.useState('');\r\n const [answerData, setAnswerData] = React.useState('');\r\n const [offerInput, setOfferInput] = React.useState('');\r\n const [answerInput, setAnswerInput] = React.useState('');\r\n const [keyFingerprint, setKeyFingerprint] = React.useState('');\r\n const [verificationCode, setVerificationCode] = React.useState('');\r\n const [showOfferStep, setShowOfferStep] = React.useState(false);\r\n const [showAnswerStep, setShowAnswerStep] = React.useState(false);\r\n const [showVerification, setShowVerification] = React.useState(false);\r\n const [showQRCode, setShowQRCode] = React.useState(false);\r\n const [qrCodeUrl, setQrCodeUrl] = React.useState('');\r\n const [showQRScanner, setShowQRScanner] = React.useState(false);\r\n const [showQRScannerModal, setShowQRScannerModal] = React.useState(false);\r\n const [isVerified, setIsVerified] = React.useState(false);\r\n const [securityLevel, setSecurityLevel] = React.useState(null);\r\n \r\n // Mutual verification states\r\n const [localVerificationConfirmed, setLocalVerificationConfirmed] = React.useState(false);\r\n const [remoteVerificationConfirmed, setRemoteVerificationConfirmed] = React.useState(false);\r\n const [bothVerificationsConfirmed, setBothVerificationsConfirmed] = React.useState(false);\r\n \r\n // PAKE password states removed - using SAS verification instead\r\n \r\n // Session state - all security features enabled by default\r\n const [sessionTimeLeft, setSessionTimeLeft] = React.useState(0);\r\n const [pendingSession, setPendingSession] = React.useState(null);\r\n \r\n // All security features are enabled by default - no payment required\r\n \r\n \r\n \r\n // ============================================\r\n // CENTRALIZED CONNECTION STATE MANAGEMENT\r\n // ============================================\r\n \r\n const [connectionState, setConnectionState] = React.useState({\r\n status: 'disconnected',\r\n hasActiveAnswer: false,\r\n answerCreatedAt: null,\r\n isUserInitiatedDisconnect: false\r\n });\r\n \r\n // Centralized connection state handler\r\n const updateConnectionState = (newState, options = {}) => {\r\n const { preserveAnswer = false, isUserAction = false } = options;\r\n \r\n setConnectionState(prev => ({\r\n ...prev,\r\n ...newState,\r\n isUserInitiatedDisconnect: isUserAction,\r\n hasActiveAnswer: preserveAnswer ? prev.hasActiveAnswer : false,\r\n answerCreatedAt: preserveAnswer ? prev.answerCreatedAt : null\r\n }));\r\n };\r\n \r\n // Check if we should preserve answer data\r\n const shouldPreserveAnswerData = () => {\r\n const now = Date.now();\r\n const answerAge = now - (connectionState.answerCreatedAt || 0);\r\n const maxPreserveTime = 300000;\r\n \r\n\r\n const hasAnswerData = (answerData && answerData.trim().length > 0) || \r\n (answerInput && answerInput.trim().length > 0);\r\n\r\n const hasAnswerQR = qrCodeUrl && qrCodeUrl.trim().length > 0;\r\n \r\n const shouldPreserve = (connectionState.hasActiveAnswer && \r\n answerAge < maxPreserveTime && \r\n !connectionState.isUserInitiatedDisconnect) ||\r\n (hasAnswerData && answerAge < maxPreserveTime && \r\n !connectionState.isUserInitiatedDisconnect) ||\r\n (hasAnswerQR && answerAge < maxPreserveTime && \r\n !connectionState.isUserInitiatedDisconnect);\r\n \r\n \r\n return shouldPreserve;\r\n };\r\n \r\n // Mark answer as created\r\n const markAnswerCreated = () => {\r\n updateConnectionState({\r\n hasActiveAnswer: true,\r\n answerCreatedAt: Date.now()\r\n });\r\n };\r\n \r\n // Global functions for cleanup\r\n React.useEffect(() => {\r\n window.forceCleanup = () => {\r\n handleClearData();\r\n if (webrtcManagerRef.current) {\r\n webrtcManagerRef.current.disconnect();\r\n }\r\n };\r\n\r\n window.clearLogs = () => {\r\n if (typeof console.clear === 'function') {\r\n console.clear();\r\n }\r\n };\r\n \r\n return () => {\r\n delete window.forceCleanup;\r\n delete window.clearLogs;\r\n };\r\n }, []);\r\n \r\n const webrtcManagerRef = React.useRef(null);\r\n // Expose for modules/UI that run outside this closure (e.g., inline handlers)\r\n // Safe because it's a ref object and we maintain it centrally here\r\n window.webrtcManagerRef = webrtcManagerRef;\r\n \r\n const addMessageWithAutoScroll = React.useCallback((message, type) => {\r\n const newMessage = {\r\n message,\r\n type,\r\n id: Date.now() + Math.random(),\r\n timestamp: Date.now()\r\n };\r\n \r\n setMessages(prev => {\r\n const updated = [...prev, newMessage];\r\n \r\n setTimeout(() => {\r\n if (chatMessagesRef?.current) {\r\n const container = chatMessagesRef.current;\r\n try {\r\n const { scrollTop, scrollHeight, clientHeight } = container;\r\n const isNearBottom = scrollHeight - scrollTop - clientHeight < 100;\r\n \r\n if (isNearBottom || prev.length === 0) {\r\n requestAnimationFrame(() => {\r\n if (container && container.scrollTo) {\r\n container.scrollTo({\r\n top: container.scrollHeight,\r\n behavior: 'smooth'\r\n });\r\n }\r\n });\r\n }\r\n } catch (error) {\r\n console.warn('Scroll error:', error);\r\n container.scrollTop = container.scrollHeight;\r\n }\r\n }\r\n }, 50);\r\n \r\n return updated;\r\n });\r\n }, []);\r\n \r\n // Update security level based on real verification\r\n const updateSecurityLevel = React.useCallback(async () => {\r\n if (window.isUpdatingSecurity) {\r\n return;\r\n }\r\n \r\n window.isUpdatingSecurity = true;\r\n \r\n try {\r\n if (webrtcManagerRef.current) {\r\n // All security features are enabled by default - always show MAXIMUM level\r\n setSecurityLevel({\r\n level: 'MAXIMUM',\r\n score: 100,\r\n color: 'green',\r\n details: 'All security features enabled by default',\r\n passedChecks: 10,\r\n totalChecks: 10,\r\n isRealData: true\r\n });\r\n \r\n if (window.DEBUG_MODE) {\r\n const currentLevel = webrtcManagerRef.current.ecdhKeyPair && webrtcManagerRef.current.ecdsaKeyPair \r\n ? await webrtcManagerRef.current.calculateSecurityLevel()\r\n : {\r\n level: 'MAXIMUM',\r\n score: 100,\r\n sessionType: 'premium',\r\n passedChecks: 10,\r\n totalChecks: 10\r\n };\r\n }\r\n }\r\n } catch (error) {\r\n console.error('Failed to update security level:', error);\r\n setSecurityLevel({\r\n level: 'ERROR',\r\n score: 0,\r\n color: 'red',\r\n details: 'Verification failed'\r\n });\r\n } finally {\r\n setTimeout(() => {\r\n window.isUpdatingSecurity = false;\r\n }, 2000);\r\n }\r\n }, []);\r\n \r\n // Session time ticker - unlimited sessions\r\n React.useEffect(() => {\r\n const timer = setInterval(() => {\r\n // Sessions are unlimited - no time restrictions\r\n setSessionTimeLeft(0);\r\n }, 1000);\r\n return () => clearInterval(timer);\r\n }, []);\r\n \r\n // Sessions are unlimited - no expiration handler needed\r\n \r\n // All security features are enabled by default - no demo sessions needed\r\n const chatMessagesRef = React.useRef(null);\r\n \r\n // Create scroll function using global helper\r\n const scrollToBottom = createScrollToBottomFunction(chatMessagesRef);\r\n \r\n // Auto-scroll when messages change\r\n React.useEffect(() => {\r\n if (messages.length > 0 && chatMessagesRef.current) {\r\n scrollToBottom();\r\n setTimeout(scrollToBottom, 50);\r\n setTimeout(scrollToBottom, 150);\r\n }\r\n }, [messages]);\r\n \r\n // PAKE password functions removed - using SAS verification instead\r\n \r\n React.useEffect(() => {\r\n // Prevent multiple initializations\r\n if (webrtcManagerRef.current) {\r\n console.log('\u26A0\uFE0F WebRTC Manager already initialized, skipping...');\r\n return;\r\n }\r\n \r\n const handleMessage = (message, type) => {\r\n if (typeof message === 'string' && message.trim().startsWith('{')) {\r\n try {\r\n const parsedMessage = JSON.parse(message);\r\n const blockedTypes = [\r\n 'file_transfer_start',\r\n 'file_transfer_response',\r\n 'file_chunk',\r\n 'chunk_confirmation',\r\n 'file_transfer_complete',\r\n 'file_transfer_error',\r\n 'heartbeat',\r\n 'verification',\r\n 'verification_response',\r\n 'verification_confirmed',\r\n 'verification_both_confirmed',\r\n 'peer_disconnect',\r\n 'key_rotation_signal',\r\n 'key_rotation_ready',\r\n 'security_upgrade'\r\n ];\r\n if (parsedMessage.type && blockedTypes.includes(parsedMessage.type)) {\r\n console.log(`Blocked system/file message from chat: ${parsedMessage.type}`);\r\n return; \r\n }\r\n } catch (parseError) {\r\n\r\n }\r\n }\r\n \r\n addMessageWithAutoScroll(message, type);\r\n };\r\n \r\n const handleStatusChange = (status) => {\r\n setConnectionStatus(status);\r\n \r\n if (status === 'connected') {\r\n document.dispatchEvent(new CustomEvent('new-connection'));\r\n \r\n // \u041D\u0435 \u0441\u043A\u0440\u044B\u0432\u0430\u0435\u043C \u0432\u0435\u0440\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u044E \u043F\u0440\u0438 'connected' - \u0442\u043E\u043B\u044C\u043A\u043E \u043F\u0440\u0438 'verified'\r\n // setIsVerified(true);\r\n // setShowVerification(false);\r\n if (!window.isUpdatingSecurity) {\r\n updateSecurityLevel().catch(console.error);\r\n }\r\n } else if (status === 'verifying') {\r\n setShowVerification(true);\r\n if (!window.isUpdatingSecurity) {\r\n updateSecurityLevel().catch(console.error);\r\n }\r\n } else if (status === 'verified') {\r\n setIsVerified(true);\r\n setShowVerification(false);\r\n setBothVerificationsConfirmed(true);\r\n setConnectionStatus('connected');\r\n // Force immediate update of isVerified state\r\n setTimeout(() => {\r\n setIsVerified(true);\r\n }, 0);\r\n if (!window.isUpdatingSecurity) {\r\n updateSecurityLevel().catch(console.error);\r\n }\r\n } else if (status === 'connecting') {\r\n if (!window.isUpdatingSecurity) {\r\n updateSecurityLevel().catch(console.error);\r\n }\r\n } else if (status === 'disconnected') {\r\n updateConnectionState({ status: 'disconnected' });\r\n setConnectionStatus('disconnected');\r\n\r\n if (shouldPreserveAnswerData()) {\r\n setIsVerified(false);\r\n setShowVerification(false);\r\n return;\r\n }\r\n\r\n setIsVerified(false);\r\n setShowVerification(false);\r\n \r\n // Dispatch disconnected event for SessionTimer\r\n document.dispatchEvent(new CustomEvent('disconnected'));\r\n \r\n // Clear verification states\r\n setLocalVerificationConfirmed(false);\r\n setRemoteVerificationConfirmed(false);\r\n setBothVerificationsConfirmed(false);\r\n \r\n // Clear connection data\r\n setOfferData(null);\r\n setAnswerData(null);\r\n setOfferInput('');\r\n setAnswerInput('');\r\n setShowOfferStep(false);\r\n setShowAnswerStep(false);\r\n setKeyFingerprint('');\r\n setVerificationCode('');\r\n setSecurityLevel(null);\r\n \r\n // Reset session and timer\r\n setSessionTimeLeft(0);\r\n \r\n // Return to main page after a short delay\r\n setTimeout(() => {\r\n setConnectionStatus('disconnected');\r\n setShowVerification(false);\r\n \r\n setOfferData(null);\r\n setAnswerData(null);\r\n setOfferInput('');\r\n setAnswerInput('');\r\n setShowOfferStep(false);\r\n setShowAnswerStep(false);\r\n setMessages([]);\r\n }, 1000);\r\n\r\n } else if (status === 'peer_disconnected') {\r\n setSessionTimeLeft(0);\r\n \r\n document.dispatchEvent(new CustomEvent('peer-disconnect'));\r\n \r\n // A short delay before clearing to display the status\r\n setTimeout(() => {\r\n setKeyFingerprint('');\r\n setVerificationCode('');\r\n setSecurityLevel(null);\r\n setIsVerified(false);\r\n setShowVerification(false);\r\n setConnectionStatus('disconnected');\r\n \r\n // Clear verification states\r\n setLocalVerificationConfirmed(false);\r\n setRemoteVerificationConfirmed(false);\r\n setBothVerificationsConfirmed(false);\r\n \r\n // Clear connection data\r\n setOfferData(null);\r\n setAnswerData(null);\r\n setOfferInput('');\r\n setAnswerInput('');\r\n setShowOfferStep(false);\r\n setShowAnswerStep(false);\r\n setMessages([]);\r\n \r\n\r\n if (typeof console.clear === 'function') {\r\n console.clear();\r\n }\r\n\r\n }, 2000);\r\n }\r\n };\r\n \r\n const handleKeyExchange = (fingerprint) => {\r\n if (fingerprint === '') {\r\n setKeyFingerprint('');\r\n } else {\r\n setKeyFingerprint(fingerprint);\r\n }\r\n };\r\n \r\n const handleVerificationRequired = (code) => {\r\n if (code === '') {\r\n setVerificationCode('');\r\n setShowVerification(false);\r\n } else {\r\n setVerificationCode(code);\r\n setShowVerification(true);\r\n }\r\n };\r\n \r\n const handleVerificationStateChange = (state) => {\r\n setLocalVerificationConfirmed(state.localConfirmed);\r\n setRemoteVerificationConfirmed(state.remoteConfirmed);\r\n setBothVerificationsConfirmed(state.bothConfirmed);\r\n };\r\n \r\n // Callback for handling response errors\r\n const handleAnswerError = (errorType, errorMessage) => {\r\n if (errorType === 'replay_attack') {\r\n // Reset the session upon replay attack\r\n setSessionTimeLeft(0);\r\n setPendingSession(null);\r\n \r\n addMessageWithAutoScroll('\uD83D\uDCA1 Data is outdated. Please create a new invitation or use a current response code.', 'system');\r\n \r\n if (typeof console.clear === 'function') {\r\n console.clear();\r\n }\r\n } else if (errorType === 'security_violation') {\r\n // Reset the session upon security breach\r\n setSessionTimeLeft(0);\r\n setPendingSession(null);\r\n \r\n addMessageWithAutoScroll(` Security breach: ${errorMessage}`, 'system');\r\n \r\n if (typeof console.clear === 'function') {\r\n console.clear();\r\n }\r\n }\r\n };\r\n \r\n \r\n if (typeof console.clear === 'function') {\r\n console.clear();\r\n }\r\n \r\n webrtcManagerRef.current = new EnhancedSecureWebRTCManager(\r\n handleMessage, \r\n handleStatusChange, \r\n handleKeyExchange,\r\n handleVerificationRequired,\r\n handleAnswerError,\r\n handleVerificationStateChange\r\n );\r\n \r\n handleMessage(' SecureBit.chat Enhanced Security Edition v4.2.12 - 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');\r\n \r\n const handleBeforeUnload = (event) => {\r\n if (event.type === 'beforeunload' && !isTabSwitching) {\r\n \r\n if (webrtcManagerRef.current && webrtcManagerRef.current.isConnected()) {\r\n try {\r\n webrtcManagerRef.current.sendSystemMessage({\r\n type: 'peer_disconnect',\r\n reason: 'user_disconnect',\r\n timestamp: Date.now()\r\n });\r\n } catch (error) {\r\n }\r\n \r\n setTimeout(() => {\r\n if (webrtcManagerRef.current) {\r\n webrtcManagerRef.current.disconnect();\r\n }\r\n }, 100);\r\n } else if (webrtcManagerRef.current) {\r\n webrtcManagerRef.current.disconnect();\r\n }\r\n } else if (isTabSwitching) {\r\n event.preventDefault();\r\n event.returnValue = '';\r\n }\r\n };\r\n \r\n window.addEventListener('beforeunload', handleBeforeUnload);\r\n \r\n let isTabSwitching = false;\r\n let tabSwitchTimeout = null;\r\n \r\n const handleVisibilityChange = () => {\r\n if (document.visibilityState === 'hidden') {\r\n isTabSwitching = true;\r\n \r\n if (tabSwitchTimeout) {\r\n clearTimeout(tabSwitchTimeout);\r\n }\r\n \r\n tabSwitchTimeout = setTimeout(() => {\r\n isTabSwitching = false;\r\n }, 5000); \r\n \r\n } else if (document.visibilityState === 'visible') {\r\n isTabSwitching = false;\r\n \r\n if (tabSwitchTimeout) {\r\n clearTimeout(tabSwitchTimeout);\r\n tabSwitchTimeout = null;\r\n }\r\n }\r\n };\r\n \r\n document.addEventListener('visibilitychange', handleVisibilityChange);\r\n \r\n // Setup file transfer callbacks\r\n if (webrtcManagerRef.current) {\r\n webrtcManagerRef.current.setFileTransferCallbacks(\r\n // Progress callback\r\n (progress) => {\r\n console.log('File progress:', progress);\r\n },\r\n \r\n // File received callback\r\n (fileData) => {\r\n const sizeMb = Math.max(1, Math.round((fileData.fileSize || 0) / (1024 * 1024)));\r\n const downloadMessage = React.createElement('div', {\r\n className: 'flex items-center space-x-2'\r\n }, [\r\n React.createElement('span', { key: 'label' }, ` File received: ${fileData.fileName} (${sizeMb} MB)`),\r\n React.createElement('button', {\r\n key: 'btn',\r\n className: 'px-3 py-1 rounded bg-blue-600 hover:bg-blue-700 text-white text-xs',\r\n onClick: async () => {\r\n try {\r\n const url = await fileData.getObjectURL();\r\n const a = document.createElement('a');\r\n a.href = url;\r\n a.download = fileData.fileName;\r\n a.click();\r\n setTimeout(() => fileData.revokeObjectURL(url), 15000);\r\n } catch (e) {\r\n console.error('Download failed:', e);\r\n addMessageWithAutoScroll(` File upload error: ${String(e?.message || e)}`, 'system');\r\n }\r\n }\r\n }, 'Download')\r\n ]);\r\n \r\n addMessageWithAutoScroll(downloadMessage, 'system');\r\n },\r\n \r\n // Error callback\r\n (error) => {\r\n console.error('File transfer error:', error);\r\n \r\n if (error.includes('Connection not ready')) {\r\n addMessageWithAutoScroll(` File transfer error: connection not ready. Try again later.`, 'system');\r\n } else if (error.includes('File too large')) {\r\n addMessageWithAutoScroll(` File is too big. Maximum size: 100 MB`, 'system');\r\n } else {\r\n addMessageWithAutoScroll(` File transfer error: ${error}`, 'system');\r\n }\r\n }\r\n );\r\n }\r\n \r\n return () => {\r\n window.removeEventListener('beforeunload', handleBeforeUnload);\r\n document.removeEventListener('visibilitychange', handleVisibilityChange);\r\n \r\n if (tabSwitchTimeout) {\r\n clearTimeout(tabSwitchTimeout);\r\n tabSwitchTimeout = null;\r\n }\r\n \r\n if (webrtcManagerRef.current) {\r\n webrtcManagerRef.current.disconnect();\r\n webrtcManagerRef.current = null;\r\n }\r\n };\r\n }, []); // Empty dependency array to run only once\r\n \r\n // All security features are enabled by default - no session purchase needed\r\n \r\n const compressOfferData = (offerData) => {\r\n try {\r\n // Parse the offer data if it's a string\r\n const offer = typeof offerData === 'string' ? JSON.parse(offerData) : offerData;\r\n \r\n // Create a minimal version with only the most essential data\r\n const minimalOffer = {\r\n type: offer.type,\r\n version: offer.version,\r\n timestamp: offer.timestamp,\r\n sessionId: offer.sessionId,\r\n connectionId: offer.connectionId,\r\n verificationCode: offer.verificationCode,\r\n salt: offer.salt,\r\n // Use only key fingerprints instead of full keys\r\n keyFingerprints: offer.keyFingerprints,\r\n // Add a reference to get full data\r\n fullDataAvailable: true,\r\n compressionLevel: 'minimal'\r\n };\r\n \r\n return JSON.stringify(minimalOffer);\r\n } catch (error) {\r\n console.error('Error compressing offer data:', error);\r\n return offerData; // Return original if compression fails\r\n }\r\n };\r\n\r\n const createQRReference = (offerData) => {\r\n try {\r\n // Create a unique reference ID for this offer\r\n const referenceId = `offer_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\r\n \r\n // Store the full offer data in localStorage with the reference ID\r\n localStorage.setItem(`qr_offer_${referenceId}`, JSON.stringify(offerData));\r\n \r\n // Create a minimal QR code with just the reference\r\n const qrReference = {\r\n type: 'secure_offer_reference',\r\n referenceId: referenceId,\r\n timestamp: Date.now(),\r\n message: 'Scan this QR code and use the reference ID to get full offer data'\r\n };\r\n \r\n return JSON.stringify(qrReference);\r\n } catch (error) {\r\n console.error('Error creating QR reference:', error);\r\n return null;\r\n }\r\n };\r\n\r\n const createTemplateOffer = (offer) => {\r\n // Minimal template to keep QR within single image capacity\r\n const templateOffer = {\r\n type: 'enhanced_secure_offer_template',\r\n version: '4.0',\r\n sessionId: offer.sessionId,\r\n connectionId: offer.connectionId,\r\n verificationCode: offer.verificationCode,\r\n timestamp: offer.timestamp,\r\n // Avoid bulky fields (SDP, raw keys); keep only fingerprints and essentials\r\n keyFingerprints: offer.keyFingerprints,\r\n // Keep concise auth hints (omit large nonces)\r\n authChallenge: offer?.authChallenge?.challenge,\r\n // Optionally include a compact capability hint if small\r\n capabilities: Array.isArray(offer.capabilities) && offer.capabilities.length <= 5\r\n ? offer.capabilities\r\n : undefined\r\n };\r\n \r\n return templateOffer;\r\n };\r\n\r\n // Conservative QR payload limits (characters). Adjust per error correction level.\r\n const MAX_QR_LEN = 800; // for JSON/plain/gzip\r\n const BIN_MAX_QR_LEN = 400; // stricter for SB1:bin to improve scan reliability\r\n const [qrFramesTotal, setQrFramesTotal] = React.useState(0);\r\n const [qrFrameIndex, setQrFrameIndex] = React.useState(0);\r\n const [qrManualMode, setQrManualMode] = React.useState(false);\r\n\r\n // Animated QR state (for multi-chunk COSE)\r\n const qrAnimationRef = React.useRef({ timer: null, chunks: [], idx: 0, active: false });\r\n const stopQrAnimation = () => {\r\n try { if (qrAnimationRef.current.timer) { clearInterval(qrAnimationRef.current.timer); } } catch {}\r\n qrAnimationRef.current = { timer: null, chunks: [], idx: 0, active: false };\r\n setQrFrameIndex(0);\r\n setQrFramesTotal(0);\r\n setQrManualMode(false);\r\n };\r\n\r\n // Render frame at current index (no index mutation)\r\n const renderCurrent = async () => {\r\n const { chunks, idx } = qrAnimationRef.current || {};\r\n if (!chunks || !chunks.length) return;\r\n const current = chunks[idx % chunks.length];\r\n try {\r\n const isDesktop = (typeof window !== 'undefined') && ((window.innerWidth || 0) >= 1024);\r\n const QR_SIZE = isDesktop ? 720 : 512;\r\n const url = await (window.generateQRCode ? window.generateQRCode(current, { errorCorrectionLevel: 'M', margin: 2, size: QR_SIZE }) : Promise.resolve(''));\r\n if (url) setQrCodeUrl(url);\r\n } catch (e) {\r\n console.warn('Animated QR render error (current):', e);\r\n }\r\n setQrFrameIndex(((qrAnimationRef.current?.idx || 0) % (qrAnimationRef.current?.chunks?.length || 1)) + 1);\r\n };\r\n\r\n // Render current frame, then advance index by 1\r\n const renderAndAdvance = async () => {\r\n await renderCurrent();\r\n const len = qrAnimationRef.current?.chunks?.length || 0;\r\n if (len > 0) {\r\n const nextIdx = ((qrAnimationRef.current?.idx || 0) + 1) % len;\r\n qrAnimationRef.current.idx = nextIdx;\r\n setQrFrameIndex(nextIdx + 1);\r\n }\r\n };\r\n\r\n const toggleQrManualMode = () => {\r\n const newManualMode = !qrManualMode;\r\n setQrManualMode(newManualMode);\r\n \r\n if (newManualMode) {\r\n\r\n if (qrAnimationRef.current.timer) {\r\n clearInterval(qrAnimationRef.current.timer);\r\n qrAnimationRef.current.timer = null;\r\n }\r\n console.log('QR Manual mode enabled - auto-scroll stopped');\r\n } else {\r\n if (qrAnimationRef.current.chunks.length > 1) {\r\n const intervalMs = 3000;\r\n qrAnimationRef.current.active = true;\r\n clearInterval(qrAnimationRef.current.timer);\r\n qrAnimationRef.current.timer = setInterval(renderAndAdvance, intervalMs);\r\n }\r\n console.log('QR Manual mode disabled - auto-scroll resumed');\r\n }\r\n };\r\n\r\n const nextQrFrame = async () => {\r\n console.log('\uD83C\uDFAE nextQrFrame called, qrFramesTotal:', qrFramesTotal, 'qrAnimationRef.current:', qrAnimationRef.current);\r\n if (qrAnimationRef.current.chunks.length > 1) {\r\n const nextIdx = (qrAnimationRef.current.idx + 1) % qrAnimationRef.current.chunks.length;\r\n qrAnimationRef.current.idx = nextIdx;\r\n setQrFrameIndex(nextIdx + 1);\r\n console.log('\uD83C\uDFAE Next frame index:', nextIdx + 1);\r\n // Ensure auto-advance timer runs in manual mode too\r\n try { clearInterval(qrAnimationRef.current.timer); } catch {}\r\n qrAnimationRef.current.timer = null;\r\n await renderCurrent();\r\n // If not in manual mode, restart auto timer\r\n if (!qrManualMode && qrAnimationRef.current.chunks.length > 1) {\r\n const intervalMs = 3000;\r\n qrAnimationRef.current.active = true;\r\n qrAnimationRef.current.timer = setInterval(renderAndAdvance, intervalMs);\r\n } else {\r\n qrAnimationRef.current.active = false;\r\n }\r\n } else {\r\n console.log('\uD83C\uDFAE No multiple frames to navigate');\r\n }\r\n };\r\n\r\n const prevQrFrame = async () => {\r\n console.log('\uD83C\uDFAE prevQrFrame called, qrFramesTotal:', qrFramesTotal, 'qrAnimationRef.current:', qrAnimationRef.current);\r\n if (qrAnimationRef.current.chunks.length > 1) {\r\n const prevIdx = (qrAnimationRef.current.idx - 1 + qrAnimationRef.current.chunks.length) % qrAnimationRef.current.chunks.length;\r\n qrAnimationRef.current.idx = prevIdx;\r\n setQrFrameIndex(prevIdx + 1);\r\n console.log('\uD83C\uDFAE Previous frame index:', prevIdx + 1);\r\n try { clearInterval(qrAnimationRef.current.timer); } catch {}\r\n qrAnimationRef.current.timer = null;\r\n await renderCurrent();\r\n if (!qrManualMode && qrAnimationRef.current.chunks.length > 1) {\r\n const intervalMs = 3000;\r\n qrAnimationRef.current.active = true;\r\n qrAnimationRef.current.timer = setInterval(renderAndAdvance, intervalMs);\r\n } else {\r\n qrAnimationRef.current.active = false;\r\n }\r\n } else {\r\n console.log('\uD83C\uDFAE No multiple frames to navigate');\r\n }\r\n };\r\n\r\n // Buffer for assembling scanned COSE chunks\r\n const qrChunksBufferRef = React.useRef({ id: null, total: 0, seen: new Set(), items: [] });\r\n\r\n const generateQRCode = async (data) => {\r\n try {\r\n const originalSize = typeof data === 'string' ? data.length : JSON.stringify(data).length;\r\n const isDesktop = (typeof window !== 'undefined') && ((window.innerWidth || 0) >= 1024);\r\n const QR_SIZE = isDesktop ? 720 : 512;\r\n \r\n // Try binary format first (CBOR + deflate + base64url)\r\n if (typeof window.generateBinaryQRCodeFromObject === 'function') {\r\n try {\r\n const obj = typeof data === 'string' ? JSON.parse(data) : data;\r\n const qrDataUrl = await window.generateBinaryQRCodeFromObject(obj, { errorCorrectionLevel: 'M', size: QR_SIZE, margin: 2 });\r\n if (qrDataUrl) {\r\n try { if (qrAnimationRef.current && qrAnimationRef.current.timer) { clearInterval(qrAnimationRef.current.timer); } } catch {}\r\n qrAnimationRef.current = { timer: null, chunks: [], idx: 0, active: false };\r\n setQrFrameIndex(0);\r\n setQrFramesTotal(0);\r\n setQrManualMode(false);\r\n setQrCodeUrl(qrDataUrl);\r\n setQrFramesTotal(1);\r\n setQrFrameIndex(1);\r\n return;\r\n }\r\n } catch (e) {\r\n console.warn('Binary QR generation failed, falling back to compressed:', e?.message || e);\r\n }\r\n }\r\n \r\n // Fallback to compressed JSON\r\n if (typeof window.generateCompressedQRCode === 'function') {\r\n try {\r\n const payload = typeof data === 'string' ? data : JSON.stringify(data);\r\n const qrDataUrl = await window.generateCompressedQRCode(payload, { errorCorrectionLevel: 'M', size: QR_SIZE, margin: 2 });\r\n if (qrDataUrl) {\r\n try { if (qrAnimationRef.current && qrAnimationRef.current.timer) { clearInterval(qrAnimationRef.current.timer); } } catch {}\r\n qrAnimationRef.current = { timer: null, chunks: [], idx: 0, active: false };\r\n setQrFrameIndex(0);\r\n setQrFramesTotal(0);\r\n setQrManualMode(false);\r\n setQrCodeUrl(qrDataUrl);\r\n setQrFramesTotal(1);\r\n setQrFrameIndex(1);\r\n return;\r\n }\r\n } catch (e) {\r\n console.warn('Compressed QR generation failed, falling back to plain:', e?.message || e);\r\n }\r\n }\r\n \r\n // Final fallback to plain JSON\r\n const payload = typeof data === 'string' ? data : JSON.stringify(data);\r\n if (payload.length <= MAX_QR_LEN) {\r\n if (!window.generateQRCode) throw new Error('QR code generator unavailable');\r\n try { if (qrAnimationRef.current && qrAnimationRef.current.timer) { clearInterval(qrAnimationRef.current.timer); } } catch {}\r\n qrAnimationRef.current = { timer: null, chunks: [], idx: 0, active: false };\r\n setQrFrameIndex(0);\r\n setQrFramesTotal(0);\r\n setQrManualMode(false);\r\n const qrDataUrl = await window.generateQRCode(payload, { errorCorrectionLevel: 'M', size: QR_SIZE, margin: 2 });\r\n setQrCodeUrl(qrDataUrl);\r\n setQrFramesTotal(1);\r\n setQrFrameIndex(1);\r\n return;\r\n }\r\n\r\n // Large payload: \u0440\u0430\u0437\u0431\u0438\u0432\u0430\u0435\u043C \u043D\u0430 \u0444\u0440\u0435\u0439\u043C\u044B (plain JSON)\r\n try { if (qrAnimationRef.current && qrAnimationRef.current.timer) { clearInterval(qrAnimationRef.current.timer); } } catch {}\r\n qrAnimationRef.current = { timer: null, chunks: [], idx: 0, active: false };\r\n setQrFrameIndex(0);\r\n setQrFramesTotal(0);\r\n setQrManualMode(false);\r\n const id = `raw_${Date.now()}_${Math.random().toString(36).slice(2)}`;\r\n\r\n const TARGET_CHUNKS = 10;\r\n const FRAME_MAX = Math.max(200, Math.floor(payload.length / TARGET_CHUNKS));\r\n const total = Math.ceil(payload.length / FRAME_MAX);\r\n const rawChunks = [];\r\n for (let i = 0; i < total; i++) {\r\n const seq = i + 1;\r\n const part = payload.slice(i * FRAME_MAX, (i + 1) * FRAME_MAX);\r\n rawChunks.push(JSON.stringify({ hdr: { v: 1, id, seq, total, rt: 'raw' }, body: part }));\r\n }\r\n if (!window.generateQRCode) throw new Error('QR code generator unavailable');\r\n if (rawChunks.length === 1) {\r\n const url = await window.generateQRCode(rawChunks[0], { errorCorrectionLevel: 'M', margin: 2, size: QR_SIZE });\r\n setQrCodeUrl(url);\r\n setQrFramesTotal(1);\r\n setQrFrameIndex(1);\r\n return;\r\n }\r\n qrAnimationRef.current.chunks = rawChunks;\r\n qrAnimationRef.current.idx = 0;\r\n qrAnimationRef.current.active = true;\r\n setQrFramesTotal(rawChunks.length);\r\n setQrFrameIndex(1);\r\n const EC_OPTS = { errorCorrectionLevel: 'M', margin: 2, size: QR_SIZE };\r\n await renderNext();\r\n\r\n if (!qrManualMode) {\r\n const intervalMs = 4000; // 4 seconds per frame for better readability\r\n qrAnimationRef.current.active = true;\r\n qrAnimationRef.current.timer = setInterval(renderAndAdvance, intervalMs);\r\n }\r\n return;\r\n } catch (error) {\r\n console.error('QR code generation failed:', error);\r\n setMessages(prev => [...prev, {\r\n message: ` QR code generation failed: ${error.message}`,\r\n type: 'error'\r\n }]);\r\n }\r\n };\r\n\r\n const reconstructFromTemplate = (templateData) => {\r\n // Reconstruct full offer from template\r\n const fullOffer = {\r\n type: \"enhanced_secure_offer\",\r\n version: templateData.version,\r\n timestamp: templateData.timestamp,\r\n sessionId: templateData.sessionId,\r\n connectionId: templateData.connectionId,\r\n verificationCode: templateData.verificationCode,\r\n salt: templateData.salt,\r\n sdp: templateData.sdp,\r\n keyFingerprints: templateData.keyFingerprints,\r\n capabilities: templateData.capabilities,\r\n \r\n // Reconstruct ECDH key object\r\n ecdhPublicKey: {\r\n keyType: \"ECDH\",\r\n keyData: templateData.ecdhKeyData,\r\n timestamp: templateData.timestamp - 1000, // Approximate\r\n version: templateData.version,\r\n signature: templateData.ecdhSignature\r\n },\r\n \r\n // Reconstruct ECDSA key object\r\n ecdsaPublicKey: {\r\n keyType: \"ECDSA\",\r\n keyData: templateData.ecdsaKeyData,\r\n timestamp: templateData.timestamp - 999, // Approximate\r\n version: templateData.version,\r\n signature: templateData.ecdsaSignature\r\n },\r\n \r\n // Reconstruct auth challenge\r\n authChallenge: {\r\n challenge: templateData.authChallenge,\r\n timestamp: templateData.timestamp,\r\n nonce: templateData.authNonce,\r\n version: templateData.version\r\n },\r\n \r\n // Generate security level (can be recalculated)\r\n securityLevel: {\r\n level: \"CRITICAL\",\r\n score: 20,\r\n color: \"red\",\r\n verificationResults: {\r\n encryption: { passed: false, details: \"Encryption not working\", points: 0 },\r\n keyExchange: { passed: true, details: \"Simple key exchange verified\", points: 15 },\r\n messageIntegrity: { passed: false, details: \"Message integrity failed\", points: 0 },\r\n rateLimiting: { passed: true, details: \"Rate limiting active\", points: 5 },\r\n ecdsa: { passed: false, details: \"Enhanced session required - feature not available\", points: 0 },\r\n metadataProtection: { passed: false, details: \"Enhanced session required - feature not available\", points: 0 },\r\n pfs: { passed: false, details: \"Enhanced session required - feature not available\", points: 0 },\r\n nestedEncryption: { passed: false, details: \"Enhanced session required - feature not available\", points: 0 },\r\n packetPadding: { passed: false, details: \"Enhanced session required - feature not available\", points: 0 },\r\n advancedFeatures: { passed: false, details: \"Premium session required - feature not available\", points: 0 }\r\n },\r\n timestamp: templateData.timestamp,\r\n details: \"Real verification: 20/100 security checks passed (2/4 available)\",\r\n isRealData: true,\r\n passedChecks: 2,\r\n totalChecks: 4,\r\n sessionType: \"demo\",\r\n maxPossibleScore: 50\r\n }\r\n };\r\n \r\n return fullOffer;\r\n };\r\n\r\n const handleQRScan = async (scannedData) => {\r\n try {\r\n console.log('QR Code scanned:', scannedData.substring(0, 100) + '...');\r\n console.log('Current buffer state:', qrChunksBufferRef.current);\r\n \r\n // Check if this is a binary chunk (starts with SB1:bin: or is a raw binary chunk)\r\n if (scannedData.startsWith('SB1:bin:') || (qrChunksBufferRef.current && qrChunksBufferRef.current.id)) {\r\n console.log('Binary chunk detected:', scannedData.substring(0, 50) + '...');\r\n \r\n // This is a binary chunk - add to buffer\r\n if (!qrChunksBufferRef.current.id) {\r\n console.log('Initializing buffer for binary chunks');\r\n // Initialize buffer for binary chunks\r\n qrChunksBufferRef.current = { \r\n id: `bin_${Date.now()}`, \r\n total: 4, // We expect 4 chunks\r\n seen: new Set(), \r\n items: [],\r\n lastUpdateMs: Date.now()\r\n };\r\n }\r\n \r\n // Add chunk to buffer (use data hash as identifier)\r\n const chunkHash = scannedData.substring(0, 50); // Use first 50 chars as hash\r\n \r\n // Check if this chunk was already scanned\r\n if (qrChunksBufferRef.current.seen.has(chunkHash)) {\r\n console.log(`Chunk already scanned, ignoring...`);\r\n return Promise.resolve(false);\r\n }\r\n \r\n qrChunksBufferRef.current.seen.add(chunkHash);\r\n qrChunksBufferRef.current.items.push(scannedData);\r\n qrChunksBufferRef.current.lastUpdateMs = Date.now();\r\n \r\n // Emit progress and force re-render\r\n try {\r\n const uniqueCount = qrChunksBufferRef.current.seen.size;\r\n document.dispatchEvent(new CustomEvent('qr-scan-progress', { \r\n detail: { \r\n id: qrChunksBufferRef.current.id, \r\n seq: uniqueCount, \r\n total: qrChunksBufferRef.current.total \r\n } \r\n }));\r\n \r\n // Force re-render to update progress indicator\r\n setQrFramesTotal(qrChunksBufferRef.current.total);\r\n setQrFrameIndex(uniqueCount);\r\n } catch {}\r\n \r\n // Check if we have all chunks\r\n const isComplete = qrChunksBufferRef.current.seen.size >= qrChunksBufferRef.current.total;\r\n console.log(`Chunks collected: ${qrChunksBufferRef.current.seen.size}/${qrChunksBufferRef.current.total}, complete: ${isComplete}`);\r\n \r\n if (!isComplete) {\r\n // Keep scanner open for more chunks\r\n console.log(`Scanned chunk ${qrChunksBufferRef.current.seen.size}/${qrChunksBufferRef.current.total}, waiting for more...`);\r\n return Promise.resolve(false);\r\n }\r\n \r\n // All chunks collected - reconstruct binary data\r\n try {\r\n const fullBinaryData = qrChunksBufferRef.current.items.join('');\r\n // Store the original binary data, not decoded JSON\r\n if (showOfferStep) {\r\n setAnswerInput(fullBinaryData);\r\n } else {\r\n setOfferInput(fullBinaryData);\r\n }\r\n \r\n setMessages(prev => [...prev, { \r\n message: 'All binary chunks captured. Payload reconstructed.', \r\n type: 'success' \r\n }]);\r\n \r\n // Clear buffer and close scanner\r\n qrChunksBufferRef.current = { id: null, total: 0, seen: new Set(), items: [] };\r\n setShowQRScannerModal(false);\r\n return Promise.resolve(true);\r\n } catch (e) {\r\n console.warn('Binary chunks reconstruction failed:', e);\r\n return Promise.resolve(false);\r\n }\r\n }\r\n \r\n // Check if this might be a binary chunk (long string without JSON structure)\r\n if (scannedData.length > 100 && !scannedData.startsWith('{') && !scannedData.startsWith('[')) {\r\n console.log('Detected potential binary chunk (long non-JSON string):', scannedData.substring(0, 50) + '...');\r\n \r\n // Initialize buffer if not exists\r\n if (!qrChunksBufferRef.current.id) {\r\n console.log('Initializing buffer for potential binary chunks');\r\n qrChunksBufferRef.current = { \r\n id: `bin_${Date.now()}`, \r\n total: 4, // We expect 4 chunks\r\n seen: new Set(), \r\n items: [],\r\n lastUpdateMs: Date.now()\r\n };\r\n }\r\n \r\n // Add chunk to buffer (use data hash as identifier)\r\n const chunkHash = scannedData.substring(0, 50); // Use first 50 chars as hash\r\n \r\n // Check if this chunk was already scanned\r\n if (qrChunksBufferRef.current.seen.has(chunkHash)) {\r\n console.log(`Chunk already scanned, ignoring...`);\r\n return Promise.resolve(false);\r\n }\r\n \r\n qrChunksBufferRef.current.seen.add(chunkHash);\r\n qrChunksBufferRef.current.items.push(scannedData);\r\n qrChunksBufferRef.current.lastUpdateMs = Date.now();\r\n \r\n // Force re-render to update progress indicator\r\n try {\r\n const uniqueCount = qrChunksBufferRef.current.seen.size;\r\n document.dispatchEvent(new CustomEvent('qr-scan-progress', { \r\n detail: { \r\n id: qrChunksBufferRef.current.id, \r\n seq: uniqueCount, \r\n total: qrChunksBufferRef.current.total \r\n } \r\n }));\r\n \r\n // Force re-render to update progress indicator\r\n setQrFramesTotal(qrChunksBufferRef.current.total);\r\n setQrFrameIndex(uniqueCount);\r\n } catch {}\r\n \r\n // Check if we have all chunks\r\n const isComplete = qrChunksBufferRef.current.seen.size >= qrChunksBufferRef.current.total;\r\n console.log(`Chunks collected: ${qrChunksBufferRef.current.seen.size}/${qrChunksBufferRef.current.total}, complete: ${isComplete}`);\r\n \r\n if (!isComplete) {\r\n // Keep scanner open for more chunks\r\n console.log(`Scanned chunk ${qrChunksBufferRef.current.seen.size}/${qrChunksBufferRef.current.total}, waiting for more...`);\r\n return Promise.resolve(false);\r\n }\r\n \r\n // All chunks collected - reconstruct binary data\r\n try {\r\n const fullBinaryData = qrChunksBufferRef.current.items.join('');\r\n // Store the original binary data, not decoded JSON\r\n if (showOfferStep) {\r\n setAnswerInput(fullBinaryData);\r\n } else {\r\n setOfferInput(fullBinaryData);\r\n }\r\n \r\n setMessages(prev => [...prev, { \r\n message: 'All binary chunks captured. Payload reconstructed.', \r\n type: 'success' \r\n }]);\r\n \r\n // Clear buffer and close scanner\r\n qrChunksBufferRef.current = { id: null, total: 0, seen: new Set(), items: [] };\r\n setShowQRScannerModal(false);\r\n return Promise.resolve(true);\r\n } catch (e) {\r\n console.warn('Binary chunks reconstruction failed:', e);\r\n return Promise.resolve(false);\r\n }\r\n }\r\n \r\n // Single QR code - try to decode directly\r\n console.log('Processing single QR code:', scannedData.substring(0, 50) + '...');\r\n let parsedData;\r\n if (typeof window.decodeAnyPayload === 'function') {\r\n const any = window.decodeAnyPayload(scannedData);\r\n if (typeof any === 'string') {\r\n parsedData = JSON.parse(any);\r\n } else {\r\n parsedData = any; // object from binary\r\n }\r\n } else {\r\n const maybeDecompressed = (typeof window.decompressIfNeeded === 'function') ? window.decompressIfNeeded(scannedData) : scannedData;\r\n parsedData = JSON.parse(maybeDecompressed);\r\n }\r\n console.log('Decoded data:', parsedData);\r\n \r\n // QR with hdr/body: COSE or RAW/BIN animated frames\r\n if (parsedData.hdr && parsedData.body) {\r\n const { hdr } = parsedData;\r\n // Initialize/rotate buffer by id\r\n if (!qrChunksBufferRef.current.id || qrChunksBufferRef.current.id !== hdr.id) {\r\n qrChunksBufferRef.current = { id: hdr.id, total: hdr.total || 1, seen: new Set(), items: [], lastUpdateMs: Date.now() };\r\n try {\r\n document.dispatchEvent(new CustomEvent('qr-scan-progress', { detail: { id: hdr.id, seq: 0, total: hdr.total || 1 } }));\r\n } catch {}\r\n }\r\n // Deduplicate & record\r\n if (!qrChunksBufferRef.current.seen.has(hdr.seq)) {\r\n qrChunksBufferRef.current.seen.add(hdr.seq);\r\n qrChunksBufferRef.current.items.push(scannedData);\r\n qrChunksBufferRef.current.lastUpdateMs = Date.now();\r\n }\r\n // Emit progress based on unique frames captured\r\n try {\r\n const uniqueCount = qrChunksBufferRef.current.seen.size;\r\n document.dispatchEvent(new CustomEvent('qr-scan-progress', { detail: { id: hdr.id, seq: uniqueCount, total: qrChunksBufferRef.current.total || hdr.total || 0 } }));\r\n } catch {}\r\n const isComplete = qrChunksBufferRef.current.seen.size >= (qrChunksBufferRef.current.total || 1);\r\n if (!isComplete) {\r\n // Explicitly keep scanner open\r\n return Promise.resolve(false);\r\n }\r\n // Completed: decide RAW vs BIN vs COSE\r\n if (hdr.rt === 'raw') {\r\n try {\r\n // Sort by seq and concatenate bodies\r\n const parts = qrChunksBufferRef.current.items\r\n .map(s => JSON.parse(s))\r\n .sort((a, b) => (a.hdr.seq || 0) - (b.hdr.seq || 0))\r\n .map(p => p.body || '');\r\n const fullText = parts.join('');\r\n const payloadObj = JSON.parse(fullText);\r\n if (showOfferStep) {\r\n setAnswerInput(JSON.stringify(payloadObj, null, 2));\r\n } else {\r\n setOfferInput(JSON.stringify(payloadObj, null, 2));\r\n }\r\n setMessages(prev => [...prev, { message: 'All frames captured. RAW payload reconstructed.', type: 'success' }]);\r\n try { document.dispatchEvent(new CustomEvent('qr-scan-complete', { detail: { id: hdr.id } })); } catch {}\r\n // Close scanner from caller by returning true\r\n qrChunksBufferRef.current = { id: null, total: 0, seen: new Set(), items: [] };\r\n setShowQRScannerModal(false);\r\n return Promise.resolve(true);\r\n } catch (e) {\r\n console.warn('RAW multi-frame reconstruction failed:', e);\r\n return Promise.resolve(false);\r\n }\r\n } else if (hdr.rt === 'bin') {\r\n try {\r\n const parts = qrChunksBufferRef.current.items\r\n .map(s => JSON.parse(s))\r\n .sort((a, b) => (a.hdr.seq || 0) - (b.hdr.seq || 0))\r\n .map(p => p.body || '');\r\n const fullText = parts.join(''); // SB1:bin:...\r\n let payloadObj;\r\n if (typeof window.decodeAnyPayload === 'function') {\r\n const any = window.decodeAnyPayload(fullText);\r\n payloadObj = (typeof any === 'string') ? JSON.parse(any) : any;\r\n } else {\r\n payloadObj = JSON.parse(fullText);\r\n }\r\n if (showOfferStep) {\r\n setAnswerInput(JSON.stringify(payloadObj, null, 2));\r\n } else {\r\n setOfferInput(JSON.stringify(payloadObj, null, 2));\r\n }\r\n setMessages(prev => [...prev, { message: 'All frames captured. BIN payload reconstructed.', type: 'success' }]);\r\n try { document.dispatchEvent(new CustomEvent('qr-scan-complete', { detail: { id: hdr.id } })); } catch {}\r\n qrChunksBufferRef.current = { id: null, total: 0, seen: new Set(), items: [] };\r\n setShowQRScannerModal(false);\r\n return Promise.resolve(true);\r\n } catch (e) {\r\n console.warn('BIN multi-frame reconstruction failed:', e);\r\n return Promise.resolve(false);\r\n }\r\n } else if (window.receiveAndProcess) {\r\n try {\r\n const results = await window.receiveAndProcess(qrChunksBufferRef.current.items);\r\n if (results.length > 0) {\r\n const { payloadObj } = results[0];\r\n if (showOfferStep) {\r\n setAnswerInput(JSON.stringify(payloadObj, null, 2));\r\n } else {\r\n setOfferInput(JSON.stringify(payloadObj, null, 2));\r\n }\r\n setMessages(prev => [...prev, { message: 'All frames captured. COSE payload reconstructed.', type: 'success' }]);\r\n try { document.dispatchEvent(new CustomEvent('qr-scan-complete', { detail: { id: hdr.id } })); } catch {}\r\n qrChunksBufferRef.current = { id: null, total: 0, seen: new Set(), items: [] };\r\n setShowQRScannerModal(false);\r\n return Promise.resolve(true);\r\n }\r\n } catch (e) {\r\n console.warn('COSE multi-chunk processing failed:', e);\r\n }\r\n return Promise.resolve(false);\r\n } else {\r\n return Promise.resolve(false);\r\n }\r\n }\r\n \r\n // Check if this is a template-based QR code\r\n if (parsedData.type === 'enhanced_secure_offer_template') {\r\n console.log('QR scan: Template-based offer detected, reconstructing...');\r\n const fullOffer = reconstructFromTemplate(parsedData);\r\n \r\n // Determine which input to populate based on current mode\r\n if (showOfferStep) {\r\n // In \"Waiting for peer's response\" mode - populate answerInput\r\n setAnswerInput(JSON.stringify(fullOffer, null, 2));\r\n console.log('\uD83D\uDCF1 Template data populated to answerInput (waiting for response mode)');\r\n } else {\r\n // In \"Paste secure invitation\" mode - populate offerInput\r\n setOfferInput(JSON.stringify(fullOffer, null, 2));\r\n console.log('\uD83D\uDCF1 Template data populated to offerInput (paste invitation mode)');\r\n }\r\n setMessages(prev => [...prev, {\r\n message: '\uD83D\uDCF1 QR code scanned successfully! Full offer reconstructed from template.',\r\n type: 'success'\r\n }]);\r\n setShowQRScannerModal(false); // Close QR scanner modal\r\n return true;\r\n }\r\n // Check if this is a reference-based QR code\r\n else if (parsedData.type === 'secure_offer_reference' && parsedData.referenceId) {\r\n // Try to get the full offer data from localStorage\r\n const fullOfferData = localStorage.getItem(`qr_offer_${parsedData.referenceId}`);\r\n if (fullOfferData) {\r\n const fullOffer = JSON.parse(fullOfferData);\r\n // Determine which input to populate based on current mode\r\n if (showOfferStep) {\r\n // In \"Waiting for peer's response\" mode - populate answerInput\r\n setAnswerInput(JSON.stringify(fullOffer, null, 2));\r\n } else {\r\n // In \"Paste secure invitation\" mode - populate offerInput\r\n setOfferInput(JSON.stringify(fullOffer, null, 2));\r\n }\r\n setMessages(prev => [...prev, {\r\n message: '\uD83D\uDCF1 QR code scanned successfully! Full offer data retrieved.',\r\n type: 'success'\r\n }]);\r\n setShowQRScannerModal(false); // Close QR scanner modal\r\n return true;\r\n } else {\r\n setMessages(prev => [...prev, {\r\n message: 'QR code reference found but full data not available. Please use copy/paste.',\r\n type: 'error'\r\n }]);\r\n return false;\r\n }\r\n } else {\r\n // If payload was compressed, it's already decompressed above; keep legacy warning only when clearly incomplete\r\n if (!parsedData.sdp && parsedData.type === 'enhanced_secure_offer') {\r\n setMessages(prev => [...prev, {\r\n message: 'Compressed QR may omit SDP for brevity. Use copy/paste if connection fails.',\r\n type: 'warning'\r\n }]);\r\n }\r\n \r\n // Determine which input to populate based on current mode\r\n if (showOfferStep) {\r\n // In \"Waiting for peer's response\" mode - populate answerInput\r\n console.log('QR scan: Populating answerInput with:', parsedData);\r\n setAnswerInput(JSON.stringify(parsedData, null, 2));\r\n } else {\r\n // In \"Paste secure invitation\" mode - populate offerInput\r\n console.log('QR scan: Populating offerInput with:', parsedData);\r\n setOfferInput(JSON.stringify(parsedData, null, 2));\r\n }\r\n setMessages(prev => [...prev, {\r\n message: '\uD83D\uDCF1 QR code scanned successfully!',\r\n type: 'success'\r\n }]);\r\n setShowQRScannerModal(false);\r\n return true;\r\n }\r\n } catch (error) {\r\n // If not JSON, use as plain text\r\n if (showOfferStep) {\r\n // In \"Waiting for peer's response\" mode - populate answerInput\r\n setAnswerInput(scannedData);\r\n } else {\r\n // In \"Paste secure invitation\" mode - populate offerInput\r\n setOfferInput(scannedData);\r\n }\r\n setMessages(prev => [...prev, {\r\n message: '\uD83D\uDCF1 QR code scanned successfully!',\r\n type: 'success'\r\n }]);\r\n setShowQRScannerModal(false);\r\n return true;\r\n }\r\n };\r\n \r\n const handleCreateOffer = async () => {\r\n try {\r\n // All security features are enabled by default\r\n \r\n setOfferData('');\r\n setShowOfferStep(false);\r\n setShowQRCode(false);\r\n setQrCodeUrl('');\r\n \r\n const offer = await webrtcManagerRef.current.createSecureOffer();\r\n \r\n // Store offer data directly (no encryption needed with SAS)\r\n setOfferData(offer);\r\n setShowOfferStep(true);\r\n \r\n // Generate QR code with binary format and chunking\r\n const offerString = typeof offer === 'object' ? JSON.stringify(offer) : offer;\r\n try {\r\n if (typeof window.encodeBinaryToPrefixed === 'function') {\r\n const bin = window.encodeBinaryToPrefixed(offerString);\r\n // Force chunking into 4 parts - split binary data directly\r\n const TARGET_CHUNKS = 4;\r\n let FRAME_MAX = Math.max(200, Math.floor(bin.length / TARGET_CHUNKS));\r\n if (FRAME_MAX <= 0) FRAME_MAX = 200;\r\n let total = Math.ceil(bin.length / FRAME_MAX);\r\n if (total < 2) { total = 2; FRAME_MAX = Math.ceil(bin.length / 2) || 1; }\r\n \r\n const id = `bin_${Date.now()}_${Math.random().toString(36).slice(2)}`;\r\n const chunks = [];\r\n for (let i = 0; i < total; i++) {\r\n const seq = i + 1;\r\n const part = bin.slice(i * FRAME_MAX, (i + 1) * FRAME_MAX);\r\n // Store binary chunks directly without JSON wrapper\r\n chunks.push(part);\r\n }\r\n \r\n // Seed first frame and start auto-advance immediately\r\n const isDesktop = (typeof window !== 'undefined') && ((window.innerWidth || 0) >= 1024);\r\n const QR_SIZE = isDesktop ? 720 : 512;\r\n if (window.generateQRCode && chunks.length > 0) {\r\n const firstUrl = await window.generateQRCode(chunks[0], { errorCorrectionLevel: 'M', size: QR_SIZE, margin: 2 });\r\n if (firstUrl) setQrCodeUrl(firstUrl);\r\n }\r\n \r\n // Store precomputed chunks to ref, ready for animation\r\n try { if (qrAnimationRef.current && qrAnimationRef.current.timer) { clearInterval(qrAnimationRef.current.timer); } } catch {}\r\n qrAnimationRef.current = { timer: null, chunks, idx: 0, active: true };\r\n setQrFramesTotal(chunks.length);\r\n setQrFrameIndex(1);\r\n setQrManualMode(false);\r\n \r\n // Start auto-advance loop for Offer immediately\r\n const intervalMs = 3000;\r\n qrAnimationRef.current.timer = setInterval(renderAndAdvance, intervalMs);\r\n \r\n // Show QR immediately for Offer flow\r\n try { setShowQRCode(true); } catch {}\r\n } else {\r\n // Fallback to single QR\r\n await generateQRCode(offer);\r\n try { setShowQRCode(true); } catch {}\r\n }\r\n } catch (e) {\r\n console.warn('Offer QR generation failed:', e);\r\n }\r\n \r\n const existingMessages = messages.filter(m => \r\n m.type === 'system' && \r\n (m.message.includes('Secure invitation created') || m.message.includes('Send the encrypted code'))\r\n );\r\n \r\n if (existingMessages.length === 0) {\r\n setMessages(prev => [...prev, { \r\n message: 'Secure invitation created and encrypted!', \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n \r\n setMessages(prev => [...prev, { \r\n message: '\uD83D\uDCE4 Send the invitation code to your interlocutor via a secure channel (voice call, SMS, etc.)..', \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n \r\n }\r\n \r\n if (!window.isUpdatingSecurity) {\r\n updateSecurityLevel().catch(console.error);\r\n }\r\n } catch (error) {\r\n setMessages(prev => [...prev, { \r\n message: `Error creating invitation: ${error.message}`, \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n }\r\n };\r\n \r\n const handleCreateAnswer = async () => {\r\n try {\r\n \r\n if (!offerInput.trim()) {\r\n setMessages(prev => [...prev, { \r\n message: 'You need to insert the invitation code from your interlocutor.', \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n return;\r\n }\r\n \r\n try {\r\n setMessages(prev => [...prev, { \r\n message: 'Processing the secure invitation...', \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n \r\n let offer;\r\n try {\r\n // Prefer binary decode first, then gzip JSON\r\n if (typeof window.decodeAnyPayload === 'function') {\r\n const any = window.decodeAnyPayload(offerInput.trim());\r\n offer = (typeof any === 'string') ? JSON.parse(any) : any;\r\n } else {\r\n const rawText = (typeof window.decompressIfNeeded === 'function') ? window.decompressIfNeeded(offerInput.trim()) : offerInput.trim();\r\n offer = JSON.parse(rawText);\r\n }\r\n } catch (parseError) {\r\n throw new Error(`Invalid invitation format: ${parseError.message}`);\r\n }\r\n \r\n if (!offer || typeof offer !== 'object') {\r\n throw new Error('The invitation must be an object');\r\n }\r\n \r\n // Support both compact and legacy offer formats\r\n const isValidOfferType = (offer.t === 'offer') || (offer.type === 'enhanced_secure_offer');\r\n if (!isValidOfferType) {\r\n throw new Error('Invalid invitation type. Expected offer or enhanced_secure_offer');\r\n }\r\n\r\n const answer = await webrtcManagerRef.current.createSecureAnswer(offer);\r\n \r\n // Store answer data directly (no encryption needed with SAS)\r\n setAnswerData(answer);\r\n setShowAnswerStep(true);\r\n \r\n // Generate QR code with binary format and chunking\r\n const answerString = typeof answer === 'object' ? JSON.stringify(answer) : answer;\r\n try {\r\n if (typeof window.encodeBinaryToPrefixed === 'function') {\r\n const bin = window.encodeBinaryToPrefixed(answerString);\r\n // Force chunking into 4 parts - split binary data directly\r\n const TARGET_CHUNKS = 4;\r\n let FRAME_MAX = Math.max(200, Math.floor(bin.length / TARGET_CHUNKS));\r\n if (FRAME_MAX <= 0) FRAME_MAX = 200;\r\n let total = Math.ceil(bin.length / FRAME_MAX);\r\n if (total < 2) { total = 2; FRAME_MAX = Math.ceil(bin.length / 2) || 1; }\r\n \r\n const id = `ans_${Date.now()}_${Math.random().toString(36).slice(2)}`;\r\n const chunks = [];\r\n for (let i = 0; i < total; i++) {\r\n const seq = i + 1;\r\n const part = bin.slice(i * FRAME_MAX, (i + 1) * FRAME_MAX);\r\n // Store binary chunks directly without JSON wrapper\r\n chunks.push(part);\r\n }\r\n \r\n const isDesktop = (typeof window !== 'undefined') && ((window.innerWidth || 0) >= 1024);\r\n const QR_SIZE = isDesktop ? 720 : 512;\r\n if (window.generateQRCode && chunks.length > 0) {\r\n const firstUrl = await window.generateQRCode(chunks[0], { errorCorrectionLevel: 'M', size: QR_SIZE, margin: 2 });\r\n if (firstUrl) setQrCodeUrl(firstUrl);\r\n }\r\n \r\n try { if (qrAnimationRef.current && qrAnimationRef.current.timer) { clearInterval(qrAnimationRef.current.timer); } } catch {}\r\n qrAnimationRef.current = { timer: null, chunks, idx: 0, active: true };\r\n setQrFramesTotal(chunks.length);\r\n setQrFrameIndex(1);\r\n setQrManualMode(false);\r\n \r\n const intervalMs = 3000;\r\n qrAnimationRef.current.timer = setInterval(renderAndAdvance, intervalMs);\r\n \r\n // Show QR immediately for Answer flow\r\n try { setShowQRCode(true); } catch {}\r\n } else {\r\n // Fallback to single QR\r\n await generateQRCode(answer);\r\n try { setShowQRCode(true); } catch {}\r\n }\r\n } catch (e) {\r\n console.warn('Answer QR generation failed:', e);\r\n }\r\n \r\n // Mark answer as created for state management\r\n if (e.target.value.trim().length > 0) {\r\n if (typeof markAnswerCreated === 'function') {\r\n markAnswerCreated();\r\n }\r\n }\r\n\r\n \r\n const existingResponseMessages = messages.filter(m => \r\n m.type === 'system' && \r\n (m.message.includes('Secure response created') || m.message.includes('Send the response'))\r\n );\r\n \r\n if (existingResponseMessages.length === 0) {\r\n setMessages(prev => [...prev, { \r\n message: 'Secure response created!', \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n \r\n setMessages(prev => [...prev, { \r\n message: 'Send the response code to the initiator via a secure channel or let them scan the QR code below.', \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n \r\n }\r\n \r\n // Update security level after creating answer\r\n if (!window.isUpdatingSecurity) {\r\n updateSecurityLevel().catch(console.error);\r\n }\r\n } catch (error) {\r\n console.error('Error in handleCreateAnswer:', error);\r\n setMessages(prev => [...prev, { \r\n message: `Error processing the invitation: ${error.message}`, \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n }\r\n } catch (error) {\r\n console.error('Error in handleCreateAnswer:', error);\r\n setMessages(prev => [...prev, { \r\n message: `Invitation processing error: ${error.message}`, \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n }\r\n };\r\n \r\n const handleConnect = async () => {\r\n try {\r\n if (!answerInput.trim()) {\r\n setMessages(prev => [...prev, { \r\n message: 'You need to insert the response code from your interlocutor.', \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n return;\r\n }\r\n \r\n try {\r\n setMessages(prev => [...prev, { \r\n message: 'Processing the secure response...', \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n \r\n let answer;\r\n try {\r\n // Prefer binary decode first, then gzip JSON\r\n if (typeof window.decodeAnyPayload === 'function') {\r\n const anyAnswer = window.decodeAnyPayload(answerInput.trim());\r\n answer = (typeof anyAnswer === 'string') ? JSON.parse(anyAnswer) : anyAnswer;\r\n } else {\r\n const rawText = (typeof window.decompressIfNeeded === 'function') ? window.decompressIfNeeded(answerInput.trim()) : answerInput.trim();\r\n answer = JSON.parse(rawText);\r\n }\r\n } catch (parseError) {\r\n throw new Error(`Invalid response format: ${parseError.message}`);\r\n }\r\n \r\n if (!answer || typeof answer !== 'object') {\r\n throw new Error('The response must be an object');\r\n }\r\n \r\n // Support both compact and legacy formats\r\n const answerType = answer.t || answer.type;\r\n if (!answerType || (answerType !== 'answer' && answerType !== 'enhanced_secure_answer')) {\r\n throw new Error('Invalid response type. Expected answer or enhanced_secure_answer');\r\n }\r\n \r\n await webrtcManagerRef.current.handleSecureAnswer(answer);\r\n \r\n // All security features are enabled by default - no session activation needed\r\n if (pendingSession) {\r\n setPendingSession(null);\r\n setMessages(prev => [...prev, { \r\n message: `All security features enabled by default`, \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n }\r\n \r\n setMessages(prev => [...prev, { \r\n message: 'Finalizing the secure connection...', \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n \r\n // Update security level after handling answer\r\n if (!window.isUpdatingSecurity) {\r\n updateSecurityLevel().catch(console.error);\r\n }\r\n } catch (error) {\r\n console.error('Error in handleConnect inner try:', error);\r\n \r\n // \u0411\u043E\u043B\u0435\u0435 \u0434\u0435\u0442\u0430\u043B\u044C\u043D\u0430\u044F \u043E\u0431\u0440\u0430\u0431\u043E\u0442\u043A\u0430 \u043E\u0448\u0438\u0431\u043E\u043A\r\n let errorMessage = 'Connection setup error';\r\n if (error.message.includes('CRITICAL SECURITY FAILURE')) {\r\n if (error.message.includes('ECDH public key structure')) {\r\n errorMessage = 'Invalid response code - missing or corrupted cryptographic key. Please check the code and try again.';\r\n } else if (error.message.includes('ECDSA public key structure')) {\r\n errorMessage = 'Invalid response code - missing signature verification key. Please check the code and try again.';\r\n } else {\r\n errorMessage = 'Security validation failed - possible attack detected';\r\n }\r\n } else if (error.message.includes('too old') || error.message.includes('replay')) {\r\n errorMessage = 'Response data is outdated - please use a fresh invitation';\r\n } else if (error.message.includes('MITM') || error.message.includes('signature')) {\r\n errorMessage = 'Security breach detected - connection rejected';\r\n } else if (error.message.includes('Invalid') || error.message.includes('format')) {\r\n errorMessage = 'Invalid response format - please check the code';\r\n } else {\r\n errorMessage = ` ${error.message}`;\r\n }\r\n \r\n setMessages(prev => [...prev, { \r\n message: errorMessage, \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now(),\r\n showRetryButton: true\r\n }]);\r\n\r\n if (!error.message.includes('too old') && !error.message.includes('replay')) {\r\n setPendingSession(null);\r\n setSessionTimeLeft(0);\r\n }\r\n\r\n setConnectionStatus('failed');\r\n \r\n } \r\n } catch (error) {\r\n console.error('Error in handleConnect outer try:', error);\r\n\r\n let errorMessage = 'Connection setup error';\r\n if (error.message.includes('CRITICAL SECURITY FAILURE')) {\r\n if (error.message.includes('ECDH public key structure')) {\r\n errorMessage = 'Invalid response code - missing or corrupted cryptographic key. Please check the code and try again.';\r\n } else if (error.message.includes('ECDSA public key structure')) {\r\n errorMessage = 'Invalid response code - missing signature verification key. Please check the code and try again.';\r\n } else {\r\n errorMessage = 'Security validation failed - possible attack detected';\r\n }\r\n } else if (error.message.includes('too old') || error.message.includes('replay')) {\r\n errorMessage = 'Response data is outdated - please use a fresh invitation';\r\n } else if (error.message.includes('MITM') || error.message.includes('signature')) {\r\n errorMessage = 'Security breach detected - connection rejected';\r\n } else if (error.message.includes('Invalid') || error.message.includes('format')) {\r\n errorMessage = 'Invalid response format - please check the code';\r\n } else {\r\n errorMessage = `${error.message}`;\r\n }\r\n \r\n setMessages(prev => [...prev, { \r\n message: errorMessage, \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now(),\r\n showRetryButton: true\r\n }]);\r\n\r\n if (!error.message.includes('too old') && !error.message.includes('replay')) {\r\n setPendingSession(null);\r\n setSessionTimeLeft(0);\r\n }\r\n\r\n setConnectionStatus('failed');\r\n }\r\n };\r\n \r\n const handleVerifyConnection = (isValid) => {\r\n if (isValid) {\r\n webrtcManagerRef.current.confirmVerification();\r\n // Mark local verification as confirmed\r\n setLocalVerificationConfirmed(true);\r\n } else {\r\n setMessages(prev => [...prev, { \r\n message: ' Verification rejected. The connection is unsafe! Session reset..', \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n \r\n // Clear verification states\r\n setLocalVerificationConfirmed(false);\r\n setRemoteVerificationConfirmed(false);\r\n setBothVerificationsConfirmed(false);\r\n setShowVerification(false);\r\n setVerificationCode('');\r\n \r\n // Reset UI to initial state\r\n setConnectionStatus('disconnected');\r\n setOfferData(null);\r\n setAnswerData(null);\r\n setOfferInput('');\r\n setAnswerInput('');\r\n setShowOfferStep(false);\r\n setShowAnswerStep(false);\r\n setKeyFingerprint('');\r\n setSecurityLevel(null);\r\n setIsVerified(false);\r\n setMessages([]);\r\n \r\n setSessionTimeLeft(0);\r\n setPendingSession(null);\r\n \r\n // Dispatch disconnected event for SessionTimer\r\n document.dispatchEvent(new CustomEvent('disconnected'));\r\n \r\n handleDisconnect();\r\n }\r\n };\r\n \r\n const handleSendMessage = async () => {\r\n if (!messageInput.trim()) {\r\n return;\r\n }\r\n \r\n if (!webrtcManagerRef.current) {\r\n return;\r\n }\r\n \r\n if (!webrtcManagerRef.current.isConnected()) {\r\n return;\r\n }\r\n \r\n try {\r\n \r\n // Add the message to local messages immediately (sent message)\r\n addMessageWithAutoScroll(messageInput.trim(), 'sent');\r\n \r\n // Use sendMessage for simple text messages instead of sendSecureMessage\r\n await webrtcManagerRef.current.sendMessage(messageInput);\r\n setMessageInput('');\r\n } catch (error) {\r\n const msg = String(error?.message || error);\r\n if (!/queued for sending|Data channel not ready/i.test(msg)) {\r\n addMessageWithAutoScroll(`Sending error: ${msg}`,'system');\r\n }\r\n }\r\n };\r\n \r\n const handleClearData = () => {\r\n setOfferData('');\r\n setAnswerData('');\r\n setOfferInput('');\r\n setAnswerInput('');\r\n setShowOfferStep(false);\r\n\r\n if (!shouldPreserveAnswerData()) {\r\n setShowAnswerStep(false);\r\n }\r\n \r\n setShowVerification(false);\r\n setShowQRCode(false);\r\n setShowQRScanner(false);\r\n setShowQRScannerModal(false);\r\n // Clear QR scanner buffer\r\n qrChunksBufferRef.current = { id: null, total: 0, seen: new Set(), items: [] };\r\n\r\n if (!shouldPreserveAnswerData()) {\r\n setQrCodeUrl('');\r\n }\r\n \r\n setVerificationCode('');\r\n setIsVerified(false);\r\n setKeyFingerprint('');\r\n setSecurityLevel(null);\r\n setConnectionStatus('disconnected');\r\n setMessages([]);\r\n setMessageInput('');\r\n \r\n // Clear verification states\r\n setLocalVerificationConfirmed(false);\r\n setRemoteVerificationConfirmed(false);\r\n setBothVerificationsConfirmed(false);\r\n \r\n // PAKE passwords removed - using SAS verification instead \r\n\r\n if (typeof console.clear === 'function') {\r\n console.clear();\r\n }\r\n \r\n // Cleanup session state\r\n setSessionTimeLeft(0);\r\n \r\n setPendingSession(null);\r\n document.dispatchEvent(new CustomEvent('peer-disconnect'));\r\n // Session manager removed - all features enabled by default\r\n };\r\n \r\n const handleDisconnect = () => {\r\n setSessionTimeLeft(0);\r\n \r\n // Mark as user-initiated disconnect\r\n updateConnectionState({ \r\n status: 'disconnected',\r\n isUserInitiatedDisconnect: true \r\n });\r\n \r\n // Cleanup session state\r\n if (webrtcManagerRef.current) {\r\n webrtcManagerRef.current.disconnect();\r\n }\r\n \r\n setKeyFingerprint('');\r\n setVerificationCode('');\r\n setSecurityLevel(null);\r\n setIsVerified(false);\r\n setShowVerification(false);\r\n setConnectionStatus('disconnected');\r\n \r\n // Clear verification states\r\n setLocalVerificationConfirmed(false);\r\n setRemoteVerificationConfirmed(false);\r\n setBothVerificationsConfirmed(false);\r\n \r\n // Reset UI to initial state (user-initiated disconnect always clears data)\r\n setConnectionStatus('disconnected');\r\n setShowVerification(false);\r\n setOfferData(null);\r\n setAnswerData(null);\r\n setOfferInput('');\r\n setAnswerInput('');\r\n setShowOfferStep(false);\r\n setShowAnswerStep(false);\r\n setKeyFingerprint('');\r\n setVerificationCode('');\r\n setSecurityLevel(null);\r\n setIsVerified(false);\r\n \r\n setMessages([]);\r\n \r\n if (typeof console.clear === 'function') {\r\n console.clear();\r\n }\r\n \r\n document.dispatchEvent(new CustomEvent('peer-disconnect'));\r\n document.dispatchEvent(new CustomEvent('disconnected'));\r\n \r\n document.dispatchEvent(new CustomEvent('session-cleanup', {\r\n detail: { \r\n timestamp: Date.now(),\r\n reason: 'manual_disconnect'\r\n }\r\n }));\r\n \r\n setTimeout(() => {\r\n setSessionTimeLeft(0);\r\n }, 500);\r\n \r\n handleClearData();\r\n \r\n setTimeout(() => {\r\n // Session manager removed - all features enabled by default\r\n }, 1000);\r\n };\r\n \r\n const handleSessionActivated = (session) => {\r\n let message;\r\n if (session.type === 'demo') {\r\n message = ` Demo session activated for 6 minutes. You can create invitations!`;\r\n } else {\r\n message = ` All security features enabled by default. You can create invitations!`;\r\n }\r\n \r\n addMessageWithAutoScroll(message, 'system');\r\n \r\n };\r\n \r\n React.useEffect(() => {\r\n if (connectionStatus === 'connected' && isVerified) {\r\n addMessageWithAutoScroll(' Secure connection successfully established and verified! You can now communicate safely with full protection against MITM attacks and Perfect Forward Secrecy..', 'system');\r\n \r\n }\r\n }, [connectionStatus, isVerified]);\r\n \r\n const isConnectedAndVerified = (connectionStatus === 'connected' || connectionStatus === 'verified') && isVerified;\r\n \r\n React.useEffect(() => {\r\n // All security features are enabled by default - no session activation needed\r\n if (isConnectedAndVerified && pendingSession && connectionStatus !== 'failed') {\r\n setPendingSession(null);\r\n setSessionTimeLeft(0); \r\n addMessageWithAutoScroll(' All security features enabled by default', 'system');\r\n }\r\n }, [isConnectedAndVerified, pendingSession, connectionStatus]);\r\n\r\n // QR Scanner initialization\r\n React.useEffect(() => {\r\n if (showQRScannerModal && window.Html5Qrcode) {\r\n const html5Qrcode = new window.Html5Qrcode(\"qr-reader\");\r\n const config = { \r\n fps: 10\r\n // \u0423\u0431\u0438\u0440\u0430\u0435\u043C qrbox \u0447\u0442\u043E\u0431\u044B \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u044C \u0432\u0441\u044E \u043E\u0431\u043B\u0430\u0441\u0442\u044C\r\n };\r\n\r\n let isScanning = true;\r\n\r\n html5Qrcode.start(\r\n { facingMode: \"environment\" }, // Use back camera\r\n config,\r\n (decodedText, decodedResult) => {\r\n if (!isScanning) {\r\n console.log('Scanner stopped, ignoring scan');\r\n return;\r\n }\r\n \r\n console.log('QR Code scanned:', decodedText);\r\n console.log('Current buffer state:', qrChunksBufferRef.current);\r\n \r\n handleQRScan(decodedText).then((success) => {\r\n console.log('QR scan result:', success);\r\n if (success) {\r\n // Successfully processed - stop scanner and close modal\r\n console.log('Closing scanner and modal');\r\n isScanning = false;\r\n \r\n // Stop scanner first, then clear\r\n try {\r\n console.log('Stopping scanner...');\r\n html5Qrcode.stop().then(() => {\r\n console.log('Scanner stopped, clearing...');\r\n html5Qrcode.clear();\r\n setShowQRScannerModal(false);\r\n }).catch((err) => {\r\n console.log('Error stopping scanner:', err);\r\n // Try to clear anyway\r\n try {\r\n html5Qrcode.clear();\r\n } catch (clearErr) {\r\n console.log('Error clearing scanner:', clearErr);\r\n }\r\n setShowQRScannerModal(false);\r\n });\r\n } catch (err) {\r\n console.log('Error in scanner cleanup:', err);\r\n setShowQRScannerModal(false);\r\n }\r\n } else {\r\n console.log('Continuing to scan for more chunks...');\r\n }\r\n }).catch((error) => {\r\n console.error('QR scan processing error:', error);\r\n // Continue scanning on error\r\n });\r\n },\r\n (error) => {\r\n // Ignore scanning errors - continue scanning\r\n if (isScanning) {\r\n console.log('QR scan error (ignored):', error);\r\n }\r\n }\r\n ).catch((err) => {\r\n console.error('QR Scanner start error:', err);\r\n // Close modal on start error\r\n setShowQRScannerModal(false);\r\n });\r\n\r\n return () => {\r\n isScanning = false;\r\n try {\r\n // Try to stop scanner, but don't worry if it's already stopped\r\n html5Qrcode.stop().then(() => {\r\n html5Qrcode.clear();\r\n }).catch((err) => {\r\n // Scanner might already be stopped, just clear it\r\n console.log('Scanner already stopped or error stopping:', err);\r\n try {\r\n html5Qrcode.clear();\r\n } catch (clearErr) {\r\n console.log('Error clearing scanner in cleanup:', clearErr);\r\n }\r\n });\r\n } catch (err) {\r\n console.log('Error in cleanup:', err);\r\n // Just try to clear, don't worry about stopping\r\n try {\r\n html5Qrcode.clear();\r\n } catch (clearErr) {\r\n console.log('Error clearing scanner in cleanup:', clearErr);\r\n }\r\n }\r\n };\r\n }\r\n }, [showQRScannerModal]);\r\n \r\n return React.createElement('div', { \r\n className: \"minimal-bg min-h-screen\" \r\n }, [\r\n React.createElement(EnhancedMinimalHeader, {\r\n key: 'header',\r\n status: connectionStatus,\r\n fingerprint: keyFingerprint,\r\n verificationCode: verificationCode,\r\n onDisconnect: handleDisconnect,\r\n isConnected: isConnectedAndVerified,\r\n securityLevel: securityLevel,\r\n // sessionManager removed - all features enabled by default\r\n sessionTimeLeft: sessionTimeLeft,\r\n webrtcManager: webrtcManagerRef.current\r\n }),\r\n \r\n React.createElement('main', {\r\n key: 'main'\r\n }, \r\n (() => {\r\n return isConnectedAndVerified;\r\n })()\r\n ? (() => {\r\n return React.createElement(EnhancedChatInterface, {\r\n messages: messages,\r\n messageInput: messageInput,\r\n setMessageInput: setMessageInput,\r\n onSendMessage: handleSendMessage,\r\n onDisconnect: handleDisconnect,\r\n keyFingerprint: keyFingerprint,\r\n isVerified: isVerified,\r\n chatMessagesRef: chatMessagesRef,\r\n scrollToBottom: scrollToBottom,\r\n webrtcManager: webrtcManagerRef.current\r\n });\r\n })()\r\n : React.createElement(EnhancedConnectionSetup, {\r\n onCreateOffer: handleCreateOffer,\r\n onCreateAnswer: handleCreateAnswer,\r\n onConnect: handleConnect,\r\n onClearData: handleClearData,\r\n onVerifyConnection: handleVerifyConnection,\r\n connectionStatus: connectionStatus,\r\n offerData: offerData,\r\n answerData: answerData,\r\n offerInput: offerInput,\r\n setOfferInput: setOfferInput,\r\n answerInput: answerInput,\r\n setAnswerInput: setAnswerInput,\r\n showOfferStep: showOfferStep,\r\n showAnswerStep: showAnswerStep,\r\n verificationCode: verificationCode,\r\n showVerification: showVerification,\r\n showQRCode: showQRCode,\r\n qrCodeUrl: qrCodeUrl,\r\n showQRScanner: showQRScanner,\r\n setShowQRCode: setShowQRCode,\r\n setShowQRScanner: setShowQRScanner,\r\n setShowQRScannerModal: setShowQRScannerModal,\r\n messages: messages,\r\n localVerificationConfirmed: localVerificationConfirmed,\r\n remoteVerificationConfirmed: remoteVerificationConfirmed,\r\n bothVerificationsConfirmed: bothVerificationsConfirmed,\r\n // QR control props\r\n qrFramesTotal: qrFramesTotal,\r\n qrFrameIndex: qrFrameIndex,\r\n qrManualMode: qrManualMode,\r\n toggleQrManualMode: toggleQrManualMode,\r\n nextQrFrame: nextQrFrame,\r\n prevQrFrame: prevQrFrame,\r\n // PAKE passwords removed - using SAS verification instead\r\n markAnswerCreated: markAnswerCreated\r\n })\r\n ),\r\n \r\n // QR Scanner Modal\r\n showQRScannerModal && React.createElement('div', {\r\n key: 'qr-scanner-modal',\r\n className: \"fixed inset-0 bg-black/80 flex items-center justify-center z-50\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'scanner-container',\r\n className: \"bg-gray-900 rounded-lg p-4 max-w-2xl w-full mx-4\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'scanner-header',\r\n className: \"flex items-center justify-between mb-4\"\r\n }, [\r\n React.createElement('h3', {\r\n key: 'scanner-title',\r\n className: \"text-lg font-medium text-white\"\r\n }, 'QR Code Scanner'),\r\n React.createElement('button', {\r\n key: 'close-btn',\r\n onClick: () => {\r\n setShowQRScannerModal(false);\r\n // Clear QR scanner buffer\r\n qrChunksBufferRef.current = { id: null, total: 0, seen: new Set(), items: [] };\r\n },\r\n className: \"text-gray-400 hover:text-white\"\r\n }, [\r\n React.createElement('i', {\r\n key: 'close-icon',\r\n className: 'fas fa-times'\r\n })\r\n ])\r\n ]),\r\n React.createElement('div', {\r\n key: 'scanner-content',\r\n className: \"text-center\"\r\n }, [\r\n React.createElement('p', {\r\n key: 'scanner-description',\r\n className: \"text-gray-400 mb-4\"\r\n }, 'Point your camera at the QR code to scan'),\r\n qrChunksBufferRef.current && qrChunksBufferRef.current.id && React.createElement('div', {\r\n key: 'progress-indicator',\r\n className: \"mb-4 p-3 bg-blue-500/10 border border-blue-500/20 rounded-lg\"\r\n }, [\r\n React.createElement('p', {\r\n key: 'progress-text',\r\n className: \"text-blue-400 text-sm\"\r\n }, `Scanned: ${qrChunksBufferRef.current.seen.size}/${qrChunksBufferRef.current.total} parts`),\r\n React.createElement('div', {\r\n key: 'progress-bar',\r\n className: \"w-full bg-gray-700 rounded-full h-2 mt-2\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'progress-fill',\r\n className: \"bg-blue-500 h-2 rounded-full transition-all duration-300\",\r\n style: { \r\n width: `${(qrChunksBufferRef.current.seen.size / qrChunksBufferRef.current.total) * 100}%` \r\n }\r\n })\r\n ])\r\n ]),\r\n React.createElement('div', {\r\n key: 'scanner-placeholder',\r\n id: \"qr-reader\",\r\n className: \"w-full h-96 bg-gray-800 rounded-lg flex items-center justify-center\",\r\n style: { minHeight: '400px' }\r\n }, [\r\n React.createElement('p', {\r\n key: 'scanner-placeholder-text',\r\n className: \"text-gray-500\"\r\n }, 'Camera will start here...')\r\n ])\r\n ])\r\n ])\r\n ])\r\n \r\n ]);\r\n };\r\n function initializeApp() {\r\n if (window.EnhancedSecureCryptoUtils && window.EnhancedSecureWebRTCManager) {\r\n ReactDOM.render(React.createElement(EnhancedSecureP2PChat), document.getElementById('root'));\r\n } else {\r\n console.error('\u041C\u043E\u0434\u0443\u043B\u0438 \u043D\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043D\u044B:', {\r\n hasCrypto: !!window.EnhancedSecureCryptoUtils,\r\n hasWebRTC: !!window.EnhancedSecureWebRTCManager\r\n });\r\n }\r\n }\r\n\r\n if (typeof window !== 'undefined') {\r\n\r\n window.addEventListener('unhandledrejection', (event) => {\r\n console.error('Unhandled promise rejection:', event.reason);\r\n event.preventDefault(); \r\n });\r\n \r\n\r\n window.addEventListener('error', (event) => {\r\n console.error('Global error:', event.error);\r\n event.preventDefault(); \r\n });\r\n \r\n if (!window.initializeApp) {\r\n window.initializeApp = initializeApp;\r\n }\r\n }\r\n // Render Enhanced Application\r\n ReactDOM.render(React.createElement(EnhancedSecureP2PChat), document.getElementById('root'));"], + "mappings": "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", + "names": ["e", "offerData", "payload"] } diff --git a/src/app.jsx b/src/app.jsx index 23ca85e..2dbd49b 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -595,7 +595,7 @@ ]), showQRCode && qrCodeUrl && React.createElement('div', { key: 'qr-container', - className: "mt-4 p-4 bg-gray-800/50 border border-gray-600/30 rounded-lg text-center" + className: "mt-4 p-4 border border-gray-600/30 rounded-lg text-center" }, [ React.createElement('h4', { key: 'qr-title', @@ -835,10 +835,10 @@ onChange: (e) => { setOfferInput(e.target.value); if (e.target.value.trim().length > 0) { - if (typeof markAnswerCreated === 'function') { - markAnswerCreated(); - } + if (typeof markAnswerCreated === 'function') { + markAnswerCreated(); } + } }, rows: 8, placeholder: "Paste the encrypted invitation code or scan QR code...", @@ -859,17 +859,17 @@ }), 'Scan QR Code' ]), - React.createElement('button', { - key: 'process-btn', - onClick: onCreateAnswer, - disabled: !offerInput.trim() || connectionStatus === 'connecting', - className: "flex-1 btn-secondary text-white py-2 px-4 rounded-lg font-medium transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed" - }, [ - React.createElement('i', { - className: 'fas fa-cogs mr-2' - }), - 'Process invitation' - ]) + React.createElement('button', { + key: 'process-btn', + onClick: onCreateAnswer, + disabled: !offerInput.trim() || connectionStatus === 'connecting', + className: "flex-1 btn-secondary text-white py-2 px-4 rounded-lg font-medium transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed" + }, [ + React.createElement('i', { + className: 'fas fa-cogs mr-2' + }), + 'Process invitation' + ]) ]), showQRScanner && React.createElement('div', { key: 'qr-scanner', @@ -978,7 +978,7 @@ // QR Code section for answer qrCodeUrl && React.createElement('div', { key: 'qr-container', - className: "mt-4 p-4 bg-gray-800/50 border border-gray-600/30 rounded-lg text-center" + className: "mt-4 p-4 border border-gray-600/30 rounded-lg text-center" }, [ React.createElement('h4', { key: 'qr-title', @@ -2166,10 +2166,53 @@ const generateQRCode = async (data) => { try { const originalSize = typeof data === 'string' ? data.length : JSON.stringify(data).length; - // Small payload: прямой JSON в один QR (без сжатия, без обёрток) - const payload = typeof data === 'string' ? data : JSON.stringify(data); const isDesktop = (typeof window !== 'undefined') && ((window.innerWidth || 0) >= 1024); const QR_SIZE = isDesktop ? 720 : 512; + + // Try binary format first (CBOR + deflate + base64url) + if (typeof window.generateBinaryQRCodeFromObject === 'function') { + try { + const obj = typeof data === 'string' ? JSON.parse(data) : data; + const qrDataUrl = await window.generateBinaryQRCodeFromObject(obj, { errorCorrectionLevel: 'M', size: QR_SIZE, margin: 2 }); + if (qrDataUrl) { + try { if (qrAnimationRef.current && qrAnimationRef.current.timer) { clearInterval(qrAnimationRef.current.timer); } } catch {} + qrAnimationRef.current = { timer: null, chunks: [], idx: 0, active: false }; + setQrFrameIndex(0); + setQrFramesTotal(0); + setQrManualMode(false); + setQrCodeUrl(qrDataUrl); + setQrFramesTotal(1); + setQrFrameIndex(1); + return; + } + } catch (e) { + console.warn('Binary QR generation failed, falling back to compressed:', e?.message || e); + } + } + + // Fallback to compressed JSON + if (typeof window.generateCompressedQRCode === 'function') { + try { + const payload = typeof data === 'string' ? data : JSON.stringify(data); + const qrDataUrl = await window.generateCompressedQRCode(payload, { errorCorrectionLevel: 'M', size: QR_SIZE, margin: 2 }); + if (qrDataUrl) { + try { if (qrAnimationRef.current && qrAnimationRef.current.timer) { clearInterval(qrAnimationRef.current.timer); } } catch {} + qrAnimationRef.current = { timer: null, chunks: [], idx: 0, active: false }; + setQrFrameIndex(0); + setQrFramesTotal(0); + setQrManualMode(false); + setQrCodeUrl(qrDataUrl); + setQrFramesTotal(1); + setQrFrameIndex(1); + return; + } + } catch (e) { + console.warn('Compressed QR generation failed, falling back to plain:', e?.message || e); + } + } + + // Final fallback to plain JSON + const payload = typeof data === 'string' ? data : JSON.stringify(data); if (payload.length <= MAX_QR_LEN) { if (!window.generateQRCode) throw new Error('QR code generator unavailable'); try { if (qrAnimationRef.current && qrAnimationRef.current.timer) { clearInterval(qrAnimationRef.current.timer); } } catch {} @@ -2184,6 +2227,7 @@ return; } + // Large payload: разбиваем на фреймы (plain JSON) try { if (qrAnimationRef.current && qrAnimationRef.current.timer) { clearInterval(qrAnimationRef.current.timer); } } catch {} qrAnimationRef.current = { timer: null, chunks: [], idx: 0, active: false }; setQrFrameIndex(0); @@ -2214,12 +2258,12 @@ setQrFramesTotal(rawChunks.length); setQrFrameIndex(1); const EC_OPTS = { errorCorrectionLevel: 'M', margin: 2, size: QR_SIZE }; - await renderNext(); + await renderNext(); if (!qrManualMode) { const intervalMs = 4000; // 4 seconds per frame for better readability - qrAnimationRef.current.active = true; - qrAnimationRef.current.timer = setInterval(renderAndAdvance, intervalMs); + qrAnimationRef.current.active = true; + qrAnimationRef.current.timer = setInterval(renderAndAdvance, intervalMs); } return; } catch (error) { @@ -2303,7 +2347,172 @@ const handleQRScan = async (scannedData) => { try { - // Prefer binary (CBOR) decode, else gzip JSON, else raw JSON + console.log('QR Code scanned:', scannedData.substring(0, 100) + '...'); + console.log('Current buffer state:', qrChunksBufferRef.current); + + // Check if this is a binary chunk (starts with SB1:bin: or is a raw binary chunk) + if (scannedData.startsWith('SB1:bin:') || (qrChunksBufferRef.current && qrChunksBufferRef.current.id)) { + console.log('Binary chunk detected:', scannedData.substring(0, 50) + '...'); + + // This is a binary chunk - add to buffer + if (!qrChunksBufferRef.current.id) { + console.log('Initializing buffer for binary chunks'); + // Initialize buffer for binary chunks + qrChunksBufferRef.current = { + id: `bin_${Date.now()}`, + total: 4, // We expect 4 chunks + seen: new Set(), + items: [], + lastUpdateMs: Date.now() + }; + } + + // Add chunk to buffer (use data hash as identifier) + const chunkHash = scannedData.substring(0, 50); // Use first 50 chars as hash + + // Check if this chunk was already scanned + if (qrChunksBufferRef.current.seen.has(chunkHash)) { + console.log(`Chunk already scanned, ignoring...`); + return Promise.resolve(false); + } + + qrChunksBufferRef.current.seen.add(chunkHash); + qrChunksBufferRef.current.items.push(scannedData); + qrChunksBufferRef.current.lastUpdateMs = Date.now(); + + // Emit progress and force re-render + try { + const uniqueCount = qrChunksBufferRef.current.seen.size; + document.dispatchEvent(new CustomEvent('qr-scan-progress', { + detail: { + id: qrChunksBufferRef.current.id, + seq: uniqueCount, + total: qrChunksBufferRef.current.total + } + })); + + // Force re-render to update progress indicator + setQrFramesTotal(qrChunksBufferRef.current.total); + setQrFrameIndex(uniqueCount); + } catch {} + + // Check if we have all chunks + const isComplete = qrChunksBufferRef.current.seen.size >= qrChunksBufferRef.current.total; + console.log(`Chunks collected: ${qrChunksBufferRef.current.seen.size}/${qrChunksBufferRef.current.total}, complete: ${isComplete}`); + + if (!isComplete) { + // Keep scanner open for more chunks + console.log(`Scanned chunk ${qrChunksBufferRef.current.seen.size}/${qrChunksBufferRef.current.total}, waiting for more...`); + return Promise.resolve(false); + } + + // All chunks collected - reconstruct binary data + try { + const fullBinaryData = qrChunksBufferRef.current.items.join(''); + // Store the original binary data, not decoded JSON + if (showOfferStep) { + setAnswerInput(fullBinaryData); + } else { + setOfferInput(fullBinaryData); + } + + setMessages(prev => [...prev, { + message: 'All binary chunks captured. Payload reconstructed.', + type: 'success' + }]); + + // Clear buffer and close scanner + qrChunksBufferRef.current = { id: null, total: 0, seen: new Set(), items: [] }; + setShowQRScannerModal(false); + return Promise.resolve(true); + } catch (e) { + console.warn('Binary chunks reconstruction failed:', e); + return Promise.resolve(false); + } + } + + // Check if this might be a binary chunk (long string without JSON structure) + if (scannedData.length > 100 && !scannedData.startsWith('{') && !scannedData.startsWith('[')) { + console.log('Detected potential binary chunk (long non-JSON string):', scannedData.substring(0, 50) + '...'); + + // Initialize buffer if not exists + if (!qrChunksBufferRef.current.id) { + console.log('Initializing buffer for potential binary chunks'); + qrChunksBufferRef.current = { + id: `bin_${Date.now()}`, + total: 4, // We expect 4 chunks + seen: new Set(), + items: [], + lastUpdateMs: Date.now() + }; + } + + // Add chunk to buffer (use data hash as identifier) + const chunkHash = scannedData.substring(0, 50); // Use first 50 chars as hash + + // Check if this chunk was already scanned + if (qrChunksBufferRef.current.seen.has(chunkHash)) { + console.log(`Chunk already scanned, ignoring...`); + return Promise.resolve(false); + } + + qrChunksBufferRef.current.seen.add(chunkHash); + qrChunksBufferRef.current.items.push(scannedData); + qrChunksBufferRef.current.lastUpdateMs = Date.now(); + + // Force re-render to update progress indicator + try { + const uniqueCount = qrChunksBufferRef.current.seen.size; + document.dispatchEvent(new CustomEvent('qr-scan-progress', { + detail: { + id: qrChunksBufferRef.current.id, + seq: uniqueCount, + total: qrChunksBufferRef.current.total + } + })); + + // Force re-render to update progress indicator + setQrFramesTotal(qrChunksBufferRef.current.total); + setQrFrameIndex(uniqueCount); + } catch {} + + // Check if we have all chunks + const isComplete = qrChunksBufferRef.current.seen.size >= qrChunksBufferRef.current.total; + console.log(`Chunks collected: ${qrChunksBufferRef.current.seen.size}/${qrChunksBufferRef.current.total}, complete: ${isComplete}`); + + if (!isComplete) { + // Keep scanner open for more chunks + console.log(`Scanned chunk ${qrChunksBufferRef.current.seen.size}/${qrChunksBufferRef.current.total}, waiting for more...`); + return Promise.resolve(false); + } + + // All chunks collected - reconstruct binary data + try { + const fullBinaryData = qrChunksBufferRef.current.items.join(''); + // Store the original binary data, not decoded JSON + if (showOfferStep) { + setAnswerInput(fullBinaryData); + } else { + setOfferInput(fullBinaryData); + } + + setMessages(prev => [...prev, { + message: 'All binary chunks captured. Payload reconstructed.', + type: 'success' + }]); + + // Clear buffer and close scanner + qrChunksBufferRef.current = { id: null, total: 0, seen: new Set(), items: [] }; + setShowQRScannerModal(false); + return Promise.resolve(true); + } catch (e) { + console.warn('Binary chunks reconstruction failed:', e); + return Promise.resolve(false); + } + } + + // Single QR code - try to decode directly + console.log('Processing single QR code:', scannedData.substring(0, 50) + '...'); let parsedData; if (typeof window.decodeAnyPayload === 'function') { const any = window.decodeAnyPayload(scannedData); @@ -2316,6 +2525,7 @@ const maybeDecompressed = (typeof window.decompressIfNeeded === 'function') ? window.decompressIfNeeded(scannedData) : scannedData; parsedData = JSON.parse(maybeDecompressed); } + console.log('Decoded data:', parsedData); // QR with hdr/body: COSE or RAW/BIN animated frames if (parsedData.hdr && parsedData.body) { @@ -2529,24 +2739,27 @@ setOfferData(offer); setShowOfferStep(true); - // Do not auto-generate single QR; prepare animated binary frames when user opens QR + // Generate QR code with binary format and chunking const offerString = typeof offer === 'object' ? JSON.stringify(offer) : offer; try { if (typeof window.encodeBinaryToPrefixed === 'function') { const bin = window.encodeBinaryToPrefixed(offerString); - // Precompute frames to be ready instantly on show - const id = `bin_${Date.now()}_${Math.random().toString(36).slice(2)}`; - const TARGET_CHUNKS = 10; + // Force chunking into 4 parts - split binary data directly + const TARGET_CHUNKS = 4; let FRAME_MAX = Math.max(200, Math.floor(bin.length / TARGET_CHUNKS)); if (FRAME_MAX <= 0) FRAME_MAX = 200; let total = Math.ceil(bin.length / FRAME_MAX); if (total < 2) { total = 2; FRAME_MAX = Math.ceil(bin.length / 2) || 1; } + + const id = `bin_${Date.now()}_${Math.random().toString(36).slice(2)}`; const chunks = []; for (let i = 0; i < total; i++) { const seq = i + 1; const part = bin.slice(i * FRAME_MAX, (i + 1) * FRAME_MAX); - chunks.push(JSON.stringify({ hdr: { v: 1, id, seq, total, rt: 'bin' }, body: part })); + // Store binary chunks directly without JSON wrapper + chunks.push(part); } + // Seed first frame and start auto-advance immediately const isDesktop = (typeof window !== 'undefined') && ((window.innerWidth || 0) >= 1024); const QR_SIZE = isDesktop ? 720 : 512; @@ -2554,20 +2767,27 @@ const firstUrl = await window.generateQRCode(chunks[0], { errorCorrectionLevel: 'M', size: QR_SIZE, margin: 2 }); if (firstUrl) setQrCodeUrl(firstUrl); } + // Store precomputed chunks to ref, ready for animation try { if (qrAnimationRef.current && qrAnimationRef.current.timer) { clearInterval(qrAnimationRef.current.timer); } } catch {} qrAnimationRef.current = { timer: null, chunks, idx: 0, active: true }; setQrFramesTotal(chunks.length); setQrFrameIndex(1); setQrManualMode(false); + // Start auto-advance loop for Offer immediately const intervalMs = 3000; qrAnimationRef.current.timer = setInterval(renderAndAdvance, intervalMs); + // Show QR immediately for Offer flow try { setShowQRCode(true); } catch {} + } else { + // Fallback to single QR + await generateQRCode(offer); + try { setShowQRCode(true); } catch {} } } catch (e) { - console.warn('Offer QR precompute failed:', e); + console.warn('Offer QR generation failed:', e); } const existingMessages = messages.filter(m => @@ -2656,46 +2876,48 @@ setAnswerData(answer); setShowAnswerStep(true); - // Answer QR: precompute binary frames and start animation immediately + // Generate QR code with binary format and chunking const answerString = typeof answer === 'object' ? JSON.stringify(answer) : answer; try { if (typeof window.encodeBinaryToPrefixed === 'function') { const bin = window.encodeBinaryToPrefixed(answerString); - const id = `ans_${Date.now()}_${Math.random().toString(36).slice(2)}`; - const TARGET_CHUNKS = 10; + // Force chunking into 4 parts - split binary data directly + const TARGET_CHUNKS = 4; let FRAME_MAX = Math.max(200, Math.floor(bin.length / TARGET_CHUNKS)); if (FRAME_MAX <= 0) FRAME_MAX = 200; let total = Math.ceil(bin.length / FRAME_MAX); if (total < 2) { total = 2; FRAME_MAX = Math.ceil(bin.length / 2) || 1; } + + const id = `ans_${Date.now()}_${Math.random().toString(36).slice(2)}`; const chunks = []; for (let i = 0; i < total; i++) { const seq = i + 1; const part = bin.slice(i * FRAME_MAX, (i + 1) * FRAME_MAX); - chunks.push(JSON.stringify({ hdr: { v: 1, id, seq, total, rt: 'bin' }, body: part })); + // Store binary chunks directly without JSON wrapper + chunks.push(part); } + const isDesktop = (typeof window !== 'undefined') && ((window.innerWidth || 0) >= 1024); const QR_SIZE = isDesktop ? 720 : 512; if (window.generateQRCode && chunks.length > 0) { const firstUrl = await window.generateQRCode(chunks[0], { errorCorrectionLevel: 'M', size: QR_SIZE, margin: 2 }); if (firstUrl) setQrCodeUrl(firstUrl); } + try { if (qrAnimationRef.current && qrAnimationRef.current.timer) { clearInterval(qrAnimationRef.current.timer); } } catch {} qrAnimationRef.current = { timer: null, chunks, idx: 0, active: true }; setQrFramesTotal(chunks.length); setQrFrameIndex(1); setQrManualMode(false); + const intervalMs = 3000; qrAnimationRef.current.timer = setInterval(renderAndAdvance, intervalMs); + + // Show QR immediately for Answer flow try { setShowQRCode(true); } catch {} } else { - // Fallback: single QR compressed or plain - let url = ''; - if (typeof window.generateCompressedQRCode === 'function') { - url = await window.generateCompressedQRCode(answerString); - } else { - url = await generateQRCode(answerString); - } - if (url) setQrCodeUrl(url); + // Fallback to single QR + await generateQRCode(answer); try { setShowQRCode(true); } catch {} } } catch (e) { @@ -2989,6 +3211,8 @@ setShowQRCode(false); setShowQRScanner(false); setShowQRScannerModal(false); + // Clear QR scanner buffer + qrChunksBufferRef.current = { id: null, total: 0, seen: new Set(), items: [] }; if (!shouldPreserveAnswerData()) { setQrCodeUrl(''); @@ -3117,6 +3341,105 @@ addMessageWithAutoScroll(' All security features enabled by default', 'system'); } }, [isConnectedAndVerified, pendingSession, connectionStatus]); + + // QR Scanner initialization + React.useEffect(() => { + if (showQRScannerModal && window.Html5Qrcode) { + const html5Qrcode = new window.Html5Qrcode("qr-reader"); + const config = { + fps: 10 + // Убираем qrbox чтобы использовать всю область + }; + + let isScanning = true; + + html5Qrcode.start( + { facingMode: "environment" }, // Use back camera + config, + (decodedText, decodedResult) => { + if (!isScanning) { + console.log('Scanner stopped, ignoring scan'); + return; + } + + console.log('QR Code scanned:', decodedText); + console.log('Current buffer state:', qrChunksBufferRef.current); + + handleQRScan(decodedText).then((success) => { + console.log('QR scan result:', success); + if (success) { + // Successfully processed - stop scanner and close modal + console.log('Closing scanner and modal'); + isScanning = false; + + // Stop scanner first, then clear + try { + console.log('Stopping scanner...'); + html5Qrcode.stop().then(() => { + console.log('Scanner stopped, clearing...'); + html5Qrcode.clear(); + setShowQRScannerModal(false); + }).catch((err) => { + console.log('Error stopping scanner:', err); + // Try to clear anyway + try { + html5Qrcode.clear(); + } catch (clearErr) { + console.log('Error clearing scanner:', clearErr); + } + setShowQRScannerModal(false); + }); + } catch (err) { + console.log('Error in scanner cleanup:', err); + setShowQRScannerModal(false); + } + } else { + console.log('Continuing to scan for more chunks...'); + } + }).catch((error) => { + console.error('QR scan processing error:', error); + // Continue scanning on error + }); + }, + (error) => { + // Ignore scanning errors - continue scanning + if (isScanning) { + console.log('QR scan error (ignored):', error); + } + } + ).catch((err) => { + console.error('QR Scanner start error:', err); + // Close modal on start error + setShowQRScannerModal(false); + }); + + return () => { + isScanning = false; + try { + // Try to stop scanner, but don't worry if it's already stopped + html5Qrcode.stop().then(() => { + html5Qrcode.clear(); + }).catch((err) => { + // Scanner might already be stopped, just clear it + console.log('Scanner already stopped or error stopping:', err); + try { + html5Qrcode.clear(); + } catch (clearErr) { + console.log('Error clearing scanner in cleanup:', clearErr); + } + }); + } catch (err) { + console.log('Error in cleanup:', err); + // Just try to clear, don't worry about stopping + try { + html5Qrcode.clear(); + } catch (clearErr) { + console.log('Error clearing scanner in cleanup:', clearErr); + } + } + }; + } + }, [showQRScannerModal]); return React.createElement('div', { className: "minimal-bg min-h-screen" @@ -3193,6 +3516,82 @@ }) ), + // QR Scanner Modal + showQRScannerModal && React.createElement('div', { + key: 'qr-scanner-modal', + className: "fixed inset-0 bg-black/80 flex items-center justify-center z-50" + }, [ + React.createElement('div', { + key: 'scanner-container', + className: "bg-gray-900 rounded-lg p-4 max-w-2xl w-full mx-4" + }, [ + React.createElement('div', { + key: 'scanner-header', + className: "flex items-center justify-between mb-4" + }, [ + React.createElement('h3', { + key: 'scanner-title', + className: "text-lg font-medium text-white" + }, 'QR Code Scanner'), + React.createElement('button', { + key: 'close-btn', + onClick: () => { + setShowQRScannerModal(false); + // Clear QR scanner buffer + qrChunksBufferRef.current = { id: null, total: 0, seen: new Set(), items: [] }; + }, + className: "text-gray-400 hover:text-white" + }, [ + React.createElement('i', { + key: 'close-icon', + className: 'fas fa-times' + }) + ]) + ]), + React.createElement('div', { + key: 'scanner-content', + className: "text-center" + }, [ + React.createElement('p', { + key: 'scanner-description', + className: "text-gray-400 mb-4" + }, 'Point your camera at the QR code to scan'), + qrChunksBufferRef.current && qrChunksBufferRef.current.id && React.createElement('div', { + key: 'progress-indicator', + className: "mb-4 p-3 bg-blue-500/10 border border-blue-500/20 rounded-lg" + }, [ + React.createElement('p', { + key: 'progress-text', + className: "text-blue-400 text-sm" + }, `Scanned: ${qrChunksBufferRef.current.seen.size}/${qrChunksBufferRef.current.total} parts`), + React.createElement('div', { + key: 'progress-bar', + className: "w-full bg-gray-700 rounded-full h-2 mt-2" + }, [ + React.createElement('div', { + key: 'progress-fill', + className: "bg-blue-500 h-2 rounded-full transition-all duration-300", + style: { + width: `${(qrChunksBufferRef.current.seen.size / qrChunksBufferRef.current.total) * 100}%` + } + }) + ]) + ]), + React.createElement('div', { + key: 'scanner-placeholder', + id: "qr-reader", + className: "w-full h-96 bg-gray-800 rounded-lg flex items-center justify-center", + style: { minHeight: '400px' } + }, [ + React.createElement('p', { + key: 'scanner-placeholder-text', + className: "text-gray-500" + }, 'Camera will start here...') + ]) + ]) + ]) + ]) + ]); }; function initializeApp() {