1/** 2 * Evita reidratar carrinho abandonado após esvaziar localmente e sair rápido de /carrinho. 3 * Patch leve no $pd â não exige rebuild do main.js. 4 * 5 * Proteções: 6 * - flag de esvaziamento em localStorage (WebViews como Instagram não persistem sessionStorage) 7 * - cancelamento de POSTs stale (last-write-wins) 8 * - sync vazio com retry antes de navegar ao cardápio 9 */ 10(function () { 11 var CLEARED_TTL_MS = 10 * 60 * 1000; 12 var SAVE_DEBOUNCE_MS = 100; 13 var EMPTY_SYNC_RETRIES = 2; 14 15 function cookieName() { 16 return window.$CLIENTE + '_Cart'; 17 } 18 19 function clearedFlagKey() { 20 return window.$CLIENTE + '_cart_user_cleared'; 21 } 22 23 function getLocalItems() { 24 try { 25 var raw = localStorage.getItem(cookieName()); 26 if (!raw) { 27 return []; 28 } 29 var parsed = JSON.parse(raw); 30 return Array.isArray(parsed) ? parsed : []; 31 } catch (e) { 32 return []; 33 } 34 } 35 36 function setLocalItems(items) { 37 try { 38 localStorage.setItem(cookieName(), JSON.stringify(items || [])); 39 } catch (e) {} 40 } 41 42 function markCleared() { 43 var payload = JSON.stringify({ t: Date.now() }); 44 try { 45 localStorage.setItem(clearedFlagKey(), payload); 46 sessionStorage.setItem(clearedFlagKey(), '1'); 47 } catch (e) {} 48 } 49 50 function isCartUserCleared() { 51 if (getLocalItems().length > 0) { 52 return false; 53 } 54 55 try { 56 var raw = localStorage.getItem(clearedFlagKey()); 57 if (raw) { 58 var parsed = JSON.parse(raw); 59 if (parsed && parsed.t && (Date.now() - parsed.t) < CLEARED_TTL_MS) { 60 return true; 61 } 62 localStorage.removeItem(clearedFlagKey()); 63 } 64 } catch (e) {} 65 66 try { 67 if (sessionStorage.getItem(clearedFlagKey())) { 68 return true; 69 } 70 } catch (e2) {} 71 72 return false; 73 } 74 75 function clearClearedFlag() { 76 try { 77 localStorage.removeItem(clearedFlagKey()); 78 sessionStorage.removeItem(clearedFlagKey()); 79 } catch (e) {} 80 } 81 82 function bumpCartSaveGeneration(vm) { 83 vm.__cartSaveGeneration = (vm.__cartSaveGeneration || 0) + 1; 84 return vm.__cartSaveGeneration; 85 } 86 87 function abortCartSaveXhr(vm) { 88 if (vm.__cartSaveXhr && vm.__cartSaveXhr.readyState !== 4) { 89 try { 90 vm.__cartSaveXhr.abort(); 91 } catch (e) {} 92 } 93 vm.__cartSaveXhr = null; 94 } 95 96 function cancelCartSaveTimeout(vm) { 97 if (vm.idTimeout) { 98 clearTimeout(vm.idTimeout); 99 vm.idTimeout = null; 100 } 101 } 102 103 function trackCartSaveXhr(vm, xhr) { 104 vm.__cartSaveXhr = xhr; 105 xhr.always(function () { 106 if (vm.__cartSaveXhr === xhr) { 107 vm.__cartSaveXhr = null; 108 } 109 }); 110 return xhr; 111 } 112 113 function postCarrinhoAbandonado(payloadString) { 114 return window.jQuery.post(window.$ROOTURL + '/carrinho-abandonado', payloadString); 115 } 116 117 function postEmptyCart(vm, callback) { 118 abortCartSaveXhr(vm); 119 cancelCartSaveTimeout(vm); 120 var gen = bumpCartSaveGeneration(vm); 121 var payload = JSON.stringify({ 122 json: { 123 itens: [], 124 removidos: vm.produtos_removidos || [] 125 } 126 }); 127 128 function tryPost(retriesLeft) { 129 var xhr = trackCartSaveXhr(vm, postCarrinhoAbandonado(payload)); 130 xhr.done(function () { 131 if (gen !== vm.__cartSaveGeneration) { 132 return; 133 } 134 callback(true); 135 }).fail(function () { 136 if (gen !== vm.__cartSaveGeneration) { 137 return; 138 } 139 if (retriesLeft > 0) { 140 tryPost(retriesLeft - 1); 141 return; 142 } 143 callback(false); 144 }); 145 } 146 147 tryPost(EMPTY_SYNC_RETRIES); 148 } 149 150 function patchVm(vm) { 151 if (!vm || vm.__carrinhoEmptySyncPatched) { 152 return false; 153 } 154 155 if (typeof vm.Cart__loadCarrinhoAbandonado !== 'function') { 156 return false; 157 } 158 159 vm.__carrinhoEmptySyncPatched = true; 160 vm.__cartSaveGeneration = vm.__cartSaveGeneration || 0; 161 162 var originalLoad = vm.Cart__loadCarrinhoAbandonado.bind(vm); 163 var originalSaveAbandonado = vm.Cart__saveCarrinhoAbandonado.bind(vm); 164 165 vm.Cart__loadCarrinhoAbandonado = function () { 166 if (isCartUserCleared()) { 167 if (vm.cart && vm.cart.items && vm.cart.items.length) { 168 vm.cart.items.splice(0, vm.cart.items.length); 169 } 170 vm.produtos_removidos = vm.produtos_removidos || []; 171 172 if (vm.usuario && vm.usuario.logged) { 173 postEmptyCart(vm, function (ok) { 174 if (ok) { 175 clearClearedFlag(); 176 } 177 }); 178 } 179 return; 180 } 181 182 return originalLoad(); 183 }; 184 185 vm.Cart__saveCarrinhoAbandonado = function () { 186 abortCartSaveXhr(vm); 187 bumpCartSaveGeneration(vm); 188 189 var jq = window.jQuery; 190 var originalPost = jq.post; 191 192 jq.post = function (url, data, success, dataType) { 193 if (typeof url === 'string' && url.indexOf('carrinho-abandonado') !== -1) { 194 var xhr = originalPost.call(jq, url, data, success, dataType); 195 trackCartSaveXhr(vm, xhr); 196 jq.post = originalPost; 197 return xhr; 198 } 199 return originalPost.apply(jq, arguments); 200 }; 201
202 try { 203 originalSaveAbandonado(); 204 } finally { 205 jq.post = originalPost; 206 } 207 }; 208 209 vm.Cart__save = function () { 210 if (typeof vm.Cart__valideItens === 'function') { 211 vm.Cart__valideItens(); 212 } 213 214 if (vm.cart && vm.cart.items) { 215 setLocalItems(vm.cart.items); 216 if (vm.cart.items.length === 0) { 217 markCleared(); 218 } else { 219 clearClearedFlag(); 220 } 221 } 222 223 if (typeof vm.Cart__cupom__check === 'function') { 224 vm.Cart__cupom__check(); 225 } 226 if (typeof vm.Cart__cupom__add === 'function') { 227 var cupom = vm.cart && vm.cart.cupom ? vm.cart.cupom.cup_codigo : null; 228 vm.Cart__cupom__add(cupom); 229 } 230 231 cancelCartSaveTimeout(vm); 232 233 vm.idTimeout = setTimeout(function () { 234 vm.idTimeout = null; 235 if (vm.usuario && vm.usuario.logged && vm.pageReady && typeof vm.Cart__saveCarrinhoAbandonado === 'function') { 236 vm.Cart__saveCarrinhoAbandonado(); 237 } 238 }, SAVE_DEBOUNCE_MS); 239 }; 240 241 vm.Cart__voltarCardapio = function (url) { 242 var isEmpty = !vm.cart || !vm.cart.items || vm.cart.items.length === 0; 243 244 cancelCartSaveTimeout(vm); 245 setLocalItems(isEmpty ? [] : (vm.cart ? vm.cart.items : [])); 246 247 if (isEmpty) { 248 markCleared(); 249 } 250 251 var navigate = function () { 252 window.location.href = url; 253 }; 254 255 if (vm.usuario && vm.usuario.logged && isEmpty && window.jQuery) { 256 postEmptyCart(vm, navigate); 257 return; 258 } 259 260 navigate(); 261 }; 262 263 if (typeof vm.Cart__set === 'function') { 264 var originalSet = vm.Cart__set.bind(vm); 265 vm.Cart__set = function () { 266 clearClearedFlag(); 267 return originalSet.apply(vm, arguments); 268 }; 269 } 270 271 return true; 272 } 273 274 function tryPatch() { 275 if (window.$pd && patchVm(window.$pd)) { 276 return true; 277 } 278 return false; 279 } 280 281 function startPolling() { 282 if (tryPatch()) { 283 return; 284 } 285 286 var attempts = 0; 287 var timer = window.setInterval(function () { 288 attempts += 1; 289 if (tryPatch() || attempts > 120) { 290 window.clearInterval(timer); 291 } 292 }, 50); 293 } 294 295 if (document.readyState === 'loading') { 296 document.addEventListener('DOMContentLoaded', startPolling); 297 } else { 298 startPolling(); 299 } 300})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.