{"version":3,"sources":["chat.core.js","chat.luckyorange.js","chat.notify.js","chat.emojis.js","chat.auth.js","chat.error.js","chat.browser.js","chat.message.js","chat.push.js","chat.user.js","chat.modal.js","chat.stream.js","chat.settings.js","chat.payment.js","chat.room.js","chat.popover.js","chat.alertstream.js","chat.pinned.js","chat.filterpanel.js","chat.widget.tradingview.js","chat.widget.videobox.js","chat.invites.js","chat.introtutorial.js","chat.brokers.js","chat.right-panel.js","chat.templates.js","chat.alert.refresh.js","chat.widgets-top-modals.js","chat.analytics.google.js","chat.layout.js","chat.pin-message.js","chat.istyping.js","chat.session.js","chat.default.js"],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9uCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/SA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACx7BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC74CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9RA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxfA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnSA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/MA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/QA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvUA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtWA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/LA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrVA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzoCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/KA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"chat.min.js","sourcesContent":["'use strict';\r\n\r\nangular.module('chat.core', [])\r\n.config(['$routeProvider', '$locationProvider', function ($routeProvider, $locationProvider) {\r\n // check if an element exists in array using a comparer function\r\n // comparer : function(currentElement)\r\n Array.prototype.inArray = function (comparer) {\r\n for (var i = 0; i < this.length; i++) {\r\n if (comparer(this[i])) return true;\r\n }\r\n return false;\r\n };\r\n\r\n // adds an element to the array if it does not already exist using a comparer \r\n // function\r\n Array.prototype.pushIfNotExist = function (element, comparer) {\r\n if (!this.inArray(comparer)) {\r\n this.push(element);\r\n }\r\n };\r\n\r\n /*! https://mths.be/startswith v0.2.0 by @mathias */\r\n if (!String.prototype.startsWith) {\r\n (function () {\r\n 'use strict'; // needed to support `apply`/`call` with `undefined`/`null`\r\n var defineProperty = (function () {\r\n // IE 8 only supports `Object.defineProperty` on DOM elements\r\n try {\r\n var object = {};\r\n var $defineProperty = Object.defineProperty;\r\n var result = $defineProperty(object, object, object) && $defineProperty;\r\n } catch (error) { }\r\n return result;\r\n }());\r\n var toString = {}.toString;\r\n var startsWith = function (search) {\r\n if (this == null) {\r\n throw TypeError();\r\n }\r\n var string = String(this);\r\n if (search && toString.call(search) == '[object RegExp]') {\r\n throw TypeError();\r\n }\r\n var stringLength = string.length;\r\n var searchString = String(search);\r\n var searchLength = searchString.length;\r\n var position = arguments.length > 1 ? arguments[1] : undefined;\r\n // `ToInteger`\r\n var pos = position ? Number(position) : 0;\r\n if (pos != pos) { // better `isNaN`\r\n pos = 0;\r\n }\r\n var start = Math.min(Math.max(pos, 0), stringLength);\r\n // Avoid the `indexOf` call if no match is possible\r\n if (searchLength + start > stringLength) {\r\n return false;\r\n }\r\n var index = -1;\r\n while (++index < searchLength) {\r\n if (string.charCodeAt(start + index) != searchString.charCodeAt(index)) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n };\r\n if (defineProperty) {\r\n defineProperty(String.prototype, 'startsWith', {\r\n 'value': startsWith,\r\n 'configurable': true,\r\n 'writable': true\r\n });\r\n } else {\r\n String.prototype.startsWith = startsWith;\r\n }\r\n }());\r\n }\r\n\r\n $routeProvider.\r\n when('/', {\r\n templateUrl: 'messages-screen.html',\r\n controller: 'messagesController'\r\n })\r\n .when('/:id', {\r\n templateUrl: 'messages-screen.html',\r\n controller: 'messagesController'\r\n });\r\n\r\n $locationProvider.html5Mode(true).hashPrefix('#');\r\n\r\n }])\r\n .config( [\r\n '$compileProvider',\r\n function( $compileProvider )\r\n { \r\n $compileProvider.aHrefSanitizationWhitelist(/^\\s*(https?|ftp|mailto|echofin):/);\r\n // Angular before v1.2 uses $compileProvider.urlSanitizationWhitelist(...)\r\n }\r\n]);\r\n;\r\n","'use strict';\r\nangular.module('chat.luckyorange', [])\r\n\r\n .directive('luckyorange', ['userService', function (userService) {\r\n return {\r\n replace: true,\r\n templateUrl: 'luckyorange.html',\r\n scope: {\r\n ison: \"=\",\r\n },\r\n link: function (scope) {\r\n },\r\n controller: function ($scope) {\r\n $scope.$watch(function () {\r\n return userService.username\r\n }, function (nv) {\r\n if (nv == \"petra\") {\r\n $scope.ison = true\r\n }\r\n })\r\n }\r\n } \r\n\r\n }])\r\n\r\n .service('luckyService', ['$window', function ($window) {\r\n var l_objTags = {};\r\n\r\n $window.__wtw_custom_user_data = {};\r\n //$window.__wtw_custom_user_data.app = 'chat';\r\n\r\n var _setUser = function (a_objUser) {\r\n $window.__wtw_custom_user_data.username = a_objUser.username\r\n $window.__wtw_custom_user_data.team = a_objUser.team\r\n }\r\n\r\n return {\r\n setUser: _setUser\r\n }\r\n\r\n }])\r\n ;","'use strict';\r\n\r\nangular.module('chat.notify', ['ngAlertify', 'chat.error'])\r\n .service('notifyService', ['alertify', 'AppError', function (alertify, AppError) { //https://alertifyjs.org/\r\n var _showInfo = function (message) {\r\n alertify.log(message);\r\n };\r\n\r\n var _showSuccess = function (message) {\r\n alertify.success(message);\r\n };\r\n\r\n var _showError = function (message) {\r\n alertify.error(message);\r\n };\r\n var _showConsoleError = function (title, message) {\r\n // console.log('_showConsoleError', {\r\n // title: title,\r\n // message: message\r\n //});\r\n AppError.Send('_showConsoleError', {\r\n title: title,\r\n message: message\r\n });\r\n _showError(message);\r\n };\r\n var _confirm = function (a_strTitle, a_objOKCallback, a_objCancelCallback) {\r\n alertify.confirm(a_strTitle, a_objOKCallback, a_objCancelCallback);\r\n };\r\n var _confirmCustom = function (a_strTitle, a_objOKCallback, a_objCancelCallback, a_strOK, a_strCancel) {\r\n alertify.okBtn(a_strOK);\r\n alertify.cancelBtn(a_strCancel);\r\n alertify.confirm(a_strTitle, a_objOKCallback, a_objCancelCallback);\r\n };\r\n var _paymentSucccess = function (url) {\r\n alertify.alert('Your payment was successful.', function () {\r\n location.reload();\r\n });\r\n };\r\n return {\r\n success: _showSuccess,\r\n error: _showError,\r\n info: _showInfo,\r\n showError: _showConsoleError,\r\n confirm: _confirm,\r\n paymentSucccess: _paymentSucccess,\r\n confirmCustom: _confirmCustom\r\n };\r\n }]);","'use strict';\r\n\r\nangular\r\n .module('chat.emojis', [])\r\n .service('emojiService', ['$http', function ($http) {\r\n var l_lstEmojis = [];\r\n\r\n var _setEmojis = function (a_lstEmojis) {\r\n l_lstEmojis = a_lstEmojis;\r\n };\r\n\r\n var _getEmojis = function () {\r\n return l_lstEmojis;\r\n };\r\n\r\n var _getEmojiByCode = function (a_strCode) {\r\n if (l_lstEmojis == null)\r\n return null;\r\n for (var i = 0; i < l_lstEmojis.length; i++) {\r\n if (l_lstEmojis[i].code == a_strCode) {\r\n var _emojiMap = {\r\n s_img: l_lstEmojis[i].img\r\n }\r\n return _emojiMap;\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n var _getEmojisForChatbox = function () {\r\n var l_lstRet = [];\r\n if (l_lstEmojis != null) {\r\n for (var i = 0; i < l_lstEmojis.length; i++) {\r\n l_lstRet.push({\r\n id: l_lstEmojis[i].pkn_id,\r\n code: l_lstEmojis[i].s_code,\r\n img: l_lstEmojis[i].s_img,\r\n title: l_lstEmojis[i].s_title,\r\n reference: l_lstEmojis[i].b_reference,\r\n tab: l_lstEmojis[i].s_tab\r\n });\r\n }\r\n }\r\n return l_lstRet;\r\n };\r\n\r\n var _setEmojisFromJSON = function () {\r\n return $http\r\n .get(\"https://cdnjs.echofin.co/plugins/chatbox/emojis/list.svg.json\")\r\n .then(function (result) {\r\n l_lstEmojis = result.data\r\n });\r\n };\r\n\r\n return {\r\n setEmojis: _setEmojis,\r\n getEmojis: _getEmojis,\r\n getEmojisForChatbox: _getEmojisForChatbox,\r\n getEmojiByCode: _getEmojiByCode,\r\n setEmojisFromJSON: _setEmojisFromJSON,\r\n }\r\n }]);","'use strict';\r\n\r\nangular.module('chat.auth', [\r\n 'chat.browser',\r\n 'chat.error'\r\n ])\r\n .factory('tokenService', ['$rootScope', '$window', 'AppError', function ($rootScope, $window, AppError) {\r\n\r\n var _removeCookie = function (name, path, domain) {\r\n if (storage(name)) {\r\n document.cookie = name + \"=\" +\r\n ((path) ? \";path=\" + path : \"\") +\r\n ((domain) ? \";domain=\" + domain : \"\") +\r\n \";expires=Thu, 01 Jan 1970 00:00:01 GMT\";\r\n }\r\n }\r\n\r\n var removeItem = function (key) {\r\n try {\r\n $window.localStorage.removeItem(key);\r\n _removeCookie(key);\r\n } catch (e) {\r\n _removeCookie(key);\r\n }\r\n }\r\n\r\n var service = {\r\n model: {\r\n\r\n access_token: null,\r\n expires_in: null,\r\n token_type: null\r\n },\r\n Logout: function () {\r\n removeItem('tokenData');\r\n\r\n window.parent.postMessage({\r\n event: \"userReset\",\r\n }, \"*\")\r\n\r\n $window.location.reload();\r\n },\r\n RestoreState: function () {\r\n var l_strKey = storage('tokenData');\r\n if (l_strKey) {\r\n try {\r\n service.model = JSON.parse(l_strKey);\r\n } catch (e) {\r\n AppError.Send(e, l_strKey);\r\n rg4js('RestoreState key: ' + l_strKey, {\r\n error: e\r\n });\r\n }\r\n }\r\n },\r\n getItem: function (key) {\r\n return storage(key);\r\n },\r\n setItem: function (key, value) {\r\n storage(key, value);\r\n },\r\n removeItem: function () {\r\n removeItem('tokenData');\r\n }\r\n };\r\n\r\n $rootScope.$on(\"savestate\", service.SaveState);\r\n $rootScope.$on(\"restorestate\", service.RestoreState);\r\n $rootScope.$on(\"clearstate\", service.RestoreState);\r\n\r\n return service;\r\n }])\r\n .factory('BearerAuthInterceptor', ['tokenService', '$q', function (tokenService, $q) {\r\n var l_blnLogout = false;\r\n return {\r\n request: function (config) {\r\n\r\n if (config.url.startsWith('https://www.googleapis.com')) {\r\n config.headers = {};\r\n\r\n return config;\r\n }\r\n\r\n config.headers = config.headers || {};\r\n if (tokenService.model.access_token != null && config.url.indexOf(\".json\") == -1) {\r\n config.headers.Authorization = 'Bearer ' + tokenService.model.access_token;\r\n }\r\n return config || $q.when(config);\r\n },\r\n response: function (response) {\r\n return response || $q.when(response);\r\n },\r\n responseError: function (response) {\r\n if (response.status === 401 && !l_blnLogout) {\r\n l_blnLogout = true;\r\n tokenService.removeItem();\r\n location.href = '/login';\r\n //tokenService.Logout();\r\n }\r\n }\r\n };\r\n }])\r\n .run(['tokenService', function (tokenService) {\r\n tokenService.RestoreState();\r\n if (tokenService.model.access_token == null)\r\n location.href = '/login';\r\n }])\r\n .config(['$httpProvider', function ($httpProvider, $routeProvider, $locationProvider) {\r\n $httpProvider.interceptors.push('BearerAuthInterceptor');\r\n }]);","'use strict';\r\n\r\nangular.module('chat.error', [])\r\n .factory('AppError', ['$log', function ($log) {\r\n var l_blnLogout = false;\r\n var l_intIncrement = 0;\r\n\r\n var _send = function (a_objException, a_objData) {\r\n l_intIncrement += 1;\r\n\r\n if (window.Raygun) {\r\n Raygun.send(a_objException, a_objData);\r\n }\r\n\r\n if (l_blnDebug || !window.Raygun)\r\n $log.debug(l_intIncrement.toString(), a_objException, a_objData);\r\n }\r\n\r\n return {\r\n Send: _send\r\n };\r\n }])\r\n .config(function ($provide) {\r\n $provide.decorator(\"$exceptionHandler\", ['$delegate', '$log', 'AppError', function ($delegate, $log, AppError) {\r\n return function (exception, cause) {\r\n AppError.Send(exception, cause);\r\n $delegate(exception, cause);\r\n };\r\n }]);\r\n })\r\n\r\n\r\n\r\n ;\r\n\r\n\r\n","angular\r\n .module('chat.browser', [\r\n 'chat.user'\r\n ])\r\n .service('NotificationsService', ['SessionService', 'userService', '$window', '$rootScope', function (SessionService, userService, $window, $rootScope) {\r\n\r\n var service = {\r\n _supported: true,\r\n isWindowFocused: false,\r\n setup: setup,\r\n notify: notify,\r\n }\r\n\r\n return service\r\n\r\n /// notify type\r\n /// 1 - Room\r\n /// 2 - Mention\r\n /// 3 - Direct\r\n function notify(title, message, file, avatar, timeout, type, roomKey) {\r\n if (!Notification || !service._supported) {\r\n alert('Desktop notifications not available in your browser. Try Chromium.');\r\n return;\r\n }\r\n\r\n if (!avatar || avatar == '') {\r\n avatar = 'https://cdn2.iconfinder.com/data/icons/circle-icons-1/64/caution-64.png';\r\n }\r\n\r\n if (!timeout || timeout == 0 || timeout > 30) {\r\n // 3 seconds is default\r\n timeout = 3000;\r\n } else {\r\n timeout = parseInt(timeout) * 1000;\r\n }\r\n\r\n var stripHtml = function (a_strHtml) {\r\n var tmp = document.createElement(\"DIV\");\r\n tmp.innerHTML = a_strHtml;\r\n return tmp.textContent || tmp.innerText || \"\";\r\n }\r\n\r\n if (Notification.permission !== \"granted\") {\r\n Notification.requestPermission();\r\n } else {\r\n //console.log('notify', {\r\n // isWindowFocused: service.isWindowFocused,\r\n // _checkToNotify: _checkToNotify(type, roomKey),\r\n // _isAdminNotif: _isAdminNotif(title)\r\n //});\r\n if (!service.isWindowFocused && (_checkToNotify(type, roomKey) || _isAdminNotif(title))) {\r\n\r\n if (_isFromAdmin(title) && !_allowedFromAdmin()) {\r\n return;\r\n }\r\n try {\r\n var snd = new Audio(\"https://cdn.echofin.co/sounds/notification.mp3\");\r\n snd.play();\r\n } catch (e) {\r\n\r\n };\r\n\r\n \r\n if (message) {\r\n if (message.indexOf(\"/shout\") === 0) {\r\n message = message.replace(\"/shout\", '📣')\r\n }\r\n if (isSignal(message)) {\r\n message = getFormatedSignalText(message)\r\n }\r\n }\r\n else if (file) {\r\n message = \"📊 Uploaded an image\"\r\n }\r\n\r\n if (window.isDesktopClient) {\r\n window.parent.postMessage({\r\n event: \"notificationSend\",\r\n notification: {\r\n icon: avatar,\r\n title: stripHtml(title),\r\n content: stripHtml(message),\r\n }\r\n }, \"*\");\r\n return;\r\n }\r\n\r\n var notification = new Notification(stripHtml(title), {\r\n icon: avatar,\r\n body: stripHtml(message)\r\n });\r\n\r\n notification.onclick = function () {\r\n window.focus();\r\n };\r\n\r\n setTimeout(function () {\r\n notification.close()\r\n }, timeout);\r\n }\r\n\r\n }\r\n\r\n }\r\n\r\n function setup() {\r\n\r\n document.addEventListener('DOMContentLoaded', function () {\r\n if (window.webkitNotifications) {\r\n if (Notification.permission !== \"granted\") {\r\n Notification.requestPermission();\r\n }\r\n }\r\n });\r\n\r\n try {\r\n Notification.requestPermission();\r\n } catch (e) {\r\n //not supported\r\n service._supported = false;\r\n }\r\n\r\n $window.addEventListener(\"focus\", function () {\r\n //console.debug(\"Windows focus detected\")\r\n $rootScope.$broadcast('FocusChange', true);\r\n service.isWindowFocused = true\r\n })\r\n\r\n $window.addEventListener(\"blur\", function () {\r\n //console.debug(\"Windows blur detected\")\r\n $rootScope.$broadcast('FocusChange', true);\r\n service.isWindowFocused = false\r\n })\r\n\r\n }\r\n\r\n function _checkToNotify(type, roomKey) {\r\n var l_objSettings = userService.getSettings();\r\n\r\n\r\n if (type == 1) {\r\n var _roomNotify = userService.allowRoomNotify(roomKey)\r\n return l_objSettings.notifications.notifyRooms && _roomNotify;\r\n };\r\n\r\n if (type == 2) {\r\n return l_objSettings.notifications.notifyMentions;\r\n };\r\n\r\n if (type == 3) {\r\n return l_objSettings.notifications.notifyDMs;\r\n };\r\n return false;\r\n\r\n }\r\n\r\n function _isFromAdmin(title) {\r\n var l_objSettings = userService.getSettings();\r\n var usernameSplit = title.replace(\"says:\", \"\").trim().split(\" \")\r\n var user = userService.getUserByName(usernameSplit[usernameSplit.length - 1])\r\n return user.type == 1 || user.type == 2 || user.type == 3\r\n }\r\n\r\n function _allowedFromAdmin(title) {\r\n var l_objSettings = userService.getSettings();\r\n return l_objSettings.notifications.notifyFromAdmins\r\n }\r\n\r\n function _isAdminNotif(title) {\r\n var l_objSettings = userService.getSettings();\r\n var usernameSplit = title.replace(\"says:\", \"\").trim().split(\" \")\r\n var user = userService.getUserByName(usernameSplit[usernameSplit.length - 1])\r\n var isSpecialUser = user.type == 1 || user.type == 2 || user.type == 3\r\n return (l_objSettings.notifications.notifyFromAdmins && isSpecialUser)\r\n }\r\n\r\n // REGION -- SHOULD MOVE TO chat.signal.js\r\n function isSignal(message) {\r\n return message.indexOf(\": SIGNAL
\") != -1\r\n }\r\n\r\n function parseSignal(message) {\r\n var splitMessage = message.split(\"
\")\r\n var message = {\r\n header: splitMessage[0],\r\n lines: [],\r\n }\r\n\r\n for (var i = 1; i < splitMessage.length; i++) {\r\n var splitLine = splitMessage[i].split(\": \")\r\n message.lines.push({\r\n label: splitLine[0],\r\n data: splitLine[1],\r\n });\r\n }\r\n return message;\r\n }\r\n\r\n function getFormatedSignalText(message) {\r\n var parsedSignal = parseSignal(message);\r\n\r\n var header = parsedSignal.header.replace(\":shout: SIGNAL\", \"📢\")\r\n .replace(\":bull: SIGNAL\", \"📈\")\r\n .replace(\":bear: SIGNAL\", \"📉\")\r\n\r\n var dataline = \"\";\r\n var comment = \"\";\r\n for (var i = 0; i < parsedSignal.lines.length; i++) {\r\n if (parsedSignal.lines[i].data) {\r\n dataline += parsedSignal.lines[i].label + \": \" + parsedSignal.lines[i].data + \" | \";\r\n }\r\n }\r\n\r\n var l_objSignalLine = parsedSignal.lines[parsedSignal.lines.length - 1];\r\n if (l_objSignalLine != null && !l_objSignalLine.data) {\r\n comment = \" | \" + l_objSignalLine.label;\r\n }\r\n\r\n var textTemplate = header + \" \" + dataline + comment;\r\n\r\n return textTemplate;\r\n }\r\n //END REGION\r\n }])\r\n\r\n .directive('whenScrolled', ['$timeout', '$rootScope', function ($timeout, $rootScope) {\r\n return function (scope, elm, attr) {\r\n var raw = elm[0];\r\n\r\n elm.bind('scroll', function () {\r\n if (raw.scrollHeight - raw.scrollTop < 300) {\r\n // console.log('scroll', raw.scrollHeight, raw.scrollTop, raw.scrollHeight - raw.scrollTop)\r\n $rootScope.$broadcast('MoveToBottom', raw);\r\n }\r\n if (raw.scrollTop == 0) {\r\n var sh = raw.scrollHeight\r\n scope.$apply(attr.whenScrolled).then(function () {\r\n $timeout(function () {\r\n raw.scrollTop = raw.scrollHeight - sh;\r\n })\r\n });\r\n }\r\n });\r\n };\r\n }])\r\n\r\n .directive('scrollBottomOn', ['$timeout', function ($timeout) {\r\n return function (scope, elm, attr) {\r\n scope.$watch(attr.scrollBottomOn, function (value) {\r\n if (value) {\r\n $timeout(function () {\r\n elm[0].scrollTop = elm[0].scrollHeight;\r\n });\r\n }\r\n });\r\n }\r\n }])\r\n\r\n ;","'use strict';\r\n\r\nangular\r\n .module('chat.message', [\r\n 'chat.browser',\r\n 'chat.room',\r\n 'chat.user',\r\n 'chat.emojis'\r\n ])\r\n\r\n .service('messageDatasource', [\r\n '$http', '$q', 'SessionService', '$rootScope', 'userService', '$filter',\r\n function ($http, $q, SessionService, $rootScope, userService, $filter) {\r\n var _list = [],\r\n _lastMessageTime = null,\r\n _lodingImage = 'https://cdn.echofin.co/images/loading.gif',\r\n _fUploadQueue = [];\r\n\r\n var _pushMessage = function (a_obj) {\r\n _list.push(a_obj);\r\n };\r\n\r\n var _test = function () {\r\n _list.splice(0, _list.length - 100);\r\n _lastMessageTime = moment.utc(_list[0].date).unix();\r\n };\r\n\r\n var _unshiftMessage = function (a_obj) {\r\n _list.unshift(a_obj);\r\n };\r\n\r\n var _getMessages = function () {\r\n return _list;\r\n };\r\n\r\n var _setMessage = function (a_obj, a_idx) {\r\n _list[a_idx] = a_obj;\r\n }\r\n\r\n var _deleteMessage = function (a_idx) {\r\n _list.splice(a_idx, 1);\r\n };\r\n\r\n var _enableAvatar = function (a_idx) {\r\n if (_list[a_idx] != null) {\r\n _list[a_idx].b_isContinuing = false;\r\n };\r\n }\r\n\r\n var _deleteMessageByDate = function (a_msgDate) {\r\n var indx = _findByDate(a_msgDate);\r\n if (indx > -1) {\r\n _list.splice(indx, 1);\r\n _enableAvatar(indx);\r\n\r\n return true;\r\n }\r\n return false;\r\n };\r\n\r\n var _checkIfContinues = function (a_objCurrent, a_objPrevious) {\r\n\r\n if (a_objPrevious == null)\r\n return false;\r\n\r\n if (a_objCurrent.senderKey == a_objPrevious.senderKey &&\r\n moment.utc(a_objCurrent.date).diff(moment.utc(a_objPrevious.date), 'seconds') <= 300)\r\n return true;\r\n\r\n return false;\r\n }\r\n\r\n var _youtube_parse = function (url) {\r\n var regExp = /^.*(youtu\\.be\\/|v\\/|u\\/\\w\\/|embed\\/|watch\\?v=|\\&v=)([^#\\&\\?]*).*/;\r\n var match = url.match(regExp);\r\n if (match && match[2].length == 11) {\r\n return match[2];\r\n } else {\r\n return null;\r\n }\r\n }\r\n\r\n var _addToMessageList = function (a_objItem, order, clearOld) {\r\n\r\n //a_objItem.message = _parseMessage(a_objItem.message.trim());\r\n if (a_objItem.s_extension != null) {\r\n a_objItem.s_extension = a_objItem.s_extension.toLowerCase();\r\n a_objItem.b_thumb = (a_objItem.s_extension == 'jpg' ||\r\n a_objItem.s_extension == 'jpeg' ||\r\n a_objItem.s_extension == 'png' ||\r\n a_objItem.s_extension == 'bmp' ||\r\n a_objItem.s_extension == 'gif' ||\r\n a_objItem.s_extension == 'ico');\r\n\r\n }\r\n a_objItem.s_refresh = '';\r\n \r\n try { //get user type\r\n a_objItem.userType = userService.getUserByKey(a_objItem.senderKey).type;\r\n } catch (e) { }\r\n if (SessionService.isWindowFocused)\r\n a_objItem.b_isUnread = false;\r\n else\r\n a_objItem.b_isUnread = true;\r\n\r\n a_objItem.youtubeid = _youtube_parse(a_objItem.message);\r\n if (a_objItem.youtubeid != null && a_objItem.youtubeid != '') {\r\n a_objItem.b_isUploaded = true;\r\n a_objItem.n_fileType = \"\";\r\n }\r\n\r\n if (!a_objItem.date) {\r\n a_objItem.dateParsed = moment().toDate();\r\n a_objItem.dateOffset = moment().tz(userService.getUserTimezone()).format('Z').replace(\":\", \"\");\r\n } else if (!isNaN(a_objItem.date)) {\r\n a_objItem.dateParsed = moment(a_objItem.date).toDate();\r\n a_objItem.dateOffset = moment(a_objItem.date).tz(userService.getUserTimezone()).format('Z').replace(\":\", \"\");\r\n } else if (a_objItem.date.indexOf(\"Z\", a_objItem.date.length - 1) !== -1) {\r\n a_objItem.dateParsed = moment.utc(a_objItem.date).toDate();\r\n a_objItem.dateOffset = moment.utc(a_objItem.date).tz(userService.getUserTimezone()).format('Z').replace(\":\", \"\");\r\n } else {\r\n a_objItem.dateParsed = moment.utc(a_objItem.date + \"Z\").toDate();\r\n a_objItem.dateOffset = moment.utc(a_objItem.date + \"Z\").tz(userService.getUserTimezone()).format('Z').replace(\":\", \"\");\r\n }\r\n\r\n if (a_objItem.message.indexOf(\": SIGNAL
\") != -1) {\r\n a_objItem.isSignal = true;\r\n }\r\n\r\n if (a_objItem.message.startsWith('/shout')) {\r\n a_objItem.isShout = true;\r\n }\r\n\r\n if (\r\n !a_objItem.message ||\r\n a_objItem.type == \"bot\" ||\r\n a_objItem.isSignal ||\r\n a_objItem.isShout ||\r\n a_objItem.n_fileType == 2\r\n ) {\r\n a_objItem.canEdit = false;\r\n a_objItem.canPin = false;\r\n }\r\n \r\n switch (order) {\r\n case 1:\r\n a_objItem.b_isContinuing = _checkIfContinues(a_objItem, _list[_list.length - 1]);\r\n _pushMessage(a_objItem)\r\n\r\n if (clearOld && _list.length > clearOld) {\r\n _list.splice(0, _list.length - clearOld);\r\n }\r\n \r\n break;\r\n default:\r\n //check if the previous message is from the same user\r\n //add message\r\n //$scope.messagelist.unshift(a_objItem);\r\n if (_list[0] != null)\r\n _list[0].b_isContinuing = _checkIfContinues(_list[0], a_objItem);\r\n _unshiftMessage(a_objItem)\r\n\r\n if (clearOld && _list.length > clearOld) {\r\n _list.splice(clearOld, _list.length - 1);\r\n }\r\n\r\n break;\r\n };\r\n \r\n _lastMessageTime = moment.utc(_list[0].date).unix();\r\n\r\n //console.log(\"last message\",_list[0].message , \"at\",_list[0].date, _lastMessageTime)\r\n\r\n $rootScope.$broadcast('ChangeMessageCount', _list);\r\n };\r\n\r\n var _refreshDayText = function () {\r\n var messagesLength = _list.length;\r\n\r\n var tz = userService.getUserTimezone();\r\n var midnight = moment().startOf('date').tz(tz).valueOf();\r\n\r\n //var today = new Date();\r\n //today.setUTCHours(0,0,0,0);\r\n //var lastMidnightTimestamp = +today;\r\n //var midnightOffset = userTz.utcOffset(lastMidnightTimestamp) * 1000 * 60;\r\n\r\n for (var i = 1; i < messagesLength; i++) {\r\n\r\n var messageTimestamp = _list[i].dateParsed.getTime();\r\n\r\n\r\n var messageDateOffset = (parseInt(_list[i].dateOffset.substring(1,3)) * 60 + parseInt(_list[i].dateOffset.substring(3))) * 1000;\r\n\r\n var dateDiff = midnight - ( messageTimestamp + messageDateOffset);\r\n var dateDiffDays = Math.floor(dateDiff / ( 1000 * 60 * 60 * 24));\r\n\r\n if (dateDiffDays === -1) {\r\n _list[i].dayText = _list[i].dayTextStore = \"TODAY\";\r\n } else if (dateDiffDays === 0) {\r\n _list[i].dayText = _list[i].dayTextStore = \"YESTERDAY\";\r\n } else {\r\n _list[i].dayText = _list[i].dayTextStore = $filter('date')(_list[i].dateParsed, \"MMMM d, yyyy\", _list[i].dateOffset);\r\n }\r\n\r\n if (_list[i - 1].dayTextStore === _list[i].dayTextStore) {\r\n _list[i].dayText = null;\r\n }\r\n\r\n //console.log(_list[i].message, midnight,dateDiff, dateDiffDays, messageDateOffset,_list[i].dateOffset)\r\n }\r\n }\r\n\r\n var _findByDate = function (a_msgDate) {\r\n for (var i = 0; i < _list.length; i++) {\r\n if (moment.utc(_list[i].date).valueOf() == moment.utc(a_msgDate).valueOf()) {\r\n return i;\r\n }\r\n }\r\n return -1;\r\n }\r\n\r\n var _findByFileToken = function (a_strFileToken) {\r\n for (var i = 0; i < _list.length; i++) {\r\n if (_list[i].s_fileToken == a_strFileToken) {\r\n return i;\r\n }\r\n }\r\n return -1;\r\n }\r\n\r\n var _editMessageCallback = function (a_msgDate, a_msgText, a_msdDateEd) {\r\n var indx = _findByDate(a_msgDate);\r\n if (indx > -1) {\r\n _list[indx].message = a_msgText;\r\n if (a_msdDateEd != null) {\r\n _list[indx].edited = (a_msdDateEd != null);\r\n _list[indx].dateEd = a_msdDateEd;\r\n }\r\n // $(\".msg_txt\")[indx].innerText = a_msgText\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n var _fileUploadDone = function (a_strFileToken) {\r\n var indx = _findByFileToken(a_strFileToken);\r\n if (indx > -1) {\r\n //_list[indx].s_refresh = '?' + moment().unix().toString();\r\n _list[indx].b_isUploaded = true;\r\n return true;\r\n };\r\n _fUploadQueue.push(a_strFileToken);\r\n return false;\r\n }\r\n\r\n var _dequeueFileUpload = function (a_strToken) {\r\n var l_objReturn = null;\r\n var l_intIndex = _fUploadQueue.indexOf(a_strToken)\r\n if (l_intIndex > -1) {\r\n l_objReturn = _fUploadQueue[l_intIndex];\r\n _fUploadQueue.splice(l_intIndex, 1);\r\n return l_objReturn;\r\n } else {\r\n return l_objReturn;\r\n }\r\n }\r\n\r\n var _getFileUploadQueue = function () {\r\n return _fUploadQueue;\r\n }\r\n\r\n var _updateUserAvatar = function () {\r\n\r\n };\r\n\r\n var _clear = function () {\r\n _list = [];\r\n _lastMessageTime = null;\r\n };\r\n\r\n var _markAllRead = function () {\r\n var len = _list.length\r\n for (var i = 0; i < len; i++) {\r\n _list[i].b_isUnread = false;\r\n }\r\n $rootScope.$broadcast('ChangeMessageCount', _list);\r\n }\r\n\r\n var _getUnread = function () {\r\n var _unread = [];\r\n for (var i = 0; i < _list.length; i++) {\r\n if (_list[i].b_isUnread) {\r\n _unread.push(_list[i]);\r\n }\r\n }\r\n return _unread;\r\n }\r\n\r\n var _getLastMessageTime = function () {\r\n return _lastMessageTime;\r\n }\r\n\r\n var _changeUserAvatar = function (a_strUsrKey, a_strAvatarUrl) {\r\n for (var i = 0; i < _list.length; i++) {\r\n if (_list[i].senderKey === a_strUsrKey) {\r\n _list[i].s_avatar = a_strAvatarUrl;\r\n }\r\n }\r\n }\r\n\r\n return {\r\n getUnread: _getUnread,\r\n getMessages: _getMessages,\r\n pushMessage: _pushMessage,\r\n unshiftMessage: _unshiftMessage,\r\n addToMessageList: _addToMessageList,\r\n findByDate: _findByDate,\r\n deleteMessage: _deleteMessage,\r\n deleteMessageByDate: _deleteMessageByDate,\r\n editMessageCallback: _editMessageCallback,\r\n findByFileToken: _findByFileToken,\r\n fileUploadDone: _fileUploadDone,\r\n clear: _clear,\r\n markAllRead: _markAllRead,\r\n getLastMessageTime: _getLastMessageTime,\r\n dequeueFileUpload: _dequeueFileUpload,\r\n getFileUploadQueue: _getFileUploadQueue,\r\n changeUserAvatar: _changeUserAvatar,\r\n test: _test,\r\n refreshDayText: _refreshDayText,\r\n }\r\n }\r\n ])\r\n\r\n .service('messageService', [\r\n '$http', '$q', 'notifyService', '$rootScope', 'messageDatasource', 'userService', 'chatRoomService', 'emojiService', '$compile',\r\n function ($http, $q, notifyService, $rootScope, messageDatasource, userService, chatRoomService, emojiService, $compile) {\r\n\r\n // var isAdmin = userService.getCurrentUser().type == 1;\r\n var l_strEmojiPattern = /[:;\\\\][\\S]+(?=[<\\s])|[<]./g;\r\n var l_strCashtagPattern = /[$][A-Za-z]+[A-Za-z0-9]+|[$][A-Za-z]+/g;\r\n\r\n var url = {\r\n sendMessage: 'api/message/send',\r\n editMessage: 'api/message/edit',\r\n deleteMessage: 'api/message/delete',\r\n get: 'api/message',\r\n pinMessage: 'api/message/pin'\r\n }\r\n\r\n var _htmlDecode = function (input) {\r\n var e = document.createElement('div');\r\n e.innerHTML = input;\r\n return e.childNodes[0].nodeValue;\r\n }\r\n\r\n var _sendMessage = function (data) {\r\n\r\n _sendMixdata(data);\r\n\r\n var deferred = $q.defer();\r\n $http.post(url.sendMessage, data)\r\n .success(function (a_data, status, headers, config) {\r\n if (!a_data.success) {\r\n notifyService.error(a_data.error);\r\n $rootScope.$broadcast('FailedMessage', data);\r\n }\r\n deferred.resolve(a_data);\r\n })\r\n .error(function (data, status, headers, config) {\r\n $rootScope.$broadcast('FailedMessage', data);\r\n notifyService.showError(\"Get Data \", 'error ' + status + ' get ' + url.sendMessage);\r\n deferred.reject();\r\n });\r\n\r\n return deferred.promise;\r\n }\r\n\r\n var _getRoomMessages = function (room, timestamp) {\r\n var deferred = $q.defer();\r\n $http.get(url.get + '/getbyroom?room=' + room + '×tamp=' + timestamp, null)\r\n .success(function (a_data, status, headers, config) {\r\n a_data.s_key = room\r\n var d = [];\r\n for (var i = 0; i < 1; i++) {\r\n d = d.concat(a_data.data)\r\n }\r\n a_data.data = d;\r\n $rootScope.$broadcast('ChangeRoomData', a_data);\r\n deferred.resolve(a_data);\r\n })\r\n .error(function (data, status, headers, config) {\r\n notifyService.showError(\"Get Data \", 'error ' + status + ' get ' + url.get + '/getbyroom');\r\n deferred.reject();\r\n });\r\n\r\n return deferred.promise;\r\n }\r\n\r\n var _editMessage = function (data) {\r\n var deferred = $q.defer();\r\n $http.post(url.editMessage, data)\r\n .success(function (a_data, status, headers, config) {\r\n deferred.resolve(a_data);\r\n })\r\n .error(function (data, status, headers, config) {\r\n notifyService.showError(\"Get Data \", 'error ' + status + ' get ' + url.editMessage);\r\n deferred.reject();\r\n });\r\n\r\n return deferred.promise;\r\n }\r\n\r\n var _pinMessage = function (data) {\r\n var deferred = $q.defer();\r\n $http.post(url.pinMessage, data)\r\n .success(function (a_data, status, headers, config) {\r\n deferred.resolve(a_data);\r\n })\r\n .error(function (data, status, headers, config) {\r\n notifyService.showError(\"Get Data \", 'error ' + status + ' get ' + url.pinMessage);\r\n deferred.reject();\r\n });\r\n\r\n return deferred.promise;\r\n }\r\n\r\n var _deleteMessage = function (data) {\r\n var deferred = $q.defer();\r\n $http.post(url.deleteMessage, data)\r\n .success(function (a_data, status, headers, config) {\r\n deferred.resolve(a_data);\r\n })\r\n .error(function (data, status, headers, config) {\r\n notifyService.showError(\"Get Data \", 'error ' + status + ' get ' + url.deleteMessage);\r\n deferred.reject();\r\n });\r\n\r\n return deferred.promise;\r\n }\r\n\r\n var _outgoingMessage = function (data) {\r\n _sendMessage(data);\r\n }\r\n\r\n var _sendMixdata = function (data) {\r\n if (window.mixpanel) {\r\n var _room = chatRoomService.getCurrentRoom()\r\n mixpanel.track(\"send-message\", {\r\n \"Message Length\": data.message.length,\r\n \"Message With File\": !!data.filename,\r\n \"Room Name\": _room.s_url,\r\n });\r\n }\r\n }\r\n\r\n var _isSignal = function (message) {\r\n return message.indexOf(\": SIGNAL
\") != -1\r\n }\r\n\r\n var _parseSignal = function (message) {\r\n var splitMessage = message.split(\"
\")\r\n var message = {\r\n header: _parseWordToText(splitMessage[0]),\r\n lines: [],\r\n }\r\n\r\n for (var i = 1; i < splitMessage.length; i++) {\r\n var splitLine = splitMessage[i].split(\": \")\r\n message.lines.push({\r\n label: _parseWordToText(splitLine[0]),\r\n data: _parseWordToText(splitLine[1]),\r\n });\r\n }\r\n return message;\r\n }\r\n\r\n var _getFormatedSignal = function (message) {\r\n var parsedSignal = _parseSignal(message);\r\n\r\n var table = \"\";\r\n var comment = \"\";\r\n for (var i = 0; i < parsedSignal.lines.length; i++) {\r\n if (parsedSignal.lines[i].data) {\r\n var _data = parsedSignal.lines[i].data;\r\n if (parsedSignal.lines[i].label.indexOf(\"TP\") === 0) {\r\n _data = \"\" + parsedSignal.lines[i].data + \"\";\r\n } else if (parsedSignal.lines[i].label.indexOf(\"SL\") === 0) {\r\n _data = \"\" + parsedSignal.lines[i].data + \"\";\r\n }\r\n\r\n table += \"\";\r\n }\r\n }\r\n\r\n var l_objSignalLine = parsedSignal.lines[parsedSignal.lines.length - 1];\r\n if (l_objSignalLine != null && !l_objSignalLine.data) {\r\n comment = \"\";\r\n }\r\n\r\n table += \"
\" + parsedSignal.lines[i].label + \":\" + _data + \"
\";\r\n\r\n var htmlTemplate = \"
\" + parsedSignal.header + \"
\" + table + comment + \"
\";\r\n\r\n //htmlTemplate += \"
\" + message + \"
\";\r\n //htmlTemplate += \"
\" + JSON.stringify(parsedSignal,2) + \"
\";\r\n\r\n return htmlTemplate;\r\n }\r\n\r\n var _parseWordToText = function (a_strWords) {\r\n if (a_strWords == null)\r\n return '';\r\n var l_strReturn = '';\r\n var l_lstWords = _emojify(a_strWords).split(' ');\r\n for (var i = 0; i < l_lstWords.length; i++) {\r\n var a_strWord = l_lstWords[i];\r\n var l_objEmoji = emojiService.getEmojiByCode(a_strWord)\r\n if ((a_strWord.length > 4 && a_strWord.startsWith('http')) || a_strWord.startsWith('//')) {\r\n var link = a_strWord.replace(/<(?:.|\\n)*?>/gm, '');\r\n l_strReturn += ' ' + link + ' ';\r\n } else if (a_strWord.length > 4 && a_strWord.startsWith('@')) {\r\n var value = a_strWord.substring(1);\r\n var isNum = !isNaN(parseFloat(value)) && isFinite(value);\r\n var mentionExists = userService.getUserByName(value) != null;\r\n if (!isNum && (mentionExists || (value == 'everyone'))) {\r\n l_strReturn += '' + a_strWord + ' '\r\n } else {\r\n l_strReturn += a_strWord + ' ';\r\n }\r\n } else\r\n l_strReturn += a_strWord + ' ';\r\n\r\n\r\n }\r\n return l_strReturn;\r\n }\r\n\r\n var _emojify = function (l_strText) {\r\n return l_strText.replace(l_strEmojiPattern, function (str, p1, offset, s) {\r\n var l_strEmogi = emojiService.getEmojiByCode(str);\r\n if (l_strEmogi != null) {\r\n return '';\r\n } else {\r\n return str;\r\n }\r\n });\r\n }\r\n\r\n var _parseWord = function (word, scope) {\r\n\r\n // EMOJI\r\n if (word.startsWith(':') || word == '<3' || word == '\\\\m/') {\r\n var l_objEmoji = emojiService.getEmojiByCode(_htmlDecode(word));\r\n if (l_objEmoji != null) {\r\n return '' + ' '\r\n } else {\r\n return word + ' '\r\n };\r\n }\r\n\r\n // CASHTAG\r\n if (word.match(l_strCashtagPattern) != null) {\r\n var parsed\r\n word.replace(l_strCashtagPattern, function (str, p1, offset, s) {\r\n parsed = $compile('' + str + '')(scope);\r\n });\r\n return parsed;\r\n }\r\n\r\n // MENTION\r\n if (word.length > 4 && word.startsWith('@')) {\r\n var value = word.substring(1);\r\n var isNum = !isNaN(parseFloat(value)) && isFinite(value);\r\n var mentionExists = userService.getUserByName(value) != null;\r\n if (!isNum && (mentionExists || (value == 'everyone'))) {\r\n return '' + word + '' + ' '\r\n } else {\r\n return word + ' '\r\n }\r\n }\r\n\r\n // LINK\r\n if ((word.length > 4 && word.startsWith('http')) || word.startsWith('//')) {\r\n var link = word.replace(/<(?:.|\\n)*?>/gm, '');\r\n return '' + link + '' + ' '\r\n }\r\n\r\n return word + ' '\r\n }\r\n\r\n var _parseMessage = function (msg, elem, scope) {\r\n\r\n if (msg.message == null) {\r\n elem.empty();\r\n return\r\n }\r\n\r\n var l_strMessage = msg.message\r\n .replace(' ', ' ')\r\n .replace('/shout', \"\")\r\n\r\n if (msg.type == \"bot\") {\r\n elem.html(msg.message);\r\n return;\r\n }\r\n\r\n if (_isSignal(msg.message)) {\r\n var _signal = _getFormatedSignal(msg.message)\r\n elem.html(_signal);\r\n return;\r\n }\r\n\r\n if (msg.youtubeid) {\r\n elem.append($compile('
')(scope));\r\n return\r\n }\r\n\r\n if (msg.n_fileType == 2) {\r\n elem.append(msg.s_fileDescr + ' ');\r\n return\r\n }\r\n\r\n var l_lstWords = l_strMessage.replace(\"
\", \"
\").split(' ');\r\n var l_strBold = null;\r\n var l_strItalics = null;\r\n var l_strUnderline = null;\r\n\r\n for (var i = 0; i < l_lstWords.length; i++) {\r\n var l_strWord = l_lstWords[i];\r\n if (l_strBold == null && l_strWord.indexOf('') > -1) {\r\n l_strBold = l_strWord + ' ';\r\n } else if (l_strBold != null) {\r\n l_strBold += l_strWord + ' ';\r\n } else if (l_strItalics == null && l_strWord.indexOf('') > -1) {\r\n l_strItalics = l_strWord + ' ';\r\n } else if (l_strItalics != null) {\r\n l_strItalics += l_strWord + ' ';\r\n } else if (l_strUnderline == null && l_strWord.indexOf('') > -1) {\r\n l_strUnderline = l_strWord + ' ';\r\n } else if (l_strUnderline != null) {\r\n l_strUnderline += l_strWord + ' ';\r\n }\r\n\r\n if (l_strBold == null && l_strItalics == null && l_strUnderline == null) {\r\n var parsedWord = _parseWord(l_strWord, scope);\r\n elem.append(parsedWord)\r\n }\r\n\r\n if (l_strBold != null && l_strWord.indexOf('') > -1) {\r\n elem.append(l_strBold);\r\n l_strBold = null;\r\n }\r\n if (l_strItalics != null && l_strWord.indexOf('') > -1) {\r\n elem.append(l_strItalics);\r\n l_strItalics = null;\r\n }\r\n if (l_strUnderline != null && l_strWord.indexOf('') > -1) {\r\n elem.append(l_strUnderline);\r\n l_strUnderline = null;\r\n }\r\n }\r\n }\r\n\r\n var _reCountMessages = function () {\r\n var l_intUnread = messageDatasource.getUnread().length;\r\n if (l_intUnread > 0) {\r\n return l_intUnread.toString();\r\n } else {\r\n var l_objCurrentRoom = chatRoomService.getCurrentRoom();\r\n if (l_objCurrentRoom == null) {\r\n return;\r\n } else {\r\n return chatRoomService.getCurrentRoom().s_url;\r\n }\r\n }\r\n }\r\n\r\n return {\r\n sendMessage: _sendMessage,\r\n getRoomMessages: _getRoomMessages,\r\n editMessage: _editMessage,\r\n deleteMessage: _deleteMessage,\r\n outgoingMessage: _outgoingMessage,\r\n pinMessage: _pinMessage,\r\n isSignal: _isSignal,\r\n parseSignal: _parseSignal,\r\n parseWordToText: _parseWordToText,\r\n emojify: _emojify,\r\n getFormatedSignal: _getFormatedSignal,\r\n parseWord: _parseWord,\r\n parseMessage: _parseMessage,\r\n reCountMessages: _reCountMessages,\r\n }\r\n }\r\n ])\r\n\r\n .filter('unsafe', [\r\n '$sce',\r\n function ($sce) {\r\n return $sce.trustAsHtml;\r\n }\r\n ])\r\n\r\n .filter('vardate', [\r\n '$rootScope', 'userService',\r\n function ($rootScope, userService) { //$filter\r\n //var angularDateFilter = $filter('date');\r\n return function (a_strDate) { // theDate input will be UTC\r\n\r\n var l_strFormat = 'HH:mm A',\r\n l_strDateFormat = userService.getUserDateFormat(),\r\n l_strTimezone = userService.getUserTimezone();\r\n if (l_strTimezone != null) {\r\n var l_dtNow = moment(moment.utc().tz(l_strTimezone).format('YYYY-MM-DD') + ' 00:00:00')\r\n var l_dtMessage = moment(moment.utc(a_strDate).tz(l_strTimezone).format('YYYY-MM-DD') + ' 00:00:00')\r\n\r\n if (l_dtNow.diff(l_dtMessage, 'years') > 0) {\r\n l_strFormat = l_strDateFormat + '/YY ' + l_strFormat;\r\n } else if (l_dtNow.diff(l_dtMessage, 'days') > 0) {\r\n l_strFormat = l_strDateFormat + ' ' + l_strFormat;\r\n }\r\n\r\n return moment.utc(a_strDate).tz(l_strTimezone).format(l_strFormat);\r\n } else {\r\n return a_strDate;\r\n }\r\n }\r\n }\r\n ])\r\n\r\n .filter('vardate2', [\r\n '$filter', 'userService',\r\n function ($filter, userService) {\r\n var filter = function (messageDate, offset) {\r\n if (!messageDate) {\r\n return ''\r\n }\r\n var usetDateFormat = userService.getUserDateFormat().replace(\"DD\", \"dd\");\r\n var dateDiff = Math.floor((new Date() - messageDate) / (1000 * 60 * 60 * 24));\r\n var format = (dateDiff > 0) ? usetDateFormat + \" HH:mm a\" : 'HH:mm a';\r\n var dateStr = $filter(\"date\")(messageDate, format, offset);\r\n return dateStr;\r\n }\r\n return filter\r\n }\r\n ])\r\n\r\n .filter('formatdate', [\r\n '$rootScope', 'userService',\r\n function ($rootScope, userService) { //$filter\r\n //var angularDateFilter = $filter('date');\r\n return function (a_strDate) { // theDate input will be UTC\r\n\r\n var l_strDateFormat = userService.getUserDateFormat(),\r\n l_strTimezone = userService.getUserTimezone();\r\n if (l_strTimezone != null) {\r\n return moment.utc(a_strDate).tz(l_strTimezone).format(l_strDateFormat + '/YY ');\r\n } else {\r\n return a_strDate;\r\n }\r\n }\r\n }\r\n ])\r\n\r\n .directive('errSrc', [\r\n function () {\r\n\r\n return {\r\n link: function (scope, element, attrs) {\r\n if (!attrs.ngSrc) {\r\n attrs.$set('src', attrs.errSrc)\r\n }\r\n\r\n element.bind('error',\r\n function () {\r\n if (attrs.errSrc === 'REMOVE') {\r\n element.remove()\r\n return\r\n }\r\n if (attrs.src !== attrs.errSrc) {\r\n attrs.$set('src', attrs.errSrc)\r\n }\r\n })\r\n }\r\n }\r\n }\r\n ])\r\n\r\n //DEPRECATED\r\n .filter('messagefilter', [\r\n 'userService',\r\n function (userService) {\r\n return function (a_lstMessages) {\r\n var l_dtPreviousDate = null,\r\n l_dtCurrentDate = null,\r\n l_strText = null,\r\n l_strUserTimezone = userService.getUserTimezone();\r\n\r\n var l_dtNow = moment.utc().tz(l_strUserTimezone),\r\n l_dtNowEnd = moment.tz(moment.tz(l_strUserTimezone).format(\"YYYY-MM-DD 23:59:59.999\"), l_strUserTimezone);\r\n\r\n var printDate = function (a_date) {\r\n if (a_date != null)\r\n return a_date.format(\"YYYY-MM-DD HH:mm:ss\")\r\n return null;\r\n }\r\n\r\n for (var i = 0; i < a_lstMessages.length; i++) {\r\n if (i > 0) {\r\n l_dtPreviousDate = moment.utc(a_lstMessages[i - 1].date).tz(l_strUserTimezone);\r\n l_dtCurrentDate = moment.utc(a_lstMessages[i].date).tz(l_strUserTimezone);\r\n var l_intCurDiff = l_dtNowEnd.diff(l_dtCurrentDate, 'days'),\r\n l_intPrevDiff = l_dtNowEnd.diff(l_dtPreviousDate, 'days');\r\n\r\n if (l_intCurDiff == 0 && l_intPrevDiff == 1) {\r\n a_lstMessages[i].dayText = \"TODAY\";\r\n } else if (l_intCurDiff == 1 && l_intPrevDiff == 2) {\r\n a_lstMessages[i].dayText = \"YESTERDAY\";\r\n } else if (l_intCurDiff != l_intPrevDiff) {\r\n a_lstMessages[i].dayText = moment.utc(l_dtCurrentDate).tz(l_strUserTimezone).format('MMMM D, YYYY');\r\n }\r\n }\r\n }\r\n return a_lstMessages;\r\n }\r\n }\r\n ])\r\n\r\n .filter('messageParseJesus', [\r\n 'emojiService', 'messageService',\r\n function (emojiService, messageService) {\r\n return function (a_strMessage) {\r\n var l_strReturn = '';\r\n if (a_strMessage == null)\r\n return l_strReturn;\r\n a_strMessage = a_strMessage.replace(' ', ' ');\r\n var l_lstWords = a_strMessage.split(' ');\r\n for (var i = 0; i < l_lstWords.length; i++) {\r\n var l_objEmoji = emojiService.getEmojiByCode(l_lstWords[i])\r\n if (l_objEmoji != null)\r\n l_strReturn += ' ';\r\n else if ((l_lstWords[i].length > 4 && l_lstWords[i].startsWith('http')) || l_lstWords[i].startsWith('//')) {\r\n var link = l_lstWords[i].replace(/<(?:.|\\n)*?>/gm, '');\r\n l_strReturn += ' ' + link + ' ';\r\n } else if (l_lstWords[i].length > 4 && l_lstWords[i].startsWith('@')) {\r\n var value = l_lstWords[i].substring(1);\r\n var isNum = !isNaN(parseFloat(value)) && isFinite(value);\r\n if (!isNum) {\r\n l_strReturn += '' + l_lstWords[i] + ' '\r\n } else {\r\n l_strReturn += l_lstWords[i] + ' ';\r\n }\r\n } else\r\n l_strReturn += l_lstWords[i] + ' ';\r\n }\r\n\r\n if (messageService.isSignal(a_strMessage)) {\r\n l_strReturn = messageService.getFormatedSignal(l_strReturn);\r\n }\r\n\r\n return l_strReturn.trim();\r\n }\r\n }\r\n ])\r\n\r\n .directive('popupLink', [\r\n function () {\r\n return {\r\n scope: {\r\n filetype: '@',\r\n extension: '@',\r\n url: '@',\r\n message: '@',\r\n youtubeid: '@',\r\n },\r\n link: function (scope, elem, attrs) {\r\n var l_intFiletype = parseInt(scope.filetype);\r\n //var l_objMessage = JSON.parse(scope.messageitem);\r\n if (l_intFiletype == 1) {\r\n if (scope.extension == 'jpg' ||\r\n scope.extension == 'jpeg' ||\r\n scope.extension == 'png' ||\r\n scope.extension == 'bmp' ||\r\n scope.extension == 'gif' ||\r\n scope.extension == 'ico') {\r\n\r\n $(elem).magnificPopup({\r\n type: 'image',\r\n items: [{\r\n src: scope.url,\r\n download_href: \"https://\" + scope.url,\r\n }],\r\n image: {\r\n markup: '
' +\r\n '
' +\r\n '
' +\r\n '
' +\r\n '
' +\r\n '
' +\r\n ' DOWNLOAD
' +\r\n '
' +\r\n '
' +\r\n '
' +\r\n '' +\r\n '' +\r\n '',\r\n },\r\n\r\n });\r\n\r\n // $(document).on(\"click\", \".mfp-img\", function () {\r\n // $(\".mfp-close\").trigger(\"click\")\r\n // })\r\n } else {\r\n $(elem).attr('target', '_new');\r\n }\r\n $(elem).attr('href', scope.url);\r\n } else if (scope.youtubeid) {\r\n $(elem).attr('href', 'https://www.youtube.com/watch?v=' + scope.youtubeid).attr('target', '_blank');\r\n } else {\r\n $(elem).attr('href', scope.message.replace(' ', '')).attr('target', '_blank');\r\n }\r\n //if (l_objMessage.s_fileToken == null)\r\n // $(elem).attr('display', 'none');\r\n\r\n }\r\n }\r\n }\r\n ])\r\n\r\n .directive('filePopupLink', [\r\n function () {\r\n return {\r\n scope: {\r\n extension: '@',\r\n url: '@'\r\n\r\n },\r\n link: function (scope, elem, attrs) {\r\n if (scope.extension == 'jpg' ||\r\n scope.extension == 'jpeg' ||\r\n scope.extension == 'png' ||\r\n scope.extension == 'bmp' ||\r\n scope.extension == 'gif' ||\r\n scope.extension == 'ico') {\r\n\r\n $(elem).magnificPopup({\r\n type: 'image',\r\n items: [{\r\n src: scope.url,\r\n download_href: \"https://\" + scope.url,\r\n }],\r\n image: {\r\n markup: '
' +\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\r\n });\r\n // $(document).on(\"click\", \".mfp-img\", function () {\r\n // $(\".mfp-close\").trigger(\"click\")\r\n // })\r\n } else {\r\n $(elem).attr('target', '_new');\r\n }\r\n $(elem).attr('href', scope.url);\r\n\r\n }\r\n }\r\n }\r\n ])\r\n\r\n .directive('attachTitle', [\r\n function () {\r\n return {\r\n scope: {\r\n filetype: '@',\r\n filename: '@',\r\n filelink: '@'\r\n },\r\n link: function (scope, elem, attrs) {\r\n if (scope.filetype == 1) {\r\n $(elem).html('File Uploaded: ' + scope.filename);\r\n } else if (scope.filetype == 2) {\r\n $(elem).html('Link Shared: ' + scope.filelink);\r\n }\r\n }\r\n }\r\n }\r\n ])\r\n\r\n .directive('messageActions', [\r\n 'userService', 'messageService', '$sce', 'notifyService', 'chatRoomService',\r\n function (userService, messageService, $sce, notifyService, chatRoomService) {\r\n return {\r\n replace: false,\r\n templateUrl: 'message-actions.html',\r\n scope: {\r\n message: '='\r\n },\r\n controller: function ($scope, $element, $rootScope) { },\r\n link: function (scope, elem, attrs) {\r\n //return;\r\n var l_objCurrentUser = userService.getCurrentUser(),\r\n l_strOldText = null,\r\n sender = userService.getUserByKey(scope.message.senderKey);\r\n scope.msgstyle = null;\r\n scope.isAdmin = sender.type == 1;\r\n scope.isInstructor = sender.type == 2;\r\n scope.isModerator = sender.type == 3;\r\n //scope.isAdmin = true;\r\n var funEscape = function (data) {\r\n data = data.replace('', '');\r\n return data;\r\n }\r\n if (scope.message.n_fileType == 2)\r\n scope.message.message = scope.message.s_fileDescr;\r\n if (sender.b_bold)\r\n scope.msgstyle = \"font-weight: bold\";\r\n\r\n var _recalc = function () {\r\n var l_objUserSettings = userService.getSettings();\r\n\r\n $scope.alertsVisible = l_objUserSettings.wiseguy && l_objUserSettings.activeSubs;\r\n\r\n if (!$scope.alertsVisible) {\r\n var speed = 100,\r\n chatDivPadding = 15;\r\n $('#dvRight').css('width', '0px');\r\n $('.right-pad').css('padding-right', '0');\r\n $('.right-marg').css('margin-right', '0');\r\n $('.chatDiv').css('right', chatDivPadding.toString() + 'px');\r\n $('.alertDiv').css('right', '0');\r\n $(\"#dvAlerts\").css('display', 'none');\r\n $(\".btnAlert\").css('display', 'none');\r\n } else {\r\n $(\".btnAlert\").css('display', 'block');\r\n }\r\n }\r\n\r\n scope.$on('initial', function (event, data) {\r\n _recalc();\r\n });\r\n\r\n scope.$on('recalc', function (event, data) {\r\n _recalc();\r\n });\r\n\r\n $(elem).find(\".msg_txt\").keypress(function (event) {\r\n if (event.keyCode === 10 || event.keyCode === 13) {\r\n event.preventDefault();\r\n scope.saveMessage();\r\n }\r\n });\r\n\r\n scope.inEdit = false;\r\n scope.canEdit = function () {\r\n if (l_objCurrentUser == null) {\r\n return false;\r\n }\r\n if (scope.message && scope.message.message && messageService.isSignal(scope.message.message)) { // can't edit if signal\r\n return false;\r\n }\r\n if (l_objCurrentUser.type == 1 || l_objCurrentUser.type == 2 || l_objCurrentUser.type == 3) {\r\n return true;\r\n }\r\n if (scope.message.senderKey == l_objCurrentUser.s_key && Math.floor((new Date() - scope.message.dateParsed) / 1000) <= 60) {\r\n return true;\r\n }\r\n \r\n return scope.message.canEdit;\r\n }\r\n scope.canDelete = function () {\r\n if (l_objCurrentUser == null)\r\n return false;\r\n if (scope.message.type == \"bot\") {\r\n return false;\r\n }\r\n if (l_objCurrentUser.type == 1 || l_objCurrentUser.type == 2 || l_objCurrentUser.type == 3) {\r\n return true;\r\n }\r\n if (scope.message.senderKey == l_objCurrentUser.s_key && Math.floor((new Date() - scope.message.dateParsed) / 1000) <= 60) {\r\n return true;\r\n }\r\n return false;\r\n }\r\n scope.canPin = function () {\r\n if (l_objCurrentUser == null) {\r\n return false;\r\n }\r\n if (l_objCurrentUser.type == 1 || l_objCurrentUser.type == 2 || l_objCurrentUser.type == 3) {\r\n return true;\r\n }\r\n if (scope.message.senderKey == l_objCurrentUser.s_key && Math.floor((new Date() - scope.message.dateParsed) / 1000) <= 60) {\r\n return true;\r\n }\r\n return scope.message.canPin;\r\n }\r\n scope.deleteMessage = function () {\r\n notifyService.confirm('are you sure?', function () {\r\n var l_objRoom = chatRoomService.getCurrentRoom();\r\n messageService.deleteMessage({\r\n msgDate: moment.utc(scope.message.date).valueOf(),\r\n roomType: l_objRoom.roomType,\r\n roomkey: l_objRoom.s_key\r\n });\r\n }, function () { });\r\n }\r\n scope.editMessage = function () {\r\n l_strOldText = $.trim(funEscape($(elem).find(\".msg_txt\").html()));\r\n scope.inEdit = true;\r\n }\r\n scope.pinMessage = function () {\r\n var l_strMessage = $.trim(funEscape($(elem).find(\".msg_txt\").html()));\r\n var l_objRoom = chatRoomService.getCurrentRoom();\r\n notifyService.confirm('This will pin the message on top. Are you sure?', function () {\r\n // msgDate: moment.utc(scope.message.date).valueOf(),\r\n // message: l_strMessage,\r\n // roomType: l_objRoom.roomType,\r\n // roomkey: l_objRoom.s_key\r\n //});\r\n messageService.pinMessage({\r\n msgDate: moment.utc(scope.message.date).valueOf(),\r\n message: l_strMessage,\r\n roomType: l_objRoom.roomType,\r\n roomkey: l_objRoom.s_key\r\n }).then(function () {\r\n\r\n });\r\n });\r\n }\r\n scope.cancelMessage = function () {\r\n $(elem).find(\".msg_txt\").html(l_strOldText);\r\n scope.inEdit = false;\r\n }\r\n scope.saveMessage = function () {\r\n var l_strMessage = $.trim(funEscape($(elem).find(\".msg_txt\").html()));\r\n var l_objRoom = chatRoomService.getCurrentRoom();\r\n messageService.editMessage({\r\n msgDate: moment.utc(scope.message.date).valueOf(),\r\n message: l_strMessage,\r\n roomType: l_objRoom.roomType,\r\n roomkey: l_objRoom.s_key\r\n }).then(function () {\r\n scope.inEdit = false;\r\n scope.message.message = l_strMessage;\r\n $(elem).find(\".msg_txt\").val(l_strMessage);\r\n });\r\n }\r\n scope.cashtagload = function () { }\r\n }\r\n }\r\n }\r\n ])\r\n\r\n .service('daysDatasource', [\r\n function () {\r\n var _days = [];\r\n\r\n var _dayExist = function (a_strItem) {\r\n return _days.indexOf(a_strItem) >= 0;\r\n }\r\n\r\n var _dayAdd = function (a_objItem) {\r\n return _days.push(a_objItem);\r\n }\r\n\r\n var _clear = function () {\r\n _days = [];\r\n }\r\n\r\n return {\r\n clear: _clear,\r\n dayExist: _dayExist,\r\n dayAdd: _dayAdd\r\n }\r\n }\r\n ])\r\n\r\n .directive('cashtag', [\r\n '$rootScope',\r\n function ($rootScope) {\r\n return {\r\n scope: {},\r\n link: function (scope, elem, attrs) {\r\n //$('.cashtag').on('click', function () {\r\n // $rootScope.$broadcast('LoadTradingWidgetModal', elem[0].innerText);\r\n //});\r\n elem.on('click', function () {\r\n //$rootScope.$broadcast('LoadTradingWidgetModal', elem[0].innerText);\r\n $.fn.cashTags({\r\n quote: elem[0].innerText.replace('$', '')\r\n });\r\n });\r\n }\r\n }\r\n }\r\n ])\r\n\r\n .directive('youtubedescr', [\r\n '$rootScope', '$q', '$http',\r\n function ($rootScope, $q, $http) {\r\n var _getYoutubeData = function (a_strVideoId) {\r\n var deferred = $q.defer();\r\n $http.get('https://www.googleapis.com/youtube/v3/videos?part=snippet&fields=items/snippet/title,items/snippet/channelTitle&key=AIzaSyD2LjNPBQ8IUC7gkEhPhW8dQE4Dxj8IJz8&id=' + a_strVideoId)\r\n .success(function (a_data, status, headers, config) {\r\n deferred.resolve(a_data);\r\n })\r\n .error(function (data, status, headers, config) {\r\n notifyService.showError(\"Get Data \", 'error ' + status);\r\n deferred.reject();\r\n });\r\n\r\n return deferred.promise;\r\n }\r\n\r\n return {\r\n scope: {\r\n yid: '@'\r\n },\r\n link: function (scope, elem, attrs) {\r\n _getYoutubeData(scope.yid).then(function (a_objResponse) {\r\n if (a_objResponse.items && a_objResponse.items.length > 0) {\r\n elem.append(a_objResponse.items[0].snippet.title);\r\n }\r\n });\r\n }\r\n }\r\n }\r\n ])\r\n\r\n .directive('messageParser', [\r\n 'messageService',\r\n function (messageService) {\r\n return {\r\n scope: {\r\n message2: '=',\r\n },\r\n link: function (scope, elem, attrs) {\r\n scope.$watch(\"message2\", function (newValue, oldValue) {\r\n elem.empty();\r\n messageService.parseMessage(newValue, elem, scope)\r\n }, true);\r\n },\r\n controller: function ($scope, $element) { }\r\n }\r\n }\r\n ])\r\n\r\n ;","'use strict';\r\n\r\nangular.module('chat.push', ['chat.auth'])\r\n .service('pushService', ['$rootScope', 'tokenService', '$window', 'streamDataService', '$timeout',\r\n function ($rootScope, tokenService, $window, streamDataService, $timeout) {\r\n\r\n var l_objPusher = null;\r\n var l_strLastState = 'init';\r\n var roomSubscription = null;\r\n var teamRoomSubscription = null;\r\n\r\n var pusherProperties = {\r\n authTransport: 'buffered',\r\n authDelay: 100,\r\n authEndpoint: \"/api/push/auth-batch\",\r\n encrypted: true,\r\n cluster: 'mt1',\r\n auth: {\r\n headers: {\r\n Accept: 'application/json',\r\n Authorization: 'Bearer ' + tokenService.model.access_token\r\n }\r\n },\r\n authorizer: pusherAuthorizer\r\n }\r\n\r\n var service = {\r\n _authorizers: {},\r\n initPusher: initPusher,\r\n subscribeChatRoom: subscribeChatRoom,\r\n subscribeTeamRoom: subscribeTeamRoom,\r\n unsubscribeChatRoom: unsubscribeChatRoom,\r\n getPusherObject: getPusherObject,\r\n sendEventToRoom: sendEventToRoom,\r\n }\r\n\r\n return service\r\n\r\n function getPusherObject() {\r\n return l_objPusher;\r\n };\r\n\r\n function sendEventToRoom(a_strEventName, a_objData) {\r\n teamRoomSubscription.trigger(a_strEventName, a_objData);\r\n };\r\n\r\n function pusherAuthorizer(channel, options) {\r\n return {\r\n authorize: function (socketId, callback) {\r\n var authEndpoint = pusherProperties.authEndpoint\r\n var key = socketId + ':' + authEndpoint\r\n if (!service._authorizers[key]) {\r\n service._authorizers[key] = new BufferedAuthorizer({\r\n socketId: socketId,\r\n authEndpoint: authEndpoint,\r\n authDelay: pusherProperties.authDelay,\r\n authOptions: pusherProperties.auth\r\n })\r\n }\r\n service._authorizers[key].add(channel.name, callback)\r\n }\r\n }\r\n }\r\n\r\n function initPusher(PusherClientKey) {\r\n l_objPusher = new Pusher(PusherClientKey, pusherProperties);\r\n l_objPusher.connection.bind('state_change', function (states) {\r\n if (l_strLastState == 'unavailable' && states.current == 'connected')\r\n $window.location.reload();\r\n l_strLastState = states.current;\r\n });\r\n l_objPusher.connection.bind('error', function (err) {});\r\n $rootScope.$broadcast('PusherInitialized', l_objPusher);\r\n }\r\n\r\n function subscribeChatRoom(a_strRoomName) {\r\n roomSubscription = l_objPusher.subscribe(a_strRoomName);\r\n roomSubscription.bind(\"new-message\", function (obj) {\r\n $rootScope.$broadcast('IncomingMessage', obj);\r\n });\r\n roomSubscription.bind(\"upload-done\", function (obj) {\r\n $rootScope.$broadcast('UploadDone', obj);\r\n });\r\n roomSubscription.bind(\"edit-message\", function (obj) {\r\n $rootScope.$broadcast('EditMessage', obj);\r\n });\r\n roomSubscription.bind(\"delete-message\", function (obj) {\r\n $rootScope.$broadcast('DeleteMessage', obj);\r\n });\r\n roomSubscription.bind(\"pin-action\", function (obj) {\r\n $rootScope.$broadcast('PinAction', obj);\r\n });\r\n roomSubscription.bind(\"room-readed\", function (obj) {\r\n $rootScope.$broadcast('RoomReaded', obj);\r\n });\r\n roomSubscription.bind(\"admin-pin-message\", function (obj) {\r\n $rootScope.$broadcast('AdminPinMessage', obj);\r\n });\r\n roomSubscription.bind(\"admin-unpin-message\", function (obj) {\r\n $rootScope.$broadcast('AdminUnpinMessage', obj);\r\n });\r\n roomSubscription.bind(\"admin-unpin-message\", function (obj) {\r\n $rootScope.$broadcast('AdminUnpinMessage', obj);\r\n });\r\n roomSubscription.bind(\"istyping\", function (obj) {\r\n $rootScope.$broadcast('istyping', obj);\r\n });\r\n roomSubscription.bind(\"system-command\", function (obj) {\r\n switch (obj.command) {\r\n case 'blk':\r\n $rootScope.$broadcast('blk', obj.user);\r\n break;\r\n case 'unblk':\r\n $rootScope.$broadcast('unblk', obj.user);\r\n break;\r\n case 'restartu':\r\n //$rootScope.$broadcast('restartu', obj.user);\r\n $window.location.reload();\r\n break;\r\n default:\r\n break;\r\n }\r\n });\r\n };\r\n\r\n function unsubscribeChatRoom(a_strRoomName) {\r\n l_objPusher.unsubscribe(a_strRoomName);\r\n };\r\n\r\n function subscribeTeamRoom(a_strRoomName) {\r\n teamRoomSubscription = l_objPusher.subscribe('private-t-' + a_strRoomName);\r\n teamRoomSubscription.bind(\"change-user-status\", function (obj) {\r\n $rootScope.$broadcast('UserStatusChange', obj);\r\n });\r\n teamRoomSubscription.bind(\"start-stream\", function (obj) {\r\n streamDataService.m_blnAlertBoxVisible = true;\r\n streamDataService.l_strVideoId = obj.videoId;\r\n streamDataService.l_blnLive = true;\r\n\r\n $rootScope.$broadcast('StartStream', obj);\r\n\r\n });\r\n teamRoomSubscription.bind(\"stop-stream\", function (obj) {\r\n streamDataService.l_strVideoId = \"-STOPPED-\";\r\n streamDataService.l_blnLive = false;\r\n\r\n $rootScope.$broadcast('StopStream', obj);\r\n });\r\n teamRoomSubscription.bind(\"new-user\", function (obj) {\r\n $rootScope.$broadcast('NewUser', obj);\r\n });\r\n teamRoomSubscription.bind(\"change-user-avatar\", function (obj) {\r\n $rootScope.$broadcast('UserAvatarChange', obj);\r\n });\r\n //teamRoomSubscription.bind(\"istyping\", function (obj) {\r\n // $rootScope.$broadcast('istyping', obj);\r\n //});\r\n teamRoomSubscription.bind(\"system-command\", function (obj) {\r\n switch (obj.command) {\r\n case 'restart-soft':\r\n $rootScope.$broadcast('alert-refresh', {});\r\n break;\r\n case 'restart':\r\n $rootScope.$broadcast('system-restart');\r\n break;\r\n case 'ku':\r\n $rootScope.$broadcast('ku', obj.user);\r\n break;\r\n case 'uku':\r\n $rootScope.$broadcast('uku', obj.user);\r\n break;\r\n default:\r\n break;\r\n }\r\n });\r\n }\r\n }\r\n ]);\r\n\r\n/**\r\n * Pusher plugin for batching auth requests in one HTTP call\r\n *\r\n * Copyright 2016, Dirk Bonhomme \r\n * Released under the MIT licence.\r\n */\r\n\r\nvar BufferedAuthorizer = (function () {\r\n /**\r\n * Buffered authorizer constructor\r\n */\r\n function BufferedAuthorizer(options) {\r\n this.options = options;\r\n this.authOptions = options.authOptions || {};\r\n this.requests = {};\r\n this.setRequestTimeout();\r\n }\r\n /**\r\n * Add auth request to queue and execute after delay\r\n */\r\n BufferedAuthorizer.prototype.add = function (channel, callback) {\r\n this.requests[channel] = callback;\r\n if (!this.requestTimeout) {\r\n this.setRequestTimeout();\r\n }\r\n };\r\n /**\r\n * Set new delay and authenticate all queued requests after timeout\r\n */\r\n BufferedAuthorizer.prototype.setRequestTimeout = function () {\r\n var _this = this;\r\n clearTimeout(this.requestTimeout);\r\n this.requestTimeout = setTimeout(function () {\r\n if (Object.keys(_this.requests).length) {\r\n _this.executeRequests();\r\n _this.setRequestTimeout();\r\n } else {\r\n _this.requestTimeout = null;\r\n }\r\n }, this.options.authDelay || 0);\r\n };\r\n /**\r\n * Execute all queued auth requests\r\n */\r\n BufferedAuthorizer.prototype.executeRequests = function () {\r\n var _this = this;\r\n var requests = this.requests;\r\n this.requests = {};\r\n this.xhrRequest(requests, this.options.socketId, this.authOptions, this.options.authEndpoint, function (error, response) {\r\n if (error) {\r\n _this.objectApply(requests, function (callback) {\r\n callback(true, response);\r\n });\r\n } else {\r\n _this.objectApply(requests, function (callback, channel) {\r\n if (response[channel]) {\r\n if (!response[channel].status || response[channel].status === 200) {\r\n callback(null, response[channel].data); // successful authentication\r\n } else {\r\n callback(true, response[channel].status); // authentication failed\r\n }\r\n } else {\r\n callback(true, 404); // authentication data for this channel not returned\r\n }\r\n });\r\n }\r\n });\r\n };\r\n /**\r\n * Utility method: loop over object's key and call method f with each member\r\n */\r\n BufferedAuthorizer.prototype.objectApply = function (object, f) {\r\n for (var key in object) {\r\n if (Object.prototype.hasOwnProperty.call(object, key)) {\r\n f(object[key], key, object);\r\n }\r\n }\r\n };\r\n /**\r\n * Compose POST query to auth endpoint\r\n */\r\n BufferedAuthorizer.prototype.composeQuery = function (requests, socketId, authOptions) {\r\n var i = 0;\r\n var query = '&socket_id=' + encodeURIComponent(socketId);\r\n for (var channel in requests) {\r\n query += '&channel_name[' + i + ']=' + encodeURIComponent(channel);\r\n i++;\r\n }\r\n for (var param in authOptions.params) {\r\n query += '&' + encodeURIComponent(param) + '=' + encodeURIComponent(authOptions.params[param]);\r\n }\r\n return query;\r\n };\r\n /**\r\n * Execute XHR request to auth endpoint\r\n */\r\n BufferedAuthorizer.prototype.xhrRequest = function (requests, socketId, authOptions, authEndpoint, callback) {\r\n var xhr = Pusher.Runtime.createXHR();\r\n xhr.open('POST', authEndpoint, true);\r\n xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');\r\n for (var headerName in authOptions.headers) {\r\n xhr.setRequestHeader(headerName, authOptions.headers[headerName]);\r\n }\r\n xhr.onreadystatechange = function () {\r\n if (xhr.readyState === 4) {\r\n if (xhr.status === 200) {\r\n var data, parsed = false;\r\n try {\r\n data = JSON.parse(xhr.responseText);\r\n parsed = true;\r\n } catch (e) {\r\n callback(true, 'JSON returned from webapp was invalid, yet status code was 200. Data was: ' + xhr.responseText);\r\n }\r\n if (parsed) {\r\n callback(false, data);\r\n }\r\n } else {\r\n callback(true, xhr.status);\r\n }\r\n }\r\n };\r\n xhr.send(this.composeQuery(requests, socketId, authOptions));\r\n };\r\n return BufferedAuthorizer;\r\n}());","'use strict';\r\n\r\nangular.module('chat.user', [\r\n 'chat.auth',\r\n 'chat.push',\r\n 'chat.notify',\r\n 'chat.luckyorange'\r\n])\r\n\r\n .filter('usersOffline', [function () { // register new filter\r\n return function (a_lstUsers, a_blnEnabled, a_blnAll) { // filter\r\n if (!a_blnEnabled || a_blnAll || a_lstUsers == null)\r\n return a_lstUsers;\r\n var l_lstFiltered = [];\r\n for (var i = 0; i < a_lstUsers.length; i++) {\r\n if (a_lstUsers[i].status != 2 && !a_lstUsers[i].isDeleted)\r\n l_lstFiltered.push(a_lstUsers[i]);\r\n }\r\n // console.log(l_lstFiltered, a_lstUsers);\r\n return l_lstFiltered;\r\n };\r\n }])\r\n\r\n .filter('usersfilter', function () { // register new filter\r\n return function (a_lstUsers, a_strType, a_strIsBanned, a_strNameFilter) { // filter\r\n var l_intType = parseInt(a_strType),\r\n l_bIsBanned = (a_strIsBanned == \"true\");\r\n // console.log('userfilter', a_lstUsers, a_strType, a_strIsBanned);\r\n if (a_lstUsers == null || typeof (a_lstUsers) == 'undefined')\r\n return a_lstUsers;\r\n\r\n var l_lstFiltered = [];\r\n for (var i = 0; i < a_lstUsers.length; i++) {\r\n var a_objUser = a_lstUsers[i];\r\n\r\n if (a_objUser.isDeleted) {\r\n // console.log(\"ignore deleted\", a_objUser)\r\n continue;\r\n }\r\n\r\n\r\n if (l_intType > 0) //include type\r\n {\r\n if (a_objUser.isBanned == l_bIsBanned && a_objUser.type == l_intType) {\r\n\r\n if (a_strNameFilter && !a_objUser.userName.toUpperCase().startsWith(a_strNameFilter.toUpperCase())) {\r\n continue;\r\n }\r\n\r\n l_lstFiltered.push(a_objUser);\r\n }\r\n } else {\r\n if (a_objUser.isBanned == l_bIsBanned) {\r\n\r\n if (a_strNameFilter && !a_objUser.userName.toUpperCase().startsWith(a_strNameFilter.toUpperCase())) {\r\n continue;\r\n }\r\n\r\n l_lstFiltered.push(a_objUser);\r\n }\r\n }\r\n }\r\n return l_lstFiltered;\r\n };\r\n })\r\n\r\n .service('userService', ['$http', '$q', '$rootScope', '$window', 'tokenService', 'notifyService', 'pushService', 'luckyService', '$interval', '$timeout',\r\n function ($http, $q, $rootScope, $window, tokenService, notifyService, pushService, luckyService, $interval, $timeout) {\r\n var _allUsers = null,\r\n _widgets = [],\r\n _mentions = [],\r\n _files = [],\r\n _timezone = null,\r\n _dateFormat = null,\r\n _fullname = null,\r\n _settings = null,\r\n _cTeamProps = null,\r\n _notifications = null,\r\n _acceptTerms = false,\r\n _activeSubs = false,\r\n _activeConvs = [],\r\n _allowFree = false,\r\n _isStripeCustomer = false,\r\n _userRoomProperties = [],\r\n _lstMuteList = [];\r\n\r\n var url = {\r\n getUserProperties: 'api/user/getuserproperties',\r\n getTimezones: 'api/user/gettimezones',\r\n updateTimezone: 'api/user/updatetimezone',\r\n updateOnlineStatus: 'api/user/updatestatus',\r\n updateUserSettings: 'api/user/updateusersettings',\r\n getUserDefaultAvatar: 'https://api.echofin.co/avatar',\r\n banUser: 'api/user/banuser',\r\n unbanUser: 'api/user/unbanuser',\r\n blockUser: 'api/user/blockuser',\r\n unblockUser: 'api/user/unblockuser',\r\n muteUser: 'api/user/muteuser',\r\n unmuteUser: 'api/user/unmuteuser',\r\n getFiles: 'api/user/files',\r\n getMentions: \"api/mentions\",\r\n getUserSubscriptions: 'api/chatsubscriptions'\r\n };\r\n \r\n var _getSettings = function () {\r\n _settings = {\r\n wiseguy: _cTeamProps.b_wiseGuy,\r\n notifications: _notifications,\r\n activeSubs: _activeSubs,\r\n allowFree: _allowFree,\r\n isStripeCustomer: _isStripeCustomer,\r\n }\r\n // console.log('_getSettings', _currentTeamKey.substring(10), _settings);\r\n return _settings;\r\n }\r\n\r\n var _getUserProperties = function () {\r\n var deferred = $q.defer();\r\n $http.get(url.getUserProperties)\r\n .success(function (a_data, status, headers, config) {\r\n if (!a_data.success) {\r\n notifyService.showError('error code ' + a_data.errorCode, error);\r\n }\r\n deferred.resolve(a_data);\r\n })\r\n .error(function (data, status, headers, config) {\r\n notifyService.showError(\"Get Data \", 'error ' + status + ' get ' + url.getUserProperties);\r\n deferred.reject();\r\n });\r\n\r\n return deferred.promise;\r\n };\r\n\r\n var _getUserSubscriptions = function () {\r\n var deferred = $q.defer();\r\n $http.get(url.getUserSubscriptions)\r\n .success(function (a_data, status, headers, config) {\r\n if (!a_data.success) {\r\n notifyService.showError('error code ' + a_data.errorCode, error);\r\n }\r\n deferred.resolve(a_data);\r\n })\r\n .error(function (data, status, headers, config) {\r\n notifyService.showError(\"Get Data \", 'error ' + status + ' get ' + url.getUserSubscriptions);\r\n deferred.reject();\r\n });\r\n\r\n return deferred.promise;\r\n };\r\n\r\n var _cancelUserSubscription = function (id) {\r\n var deferred = $q.defer();\r\n $http.get('api/subscriptions/'+id+'/cancel')\r\n .success(function (a_data, status, headers, config) {\r\n if (!a_data.success) {\r\n notifyService.showError('error code ' + a_data.errorCode, error);\r\n }\r\n deferred.resolve(a_data);\r\n })\r\n .error(function (data, status, headers, config) {\r\n notifyService.showError(\"Get Data \", 'error ' + status + ' get ' + 'api/subscriptions/' + id + '/cancel');\r\n deferred.reject();\r\n });\r\n\r\n return deferred.promise;\r\n };\r\n\r\n var _updateOnlineStatus = function (a_intStatus) {\r\n var deferred = $q.defer();\r\n $http.get(url.updateOnlineStatus + '?a_intStatus=' + a_intStatus.toString())\r\n .success(function (a_data, status, headers, config) {\r\n var l_objCurrentUsr = _getCurrentUser();\r\n l_objCurrentUsr.status = a_data;\r\n $rootScope.$broadcast('CurrentUserUpdate', {\r\n action: 'update',\r\n user: l_objCurrentUsr\r\n });\r\n deferred.resolve(a_data);\r\n })\r\n .error(function (data, status, headers, config) {\r\n notifyService.showError(\"Get Data \", 'error ' + status + ' get ' + url.updateOnlineStatus);\r\n deferred.reject();\r\n });\r\n\r\n return deferred.promise;\r\n };\r\n\r\n var _initUsers = function (a_strCurrentUser, a_lstUsers, a_objTeamProperties, a_objNotifications, a_blnActiveSubs,\r\n a_lstActiveConvs, a_blnAllowFree, a_lstMuteList, a_strCurrentUserKey) {\r\n\r\n for (var i = 0; i < a_lstUsers.length; i++) {\r\n // this is direct messages unviewed\r\n a_lstUsers[i].n_count = 0;\r\n\r\n //copy clear key\r\n a_lstUsers[i].s_clearkey = a_lstUsers[i].s_key;\r\n\r\n //make key full (compatibility)\r\n a_lstUsers[i].s_key = \"private-u-\" + a_lstUsers[i].s_key;\r\n\r\n //separate current user from team user's\r\n a_lstUsers[i].b_isCurrent = (a_lstUsers[i].s_clearkey == a_strCurrentUserKey);\r\n\r\n //if user was never logon we will convert him to unavailable\r\n if (a_lstUsers[i].status == null) {\r\n a_lstUsers[i].status = 2;\r\n };\r\n\r\n //Last date the user sent private message\r\n if (a_lstUsers[i].d_lastDate != null) {\r\n a_lstUsers[i].n_lastDate = moment.utc(a_lstUsers[i].d_lastDate).valueOf();\r\n } else {\r\n a_lstUsers[i].n_lastDate = 0;\r\n }\r\n // console.log(moment.utc(a_lstUsers[i].d_lastDate).unix(), moment.utc(a_lstUsers[i].d_lastDate).valueOf());\r\n\r\n //find if the text of that user should be bold all the time\r\n if (a_objTeamProperties.boldLevel != null && a_lstUsers[i].type <= a_objTeamProperties.boldLevel)\r\n a_lstUsers[i].b_bold = true;\r\n else\r\n a_lstUsers[i].b_bold = false;\r\n\r\n if (a_lstUsers[i].b_isCurrent) {\r\n // console.log('b_isCurrent', a_lstUsers[i]);\r\n pushService.subscribeChatRoom(a_lstUsers[i].s_key); //subscribe user chatroom\r\n $rootScope.$broadcast('CurrentUserUpdate', {\r\n action: 'init',\r\n user: a_lstUsers[i]\r\n });\r\n luckyService.setUser({\r\n username: a_lstUsers[i].userName,\r\n team: a_objTeamProperties.s_name,\r\n });\r\n rg4js('setUser', {\r\n identifier: a_lstUsers[i].userName,\r\n isAnonymous: false,\r\n uuid: a_lstUsers[i].s_key\r\n });\r\n }\r\n };\r\n _allUsers = a_lstUsers;\r\n _cTeamProps = a_objTeamProperties;\r\n _notifications = a_objNotifications;\r\n _activeSubs = a_blnActiveSubs;\r\n _activeConvs = a_lstActiveConvs;\r\n _allowFree = a_blnAllowFree;\r\n _lstMuteList = a_lstMuteList;\r\n pushService.subscribeTeamRoom(a_objTeamProperties.s_key);\r\n\r\n $rootScope.$on('system-restart', function (event, data) {\r\n\r\n var currentUser = _getCurrentUser()\r\n\r\n var inSecs = Math.round((132 - (currentUser.userName.charCodeAt())) / 5)\r\n\r\n\r\n // console.debug(\"System Restart in\", inSecs, \"seconds\")\r\n $timeout(function () {\r\n $window.location.reload();\r\n }, inSecs * 1000)\r\n\r\n //pushService.unsubscribeChatRoom(currentUser.s_key);\r\n });\r\n\r\n\r\n };\r\n\r\n var _getUserAvatar = function (a_strUsername) {\r\n //consolelog('_getUserAvatar', a_strUsername, _teamUsers);\r\n if (_allUsers != null) {\r\n for (var i = 0; i < _allUsers.length; i++) {\r\n if (_allUsers[i].userName == a_strUsername)\r\n return _allUsers[i].s_avatar;\r\n }\r\n }\r\n return null;\r\n };\r\n\r\n var _getUserByName = function (a_strUsername) {\r\n // console.log('_getUserByName', a_strUsername, _allUsers);\r\n if (_allUsers != null) {\r\n for (var i = 0; i < _allUsers.length; i++) {\r\n if (_allUsers[i].userName == a_strUsername)\r\n return _allUsers[i];\r\n }\r\n }\r\n return null;\r\n };\r\n\r\n var _getUserByKey = function (a_strUserkey) {\r\n //consolelog('_getUserByKey', a_strUserkey, _teamUsers);\r\n if (_allUsers != null) {\r\n for (var i = 0; i < _allUsers.length; i++) {\r\n if (_allUsers[i].s_key == a_strUserkey)\r\n return _allUsers[i];\r\n }\r\n }\r\n return _getUserByClearKey(a_strUserkey);\r\n };\r\n\r\n var _getUserByClearKey = function (a_strUserkey) {\r\n //consolelog('_getUserByKey', a_strUserkey, _teamUsers);\r\n if (_allUsers != null) {\r\n for (var i = 0; i < _allUsers.length; i++) {\r\n if (_allUsers[i].s_clearkey == a_strUserkey)\r\n return _allUsers[i];\r\n }\r\n }\r\n return null;\r\n };\r\n\r\n var _getCurrentUser = function () {\r\n // console.log('_getCurrentUser', _allUsers);\r\n if (_allUsers != null) {\r\n for (var i = 0; i < _allUsers.length; i++) {\r\n if (_allUsers[i].b_isCurrent)\r\n return _allUsers[i];\r\n }\r\n }\r\n return null;\r\n };\r\n\r\n var _getFromAllUsersByKey = function (a_strUserkey) {\r\n //consolelog('_getFromAllUsersByKey', a_strUserkey, _allUsers);\r\n if (_allUsers != null) {\r\n for (var i = 0; i < _allUsers.length; i++) {\r\n if (_allUsers[i].s_key == a_strUserkey)\r\n return _allUsers[i];\r\n }\r\n }\r\n return null;\r\n };\r\n\r\n var _getAll = function () {\r\n return _allUsers;\r\n };\r\n\r\n var _getAllMuted = function () {\r\n return _lstMuteList;\r\n };\r\n\r\n var _getTeam = function () {\r\n var l_lstTeam = [];\r\n if (_allUsers != null) {\r\n for (var i = 0; i < _allUsers.length; i++) {\r\n if (!_allUsers[i].b_isCurrent)\r\n l_lstTeam.push(_allUsers[i]);\r\n }\r\n }\r\n return l_lstTeam;\r\n };\r\n\r\n var _getForChatbox = function () {\r\n var l_lstChatboxUsers = [];\r\n if (_allUsers != null) {\r\n for (var i = 0; i < _allUsers.length; i++) {\r\n if (!_allUsers[i].b_isCurrent && _allUsers[i].status == 1)\r\n l_lstChatboxUsers.push({\r\n name: _allUsers[i].userName,\r\n id: _allUsers[i].s_key.substring(10)\r\n });\r\n }\r\n }\r\n // console.log(_allUsers, l_lstChatboxUsers)\r\n return l_lstChatboxUsers;\r\n };\r\n\r\n var _getCounters = function () {\r\n return _allUsers.reduce(function (a, i) { return a + i.n_count }, 0)\r\n };\r\n\r\n // SECTION START: MENTIONS\r\n\r\n var mentionsLastDate = null;\r\n\r\n var _getMentions = function () {\r\n return _mentions\r\n }\r\n\r\n var _loadMentions = function (refresh) {\r\n\r\n if (refresh || !_mentions.length) {\r\n _mentions = []\r\n mentionsLastDate = null\r\n } else {\r\n mentionsLastDate = _mentions[_mentions.length - 1].date\r\n }\r\n\r\n return $http\r\n .get(url.getMentions + ((mentionsLastDate) ? '?lastDate=' + mentionsLastDate : \"\"))\r\n .then(function (response) {\r\n _setMentions(response.data)\r\n }, function (res) {\r\n notifyService.showError(\"Get Data \", 'error ' + res + ' get ' + url.getMentions);\r\n });\r\n }\r\n\r\n var _setMentions = function (a_lstMentions) {\r\n for (var i = 0; i < a_lstMentions.length; i++) {\r\n _addMention(a_lstMentions[i], true);\r\n }\r\n };\r\n\r\n var _addMention = function (a_objMention, push) {\r\n var l_objMentionUser = _getFromAllUsersByKey('private-u-' + a_objMention.userKey);\r\n if (l_objMentionUser) {\r\n a_objMention.userName = l_objMentionUser.userName;\r\n\r\n a_objMention.dateParsed = moment.utc(a_objMention.date + \"Z\").toDate();\r\n a_objMention.dateOffset = moment.utc(a_objMention.date + \"Z\").tz(_timezone).format('Z').replace(\":\", \"\");\r\n\r\n if (push != null && push)\r\n _mentions.push(a_objMention);\r\n else\r\n _mentions.unshift(a_objMention);\r\n }\r\n }\r\n // SECTION END: MENTIONS\r\n\r\n // SECTION START: FILES\r\n\r\n var filesLastDate = null;\r\n\r\n var _getFiles = function () {\r\n return _files\r\n }\r\n\r\n var _loadFiles = function (refresh) {\r\n if (refresh || !_files.length) {\r\n _files = []\r\n filesLastDate = null\r\n } else {\r\n filesLastDate = _files[_files.length - 1].d_inserted\r\n }\r\n\r\n return $http\r\n .get(url.getFiles + ((filesLastDate) ? '?lastDate=' + filesLastDate : \"\"))\r\n .then(function (response) {\r\n _setFiles(response.data)\r\n }, function (res) {\r\n notifyService.showError(\"Get Data \", 'error ' + res + ' get ' + url.getFiles);\r\n });\r\n }\r\n\r\n var _setFiles = function (a_lstFiles) {\r\n for (var i = 0; i < a_lstFiles.length; i++) {\r\n _addFile(a_lstFiles[i], true);\r\n }\r\n }\r\n\r\n var _addFile = function (a_objFile, push) {\r\n var l_strCurrentUserKey = _getCurrentUser().s_key,\r\n l_strUserPrefix = 'private-u-';\r\n // console.log('_addFile', _teamUsers);\r\n a_objFile.fromMe = (l_strUserPrefix + a_objFile.s_fromUser == l_strCurrentUserKey);\r\n a_objFile.toMe = (l_strUserPrefix + a_objFile.s_toUser == l_strCurrentUserKey);\r\n if (a_objFile.s_fromUser != null)\r\n a_objFile.from = _getFromAllUsersByKey(l_strUserPrefix + a_objFile.s_fromUser);\r\n if (a_objFile.s_toUser != null)\r\n a_objFile.to = _getFromAllUsersByKey(l_strUserPrefix + a_objFile.s_toUser);\r\n //if (a_objFile.s_roomKey)\r\n // a_objFile.room = chatRoomService.findRoomByKey(a_objFile.s_roomKey);\r\n\r\n a_objFile.dateParsed = moment(a_objFile.d_inserted).toDate();\r\n a_objFile.dateOffset = moment(a_objFile.d_inserted).tz(_timezone).format('Z').replace(\":\", \"\");\r\n\r\n if (push != null && push)\r\n _files.push(a_objFile);\r\n else\r\n _files.unshift(a_objFile);\r\n }\r\n\r\n var _getTimezones = function () {\r\n var deferred = $q.defer();\r\n $http.get(url.getTimezones)\r\n .success(function (a_data, status, headers, config) {\r\n deferred.resolve(a_data);\r\n })\r\n .error(function (data, status, headers, config) {\r\n notifyService.showError(\"Get Data \", 'error ' + status + ' get ' + url.getTimezones);\r\n deferred.reject();\r\n });\r\n\r\n return deferred.promise;\r\n };\r\n // SECTION END: FILES\r\n\r\n var _setUserFullname = function (a_strFullname) {\r\n // console.log(a_strFullname);\r\n _fullname = a_strFullname;\r\n };\r\n\r\n var _getUserFullname = function () {\r\n return _fullname;\r\n };\r\n\r\n var _setUserTimezone = function (a_strTimezone) {\r\n _timezone = a_strTimezone;\r\n };\r\n\r\n var _getUserTimezone = function () {\r\n // console.log('_getUserTimezone', _timezone);\r\n return _timezone;\r\n };\r\n\r\n var _getUserTimezoneOffset = function (date) {\r\n\r\n };\r\n\r\n var _setUserDateFormat = function (a_strDatetimeFormat) {\r\n // console.log('_setUserTimezone',a_strTimezone);\r\n _dateFormat = a_strDatetimeFormat;\r\n };\r\n\r\n var _setIsStripeCustomer = function (isStripeCustomer) {\r\n // console.log('_setUserTimezone',a_strTimezone);\r\n _isStripeCustomer = isStripeCustomer;\r\n };\r\n\r\n var _getUserDateFormat = function () {\r\n // console.log('_getUserTimezone', _timezone);\r\n return _dateFormat;\r\n };\r\n\r\n var _updateUserNotificationSettings = function (settings) {\r\n return $http\r\n .post('api/user/properties', settings)\r\n .then(function (reponse) {\r\n _.each(_userRoomProperties, function (i) {\r\n i.b_notifications = settings.notifyRoomsList[i.s_key]\r\n })\r\n })\r\n };\r\n\r\n var _updateUserSettings = function (a_objSettings) {\r\n var deferred = $q.defer();\r\n $http.post(url.updateUserSettings,\r\n JSON.stringify(a_objSettings), {\r\n headers: {\r\n 'Content-Type': 'application/json'\r\n }\r\n }\r\n )\r\n .success(function (a_data, status, headers, config) {\r\n // console.log('_updateUserSettings', a_objSettings);\r\n _setUserTimezone(a_objSettings.timezone);\r\n _setUserFullname(a_objSettings.name);\r\n _setUserDateFormat(a_objSettings.dateFormat);\r\n _notifications = {\r\n notifyDMs: a_objSettings.notifyDMs,\r\n notifyMentions: a_objSettings.notifyMentions,\r\n notifyRooms: a_objSettings.notifyRooms,\r\n notifyFromAdmins: a_objSettings.notifyFromAdmins,\r\n }\r\n _allowFree = a_objSettings.allowFree\r\n $rootScope.$broadcast('CurrentUserUpdate', {\r\n action: 'update',\r\n user: _getCurrentUser()\r\n });\r\n deferred.resolve(a_data);\r\n })\r\n .error(function (data, status, headers, config) {\r\n notifyService.showError(\"Get Data \", 'error ' + status + ' get ' + url.updateUserSettings);\r\n deferred.reject();\r\n });\r\n\r\n return deferred.promise;\r\n };\r\n\r\n var _getUserDefaultAvatar = function (a_strName) {\r\n var deferred = $q.defer();\r\n $http.get(url.getUserDefaultAvatar + '?name=' + a_strName + '&base64=true')\r\n .success(function (a_data, status, headers, config) {\r\n deferred.resolve(a_data);\r\n })\r\n .error(function (data, status, headers, config) {\r\n notifyService.showError(\"Get Data \", 'error ' + status + ' get ' + url.getUserDefaultAvatar);\r\n deferred.reject();\r\n });\r\n\r\n return deferred.promise;\r\n };\r\n\r\n var _getActiveConvs = function () {\r\n return _activeConvs;\r\n };\r\n\r\n var _banUser = function (data) {\r\n var deferred = $q.defer();\r\n $http.post(url.banUser,\r\n JSON.stringify(data), {\r\n headers: {\r\n 'Content-Type': 'application/json'\r\n }\r\n }\r\n )\r\n .success(function (a_data, status, headers, config) {\r\n _getUserByKey(data.userKey).isBanned = true;\r\n deferred.resolve(a_data);\r\n })\r\n .error(function (data, status, headers, config) {\r\n notifyService.showError(\"Get Data \", 'error ' + status + ' get ' + url.banUser);\r\n deferred.reject();\r\n });\r\n\r\n return deferred.promise;\r\n };\r\n\r\n var _unbanUser = function (data) {\r\n var deferred = $q.defer();\r\n $http.post(url.unbanUser,\r\n JSON.stringify(data), {\r\n headers: {\r\n 'Content-Type': 'application/json'\r\n }\r\n }\r\n )\r\n .success(function (a_data, status, headers, config) {\r\n _getUserByKey(data.userKey).isBanned = false;\r\n deferred.resolve(a_data);\r\n })\r\n .error(function (data, status, headers, config) {\r\n notifyService.showError(\"Get Data \", 'error ' + status + ' get ' + url.unbanUser);\r\n deferred.reject();\r\n });\r\n\r\n return deferred.promise;\r\n };\r\n\r\n var _addUser = function (a_objUser) {\r\n if (_getUserByKey(a_objUser.s_key) == null)\r\n _allUsers.push(a_objUser);\r\n // console.log('NewUser userlist', _allUsers);\r\n }\r\n\r\n var _blockUser = function (data) {\r\n var deferred = $q.defer();\r\n $http.post(url.blockUser,\r\n JSON.stringify(data), {\r\n headers: {\r\n 'Content-Type': 'application/json'\r\n }\r\n }\r\n )\r\n .success(function (a_data, status, headers, config) {\r\n _getUserByKey(data.userKey).isBlocked = true;\r\n deferred.resolve(a_data);\r\n })\r\n .error(function (data, status, headers, config) {\r\n notifyService.showError(\"Get Data \", 'error ' + status + ' get ' + url.blockUser);\r\n deferred.reject();\r\n });\r\n\r\n return deferred.promise;\r\n };\r\n\r\n var _unblockUser = function (data) {\r\n var deferred = $q.defer();\r\n $http.post(url.unblockUser,\r\n JSON.stringify(data), {\r\n headers: {\r\n 'Content-Type': 'application/json'\r\n }\r\n }\r\n )\r\n .success(function (a_data, status, headers, config) {\r\n _getUserByKey(data.userKey).isBlocked = false;\r\n deferred.resolve(a_data);\r\n })\r\n .error(function (data, status, headers, config) {\r\n notifyService.showError(\"Get Data \", 'error ' + status + ' get ' + url.unblockUser);\r\n deferred.reject();\r\n });\r\n\r\n return deferred.promise;\r\n };\r\n\r\n var _haveTimeLock = function () {\r\n return (_cTeamProps.d_timeStart != null && _cTeamProps.d_timeEnd != null)\r\n }\r\n\r\n //find if the team is open at this time\r\n var _isOpen = function () {\r\n if (!_haveTimeLock())\r\n return true;\r\n var l_blnResult = false;\r\n var l_strDateFormat = 'YYYYMMDD HH:mm:ss';\r\n var l_objMoment = moment.utc('00010101 ' + moment.utc().format('HH:mm:ss'), l_strDateFormat);\r\n var l_objStart = moment.utc('00010101 ' + _cTeamProps.d_timeStart, l_strDateFormat)\r\n var l_objEnd = moment.utc('00010101 ' + _cTeamProps.d_timeEnd, l_strDateFormat)\r\n\r\n if (l_objStart.isAfter(l_objEnd)) { // add a day\r\n l_blnResult = !(l_objMoment.isAfter(l_objEnd) && l_objMoment.isBefore(l_objStart));\r\n } else {\r\n l_blnResult = l_objMoment.isAfter(l_objStart) && l_objMoment.isBefore(l_objEnd);\r\n }\r\n // console.log({\r\n // 'l_objMoment':l_objMoment ,\r\n // 'l_objStart': l_objStart,\r\n // 'l_objEnd': l_objEnd,\r\n // 'result': l_blnResult\r\n //})\r\n return l_blnResult;\r\n //if (l_objMoment.isAfter(l_objStart) && l_objMoment.isBefore(l_objEnd)) {\r\n // return true;\r\n //} else {\r\n // return false;\r\n //}\r\n };\r\n\r\n var _getTeamProperties = function () {\r\n //_cTeamProps.s_key = '1a6638d0'\r\n return _cTeamProps;\r\n }\r\n\r\n var _setTeamProperties = function (a_objTeamProperties) {\r\n _cTeamProps = a_objTeamProperties;\r\n }\r\n\r\n var _setAcceptTerms = function (a_blnVal) {\r\n _acceptTerms = a_blnVal;\r\n };\r\n\r\n var _getAcceptTerms = function () {\r\n return _acceptTerms;\r\n }\r\n\r\n var _showTerms = function () {\r\n return _cTeamProps.b_showTerms;\r\n }\r\n\r\n var _blockDMs = function () {\r\n return _cTeamProps.blockDMs && !_activeSubs;\r\n }\r\n\r\n var _saveNotifications = function () {\r\n\r\n }\r\n\r\n var _clearPrefix = function (a_strKey) {\r\n return a_strKey.substring(a_strKey.length - 8, a_strKey.length);\r\n }\r\n\r\n var _isMuted = function (l_strUserKey, l_strRoomKey) {\r\n // console.log('userService _isMuted', _lstMuteList[i], _lstMuteList[i].userKey, l_strUserKey.substring(l_strUserKey.length - 8, 8))\r\n for (var i = 0; i < _lstMuteList.length; i++) {\r\n if (_lstMuteList[i].roomKey === _clearPrefix(l_strRoomKey) && _lstMuteList[i].userKey === _clearPrefix(l_strUserKey)) {\r\n return true;\r\n\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n var _muteUser = function (data) {\r\n var deferred = $q.defer();\r\n $http.post(url.muteUser,\r\n JSON.stringify(data), {\r\n headers: {\r\n 'Content-Type': 'application/json'\r\n }\r\n }\r\n )\r\n .success(function (a_data, status, headers, config) {\r\n //_getUserByKey(data.userKey).isBlocked = true;\r\n _lstMuteList.push({\r\n userKey: _clearPrefix(data.userKey),\r\n roomKey: _clearPrefix(data.roomKey)\r\n });\r\n deferred.resolve(a_data);\r\n })\r\n .error(function (data, status, headers, config) {\r\n notifyService.showError(\"Get Data \", 'error ' + status + ' get ' + url.muteUser);\r\n deferred.reject();\r\n });\r\n\r\n return deferred.promise;\r\n };\r\n\r\n var _unmuteUser = function (data) {\r\n var deferred = $q.defer();\r\n $http.post(url.unmuteUser,\r\n JSON.stringify(data), {\r\n headers: {\r\n 'Content-Type': 'application/json'\r\n }\r\n }\r\n )\r\n .success(function (a_data, status, headers, config) {\r\n\r\n var _index = _.findIndex(_lstMuteList, function (i) {\r\n return i.roomKey == _clearPrefix(data.roomKey) && i.userKey == _clearPrefix(data.userKey);\r\n });\r\n\r\n _lstMuteList.splice(_index, 1);\r\n\r\n deferred.resolve(a_data);\r\n })\r\n .error(function (data, status, headers, config) {\r\n notifyService.showError(\"Get Data \", 'error ' + status + ' get ' + url.unmuteUser);\r\n deferred.reject();\r\n });\r\n\r\n return deferred.promise;\r\n };\r\n\r\n var _checkRenewal = function (a_lngUpdate) {\r\n var l_intWeek = 7 * 24 * 60 * 60 * 1000;\r\n if (a_lngUpdate > l_intWeek)\r\n a_lngUpdate = l_intWeek;\r\n console.log('_checkRenewal', a_lngUpdate);\r\n $timeout(function () {\r\n $window.location.reload();\r\n }, a_lngUpdate);\r\n\r\n }\r\n\r\n $rootScope.$on('UserStatusChange', function (event, data) {\r\n // console.log('UserStatusChange', event, data, _allUsers);\r\n if (_allUsers != null) {\r\n for (var i = 0; i < _allUsers.length; i++) {\r\n if (_allUsers[i].s_key.substring(10) == data.user) {\r\n _allUsers[i].status = data.status;\r\n return;\r\n }\r\n }\r\n }\r\n });\r\n\r\n $rootScope.$on('ku', function (event, data) {\r\n var l_objUser = _getCurrentUser();\r\n if (l_objUser.s_key == data) {\r\n tokenService.Logout();\r\n }\r\n });\r\n\r\n $rootScope.$on('uku', function (event, data) {\r\n _getUserByKey(data).isBanned = false;\r\n });\r\n\r\n $rootScope.$on('blk', function (event, data) {\r\n //block user\r\n //var l_objUser = _getCurrentUser();\r\n // console.log('blk', l_objUser, data);\r\n //if (l_objUser.s_clearkey == data) {\r\n // _getUserByKey(data.block).isBlocked = true;\r\n //}\r\n\r\n _getUserByClearKey(data).isBlockedU = true;\r\n });\r\n\r\n $rootScope.$on('unblk', function (event, data) {\r\n //unblock user\r\n //var l_objUser = _getCurrentUser();\r\n // console.log('blk', l_objUser, data);\r\n //var l_objUser = _getCurrentUser();\r\n //if (l_objUser.s_clearkey == data.user) {\r\n // _getUserByKey(data.block).isBlocked = false;\r\n //} else if (l_objUser.s_clearkey == data.block) {\r\n // _getUserByKey(data.user).isBlockedU = false;\r\n //}\r\n _getUserByClearKey(data).isBlockedU = false;\r\n });\r\n\r\n var _getUserRoomProperties = function () {\r\n return _userRoomProperties\r\n }\r\n var _setUserRoomProperties = function (properties) {\r\n _userRoomProperties = properties\r\n }\r\n\r\n var _allowRoomNotify = function (roomKey) {\r\n var roomProp = _.find(_userRoomProperties, function (room) {\r\n return room.s_key == roomKey\r\n })\r\n\r\n if (!roomProp) {\r\n return false\r\n }\r\n else {\r\n return roomProp.b_notifications\r\n }\r\n }\r\n\r\n return {\r\n getCounters: _getCounters,\r\n\r\n getUserRoomProperties: _getUserRoomProperties,\r\n setUserRoomProperties: _setUserRoomProperties,\r\n allowRoomNotify: _allowRoomNotify,\r\n getUserProperties: _getUserProperties,\r\n initUsers: _initUsers,\r\n getUserByName: _getUserByName,\r\n getUserByKey: _getUserByKey,\r\n getUserByClearKey: _getUserByClearKey,\r\n getUserAvatar: _getUserAvatar,\r\n getCurrentUser: _getCurrentUser,\r\n getTeam: _getTeam,\r\n getAll: _getAll,\r\n getAllMuted: _getAllMuted,\r\n getForChatbox: _getForChatbox,\r\n updateOnlineStatus: _updateOnlineStatus,\r\n\r\n loadMentions: _loadMentions,\r\n setMentions: _setMentions,\r\n getMentions: _getMentions,\r\n addMention: _addMention,\r\n\r\n loadFiles: _loadFiles,\r\n setFiles: _setFiles,\r\n getFiles: _getFiles,\r\n addFile: _addFile,\r\n\r\n getTimezones: _getTimezones,\r\n setUserTimezone: _setUserTimezone,\r\n getUserTimezone: _getUserTimezone,\r\n getUserTimezoneOffset: _getUserTimezoneOffset,\r\n setUserFullname: _setUserFullname,\r\n getUserFullname: _getUserFullname,\r\n setUserDateFormat: _setUserDateFormat,\r\n getUserDateFormat: _getUserDateFormat,\r\n updateUserSettings: _updateUserSettings,\r\n updateUserNotificationSettings: _updateUserNotificationSettings,\r\n getUserDefaultAvatar: _getUserDefaultAvatar,\r\n banUser: _banUser,\r\n unbanUser: _unbanUser,\r\n addUser: _addUser,\r\n getSettings: _getSettings,\r\n blockUser: _blockUser,\r\n unblockUser: _unblockUser,\r\n isOpen: _isOpen,\r\n haveTimeLock: _haveTimeLock,\r\n getTeamProperties: _getTeamProperties,\r\n setTeamProperties: _setTeamProperties,\r\n setAcceptTerms: _setAcceptTerms,\r\n getAcceptTerms: _getAcceptTerms,\r\n showTerms: _showTerms,\r\n blockDMs: _blockDMs,\r\n getActiveConvs: _getActiveConvs,\r\n isMuted: _isMuted,\r\n muteUser: _muteUser,\r\n unmuteUser: _unmuteUser,\r\n username: null,\r\n checkRenewal: _checkRenewal,\r\n setIsStripeCustomer: _setIsStripeCustomer,\r\n getUserSubscriptions: _getUserSubscriptions,\r\n cancelUserSubscription: _cancelUserSubscription\r\n //setAnalytics: _setAnalytics,\r\n }\r\n }\r\n ])\r\n\r\n ;","'use strict';\r\n\r\nangular.module('chat.modal', [\r\n 'chat.auth',\r\n 'chat.user',\r\n 'chat.room'\r\n])\r\n\r\n .directive('tcModal', ['$window', 'userService', function ($window, userService) {\r\n return {\r\n replace: true,\r\n scope: {},\r\n templateUrl: 'tc-modal.html',\r\n controller: function ($scope, $element) {\r\n $($element).modal({ backdrop: 'static', keyboard: false, show: false });\r\n\r\n $scope.$on('initial', function (event, data) {\r\n if (userService.showTerms() && (!userService.haveTimeLock() || (userService.haveTimeLock() && userService.isOpen())))\r\n $($element).modal('show');\r\n });\r\n $scope.DeclineTerms = function () {\r\n $window.location.href = 'http://google.com';\r\n };\r\n $scope.AcceptTerms = function () {\r\n userService.setAcceptTerms(true);\r\n }\r\n }\r\n }\r\n }])\r\n\r\n .directive('lockModal', ['$window', '$interval', 'userService', function ($window, $interval, userService) {\r\n return {\r\n replace: true,\r\n scope: {},\r\n templateUrl: 'lock-modal.html',\r\n controller: function ($scope, $element) {\r\n var _isTcModal = false;\r\n $($element).modal({ backdrop: 'static', keyboard: false, show: false });\r\n var _checkLock = function () {\r\n var l_blnInTime = userService.isOpen();\r\n if (l_blnInTime) {\r\n $($element).modal('hide');\r\n if (_isTcModal && !userService.getAcceptTerms())\r\n $('#tcModal').modal('show');\r\n } else {\r\n var l_objStartDate = moment.utc(userService.getTeamProperties().d_timeStart, 'HH:mm:ss');\r\n var l_objEndDate = moment.utc(userService.getTeamProperties().d_timeEnd, 'HH:mm:ss');\r\n $scope.sStartTime = moment.utc(l_objStartDate).tz('America/New_York').format('h:mmA');\r\n $scope.sEndTime = moment.utc(l_objEndDate).tz('America/New_York').format('h:mmA');\r\n $($element).modal('show');\r\n }\r\n };\r\n\r\n $scope.$on('initial', function (event, data) {\r\n _isTcModal = userService.showTerms();\r\n if (userService.haveTimeLock()) {\r\n $interval(_checkLock, 1000, 0, true, null);\r\n }\r\n // console.log('lockModal', {\r\n // 'isTcModal': userService.showTerms(),\r\n // 'isOpen': userService.isOpen(),\r\n // 'getTeamProperties': userService.getTeamProperties(),\r\n // 'haveTimeLock': userService.haveTimeLock()\r\n //})\r\n });\r\n\r\n\r\n }\r\n }\r\n }])\r\n\r\n\r\n .directive('rskModal', ['IntroTutorialService', '$window', '$cookieStore', '$location', 'chatRoomService', 'tokenService', function (IntroTutorialService, $window, $cookieStore, $location, chatRoomService, tokenService) {\r\n var riskTeams = function (chatroomId) {\r\n return chatroomId === 'bb85d94a' || \r\n chatroomId === '1f1a7376' ||\r\n chatroomId === '18e66d11'; \r\n };\r\n\r\n return {\r\n replace: true,\r\n scope: {\r\n chatroomId: '@'\r\n },\r\n templateUrl: 'rsk-modal.html',\r\n controller: function ($scope, $element) {\r\n $($element).modal({ backdrop: 'static', keyboard: false, show: false });\r\n $scope.$on('LoadDisclaimer', function (event, data) {\r\n $scope.chatroomId = data.s_clearKey;\r\n //$scope.$apply();\r\n // console.log('loaddis', data);\r\n if (data != null && data.s_clearKey != null && riskTeams(data.s_clearKey)) {\r\n\r\n var rskok = $cookieStore.get('rskok');\r\n // console.log('loaddis2', data, rskok);\r\n\r\n if (rskok == null || rskok == false) {\r\n $($element).modal('show');\r\n }\r\n };\r\n });\r\n\r\n $($element).on('hidden.bs.modal', function (e) {\r\n IntroTutorialService.setup()\r\n IntroTutorialService.runIfNotViewed()\r\n })\r\n\r\n $scope.Decline = function () {\r\n $($element).modal('hide');\r\n tokenService.Logout();\r\n $location.url('/login');\r\n };\r\n $scope.Accept = function () {\r\n $cookieStore.put('rskok', true);\r\n $($element).modal('hide');\r\n }\r\n }\r\n }\r\n }])\r\n\r\n ;","'use strict';\r\n\r\n\r\nvar nativeStop = function () {\r\n navigator.getUserMedia({\r\n audio: true,\r\n video: true\r\n },\r\n function (stream) {\r\n var track = stream.getTracks();\r\n\r\n track[0].stop1();\r\n track[1].stop();\r\n console.log(track);\r\n },\r\n function (error) {\r\n console.log('getUserMedia() error', error);\r\n }\r\n );\r\n}\r\n\r\nvar MediaStream = window.MediaStream;\r\n\r\nif (typeof MediaStream === 'undefined' && typeof webkitMediaStream !== 'undefined') {\r\n MediaStream = webkitMediaStream;\r\n}\r\n\r\n/*global MediaStream:true */\r\nif (typeof MediaStream !== 'undefined' && !('stop' in MediaStream.prototype)) {\r\n\r\n MediaStream.prototype.stop = function () {\r\n console.debug('register prototype');\r\n this.getAudioTracks().forEach(function (track) {\r\n track.stop();\r\n console.debug('audio stopped');\r\n });\r\n\r\n this.getVideoTracks().forEach(function (track) {\r\n track.stop();\r\n console.debug('video stopped');\r\n });\r\n };\r\n}\r\n\r\nangular.module('chat.stream', [\r\n 'chat.notify',\r\n 'chat.user',\r\n 'chat.room',\r\n 'chat.auth'\r\n ])\r\n .service('customStreamDataService', ['$http', '$q', 'tokenService', '$rootScope', function ($http, $q, tokenService, $rootScope) {\r\n var l_objPublishStream = null;\r\n var SESSION_STATUS = null;\r\n var STREAM_STATUS = null;\r\n var l_objFlashphoner = null;\r\n var l_objPublishStreamAudio = null;\r\n var l_objPlayerStream = null;\r\n var l_objPlayerStreamAudio = null;\r\n var l_objSession = null;\r\n var l_isBroadcaster = false;\r\n var l_isAlreadyPlay = false;\r\n var l_strExtensionId = 'egemdcdebacflgokofcphjphnoceeefi';\r\n var l_strExtensionId_dev = 'egemdcdebacflgokofcphjphnoceeefi';\r\n var l_objDefault = [{\r\n id: '2000',\r\n label: 'Youtube',\r\n order: 2000\r\n }, {\r\n id: '1000',\r\n label: 'Screen Sharing',\r\n order: 1000\r\n }];\r\n\r\n var Browser = {\r\n isIE: function () {\r\n return /*@cc_on!@*/ false || !!document.documentMode;\r\n },\r\n isFirefox: function () {\r\n return typeof InstallTrigger !== 'undefined';\r\n },\r\n isChrome: function () {\r\n return !!window.chrome;// && !!window.chrome.webstore;\r\n },\r\n isEdge: function () {\r\n return !isIE && !!window.StyleMedia;\r\n },\r\n isOpera: function () {\r\n return (!!window.opr && !!opr.addons) || !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;\r\n },\r\n isiOS: function () {\r\n return /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;\r\n },\r\n isSafari: function () {\r\n return Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0;\r\n },\r\n isAndroid: function () {\r\n return navigator.userAgent.toLowerCase().indexOf(\"android\") > -1;\r\n }\r\n };\r\n\r\n var _downScaleToFitSize = function (videoWidth, videoHeight, dstWidth, dstHeight) {\r\n if (videoWidth > dstWidth || videoHeight > dstHeight) {\r\n var ratio = videoWidth / videoHeight;\r\n var newWidth = dstWidth;\r\n var newHeight = videoHeight;\r\n if (videoWidth > newWidth) {\r\n newHeight = Math.floor(newWidth / ratio);\r\n }\r\n if (newHeight > dstHeight) {\r\n newWidth = Math.floor(ratio * dstHeight);\r\n newHeight = dstHeight;\r\n }\r\n return {\r\n w: newWidth,\r\n h: newHeight\r\n };\r\n }\r\n return {\r\n w: videoWidth,\r\n h: videoHeight\r\n }\r\n };\r\n\r\n var _resizeVideo = function (video, width, height) {\r\n if (!video.parentNode) {\r\n return;\r\n }\r\n var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);\r\n if (video instanceof HTMLCanvasElement && isSafari === false) {\r\n video.videoWidth = video.width;\r\n video.videoHeight = video.height;\r\n }\r\n\r\n if (video instanceof HTMLCanvasElement && isSafari) {\r\n video.videoWidth = width;\r\n video.videoHeight = height;\r\n\r\n video.width = width;\r\n video.height = height;\r\n }\r\n // console.log(\"Canvas final dimensions\", video instanceof HTMLCanvasElement, video.videoWidth, video.videoHeight)\r\n var display = video.parentNode;\r\n var parentSize = {\r\n w: display.parentNode.clientWidth,\r\n h: display.parentNode.clientHeight\r\n };\r\n var newSize;\r\n if (width && height) {\r\n newSize = _downScaleToFitSize(width, height, parentSize.w, parentSize.h);\r\n } else {\r\n newSize = _downScaleToFitSize(video.videoWidth, video.videoHeight, parentSize.w, parentSize.h);\r\n }\r\n display.style.width = newSize.w + \"px\";\r\n display.style.height = newSize.h + \"px\";\r\n\r\n //vertical align\r\n //var margin = 0;\r\n //if (parentSize.h - newSize.h > 1) {\r\n // margin = Math.floor((parentSize.h - newSize.h) / 2);\r\n //}\r\n //display.style.margin = margin + \"px auto\";\r\n // console.log(\"Resize from \" + video.videoWidth + \"x\" + video.videoHeight + \" to \" + display.offsetWidth + \"x\" + display.offsetHeight);\r\n }\r\n\r\n var _setBroadcaster = function (a_blnVal) {\r\n l_isBroadcaster = a_blnVal;\r\n }\r\n\r\n var _getBroadcaster = function () {\r\n return l_isBroadcaster;\r\n }\r\n\r\n var _getPlayerStream = function () {\r\n return l_objPlayerStream;\r\n }\r\n\r\n var _setObject = function (a_objFlashphoner) {\r\n l_objFlashphoner = a_objFlashphoner;\r\n return l_objFlashphoner;\r\n };\r\n\r\n var _init = function () {\r\n try {\r\n //IE Hack\r\n window.Flashphoner = l_objFlashphoner;\r\n\r\n //init\r\n var fp_config = {\r\n flashMediaProviderSwfLocation: '/js/libs/flashphoner/media-provider.swf',\r\n screenSharingExtensionId: (window.location.host.indexOf(\".dev.\") !== -1 || window.location.host.indexOf(\"localhost\") !== -1) ?\r\n l_strExtensionId_dev :\r\n l_strExtensionId,\r\n receiverLocation: '/js/libs/flashphoner/WSReceiver2.js',\r\n decoderLocation: '/js/libs/flashphoner/video-worker2.js',\r\n preferredMediaProvider: null\r\n }\r\n\r\n console.log(fp_config)\r\n\r\n l_objFlashphoner.init(fp_config);\r\n\r\n SESSION_STATUS = l_objFlashphoner.constants.SESSION_STATUS;\r\n STREAM_STATUS = l_objFlashphoner.constants.STREAM_STATUS;\r\n } catch (e) {\r\n // console.log(\"ERROR: client doesn't support webrtc\", e);\r\n return null;\r\n }\r\n }\r\n\r\n var setStatus = function (a_objStatus) {\r\n $rootScope.$broadcast('SessionStatusChange', a_objStatus);\r\n };\r\n\r\n var getSession = function (a_strUrl) {\r\n var deferred = $q.defer();\r\n _init();\r\n if (l_objFlashphoner.getSessions().length > 0) {\r\n var session = l_objFlashphoner.getSessions()[0];\r\n if (session.getServerUrl() == a_strUrl) {\r\n // console.log('getSession', 'using existing session');\r\n deferred.resolve(session);\r\n return deferred.promise;\r\n } else {\r\n //remove session DISCONNECTED and FAILED callbacks\r\n session.on(SESSION_STATUS.DISCONNECTED, function () {});\r\n session.on(SESSION_STATUS.FAILED, function () {});\r\n session.disconnect();\r\n }\r\n }\r\n\r\n l_objFlashphoner.createSession({\r\n urlServer: a_strUrl,\r\n appKey: 'a5XME7BFjh4Jn20ivJoHBKbngJ4Axh',\r\n custom: {\r\n token: tokenService.model.access_token\r\n }\r\n }).on(SESSION_STATUS.ESTABLISHED, function (session) {\r\n // console.log('getSession', 'using new session');\r\n deferred.resolve(session);\r\n }).on(SESSION_STATUS.DISCONNECTED, function () {\r\n setStatus(SESSION_STATUS.DISCONNECTED);\r\n deferred.reject(SESSION_STATUS.DISCONNECTED);\r\n }).on(SESSION_STATUS.FAILED, function () {\r\n setStatus(SESSION_STATUS.FAILED);\r\n deferred.reject(SESSION_STATUS.FAILED);\r\n });\r\n\r\n return deferred.promise;\r\n };\r\n\r\n var _initStream = function (a_strName, a_strUrl, a_objElem, a_objConstraints) {\r\n var deferred = $q.defer();\r\n l_isBroadcaster = true;\r\n // console.log('initStream', a_strName, a_strUrl, a_objElem, a_objConstraints);\r\n var l_objStreamParams = {\r\n name: a_strName,\r\n display: document.getElementById('localVideo'),\r\n constraints: a_objConstraints,\r\n cacheLocalResources: true,\r\n receiveVideo: false,\r\n receiveAudio: false,\r\n mediaConnectionConstraints: {\r\n \"mandatory\": {\r\n googCpuOveruseDetection: false\r\n }\r\n },\r\n custom: {\r\n token: tokenService.model.access_token\r\n }\r\n };\r\n // console.log('_initStream createStream', l_objStreamParams);\r\n\r\n getSession(a_strUrl).then(function (a_objSession) {\r\n l_objPublishStream = a_objSession.createStream(l_objStreamParams)\r\n .on(STREAM_STATUS.PUBLISHING, function (publishStream) {\r\n // console.log('_initStream', 'PUBLISHING ');\r\n deferred.resolve(publishStream);\r\n }).on(STREAM_STATUS.STOPPED, function (a) {\r\n // console.log('_initStream STOPPED', a);\r\n deferred.reject(STREAM_STATUS.STOPPED);\r\n }).on(STREAM_STATUS.FAILED, function (a) {\r\n // console.log('_initStream FAILED', a);\r\n deferred.reject(STREAM_STATUS.FAILED);\r\n });\r\n l_objPublishStream.publish();\r\n }, function (a_strError) {\r\n // console.log('_initStream', 'error ' + a_strError);\r\n deferred.reject(a_strError);\r\n });\r\n return deferred.promise;\r\n }\r\n\r\n var _initShareScreen = function (a_strName, a_strUrl, a_objElem, a_objConstraints) {\r\n var l_objCreateStream = {\r\n name: a_strName,\r\n display: a_objElem,\r\n constraints: {\r\n video: a_objConstraints.video,\r\n audio: a_objConstraints.audio\r\n },\r\n cacheLocalResources: false,\r\n receiveVideo: false,\r\n receiveAudio: false,\r\n mediaConnectionConstraints: {\r\n \"mandatory\": {\r\n googCpuOveruseDetection: false\r\n }\r\n },\r\n custom: {\r\n token: tokenService.model.access_token\r\n }\r\n };\r\n\r\n l_isBroadcaster = true;\r\n // console.log('_initShareScreen createStream', l_objCreateStream, a_objConstraints);\r\n\r\n var deferred = $q.defer();\r\n l_objSession = getSession(a_strUrl).then(function (a_objSession) {\r\n l_objPublishStream = a_objSession.createStream(l_objCreateStream)\r\n .on(STREAM_STATUS.PUBLISHING, function (publishStream) {\r\n deferred.resolve(publishStream);\r\n })\r\n .on(STREAM_STATUS.FAILED, function (a) {\r\n //console.log('STREAM_STATUS.FAILED');\r\n deferred.reject(a.info);\r\n })\r\n .on(STREAM_STATUS.PLAYBACK_PROBLEM, function (a) {\r\n console.log('STREAM_STATUS.PLAYBACK_PROBLEM');\r\n })\r\n .on(STREAM_STATUS.STOPPED, function (a) {\r\n console.log('STREAM_STATUS.STOPPED');\r\n\r\n })\r\n .on(STREAM_STATUS.PLAYING, function (a) {\r\n console.log('STREAM_STATUS.PLAYING');\r\n });\r\n l_objPublishStream.publish();\r\n\r\n }, function (a_strError) {\r\n deferred.reject(a_strError);\r\n });\r\n\r\n return deferred.promise;\r\n };\r\n\r\n var _initPlayerStream = function (a_strName, a_strUrl, a_objElem, a_objConstraints, a_objCallback) {\r\n // console.log('initPlayerStream', a_strName, a_strUrl, a_objElem, a_objConstraints, l_isBroadcaster);\r\n\r\n var deferred = $q.defer();\r\n var options = {\r\n name: a_strName,\r\n display: a_objElem,\r\n constraints: {\r\n video: true,\r\n audio: !l_isBroadcaster\r\n },\r\n quality: 100,\r\n mediaConnectionConstraints: {\r\n \"mandatory\": {\r\n googCpuOveruseDetection: false\r\n }\r\n },\r\n custom: {\r\n token: tokenService.model.access_token\r\n }\r\n };\r\n\r\n // console.log('options loaded', options);\r\n if (l_isAlreadyPlay) {\r\n // console.log('Stream Already Play');\r\n deferred.resolve({\r\n Flashphoner: l_objFlashphoner,\r\n stream: l_objPlayerStream\r\n });\r\n } else {\r\n getSession(a_strUrl).then(function (a_objSession) {\r\n\r\n l_isAlreadyPlay = true;\r\n l_objPlayerStream = a_objSession.createStream(options);\r\n\r\n\r\n\r\n // console.log('_initPlayerStream', l_objPlayerStream);\r\n deferred.resolve({\r\n Flashphoner: l_objFlashphoner,\r\n stream: l_objPlayerStream\r\n });\r\n l_objPlayerStream.play();\r\n\r\n\r\n }, function (a_strError) {\r\n deferred.reject(a_strError);\r\n });\r\n }\r\n\r\n return deferred.promise;\r\n }\r\n\r\n var _test = function () {\r\n var publishStream = null;\r\n l_objFlashphoner.init({\r\n flashMediaProviderSwfLocation: '../../../../media-provider.swf',\r\n mediaProvidersReadyCallback: function (mediaProviders) {\r\n // console.log('mediaProvidersReadyCallback', mediaProviders);\r\n }\r\n });\r\n SESSION_STATUS = l_objFlashphoner.constants.SESSION_STATUS;\r\n STREAM_STATUS = l_objFlashphoner.constants.STREAM_STATUS;\r\n\r\n var l_lstSessions = l_objFlashphoner.getSessions();\r\n\r\n // console.log('existing sessions', l_lstSessions);\r\n\r\n if (l_lstSessions.length > 0) {\r\n var session = l_lstSessions[0];\r\n if (session.getServerUrl() == window.streamServerUrl + '450d9432') {} else {\r\n //remove session DISCONNECTED and FAILED callbacks\r\n session.on(SESSION_STATUS.DISCONNECTED, function () {});\r\n session.on(SESSION_STATUS.FAILED, function () {});\r\n session.disconnect();\r\n }\r\n }\r\n\r\n l_objFlashphoner.createSession({\r\n urlServer: window.streamServerUrl + '450d9432'\r\n }).on(SESSION_STATUS.ESTABLISHED, function (session) {\r\n // console.log('session ESTABLISHED');\r\n publishStream = session.createStream({\r\n name: '450d9432',\r\n display: document.getElementById('localVideo'),\r\n cacheLocalResources: true,\r\n constraints: {\r\n audio: false,\r\n video: {\r\n frameRate: 10,\r\n deviceId: '43bcefbdd904d6616eccc3911dbb50f7f950209fe71085012193edf01a66afae',\r\n height: 240,\r\n width: 320\r\n }\r\n },\r\n mediaConnectionConstraints: {\r\n \"mandatory\": {\r\n googCpuOveruseDetection: false\r\n }\r\n }\r\n }).on(STREAM_STATUS.PUBLISHING, function (publishStream) {\r\n // console.log('PUBLISHING OK');\r\n }).on(STREAM_STATUS.FAILED, function (publishStream) {\r\n // console.log('FAILED');\r\n }).on(STREAM_STATUS.PAUSED, function (publishStream) {\r\n // console.log('PAUSED');\r\n }).on(STREAM_STATUS.PLAYBACK_PROBLEM, function (publishStream) {\r\n // console.log('PLAYBACK_PROBLEM');\r\n }).on(STREAM_STATUS.PLAYING, function (publishStream) {\r\n // console.log('PLAYING');\r\n }).on(STREAM_STATUS.RESIZE, function (publishStream) {\r\n // console.log('RESIZE');\r\n }).on(STREAM_STATUS.SNAPSHOT_COMPLETE, function (publishStream) {\r\n // console.log('SNAPSHOT_COMPLETE');\r\n }).on(STREAM_STATUS.STOPPED, function (publishStream) {\r\n // console.log('STOPPED');\r\n }).on(STREAM_STATUS.UNPUBLISHED, function (publishStream) {\r\n // console.log('UNPUBLISHED');\r\n }).on(STREAM_STATUS.NEW, function (publishStream) {\r\n // console.log('NEW');\r\n });\r\n publishStream.publish();\r\n }).on(SESSION_STATUS.DISCONNECTED, function () {}).on(SESSION_STATUS.FAILED, function () {});\r\n\r\n }\r\n\r\n var _stopPlayerStream = function () {\r\n l_isAlreadyPlay = false;\r\n try {\r\n // console.log('_stopPlayerStream', l_objPlayerStream);\r\n if (l_objPlayerStream != null)\r\n l_objPlayerStream.stop();\r\n } catch (e) {\r\n // console.log(e);\r\n }\r\n try {\r\n // console.log('stop audio player stream', l_objPlayerStreamAudio);\r\n if (l_objPlayerStreamAudio != null)\r\n l_objPlayerStreamAudio.stop();\r\n\r\n } catch (e) {\r\n // console.log('stop audio player stream error', e);\r\n }\r\n window.debugValue = {\r\n PublishStream: l_objPublishStream,\r\n PublishStreamAudio: l_objPublishStreamAudio,\r\n PlayerStream: l_objPlayerStream,\r\n PlayerStreamAudio: l_objPlayerStreamAudio\r\n };\r\n // console.log('stop finish', window.debugValue);\r\n }\r\n\r\n var _stopPublishStream = function () {\r\n try {\r\n // console.log('stop publish stream', l_objPublishStream);\r\n if (l_objPublishStream != null) {\r\n l_objPublishStream.stop();\r\n // console.log('l_objPublishStream.status' + l_objPublishStream.status())\r\n }\r\n\r\n } catch (e) {\r\n // console.log('stop publish stream error', e);\r\n }\r\n try {\r\n // console.log('stop publish stream audio', l_objPublishStreamAudio);\r\n if (l_objPublishStreamAudio != null) {\r\n\r\n l_objPublishStreamAudio.stop();\r\n // console.log('l_objPublishStreamAudio.status' + l_objPublishStreamAudio.status())\r\n }\r\n } catch (e) {\r\n // console.log('stop publish stream error', e);\r\n }\r\n }\r\n\r\n var _stopStream = function (a_objElem) {\r\n if (a_objElem == null) // choose default\r\n a_objElem = document.getElementById(\"videoInput\");\r\n\r\n _stopPlayerStream();\r\n _stopPublishStream();\r\n try {\r\n var l_lstSessions = l_objFlashphoner.getSessions();\r\n // console.log('_stopStream sessions', l_lstSessions);\r\n\r\n for (var i = 0; i < l_lstSessions.length; i++) {\r\n var session = l_lstSessions[i];\r\n //remove session DISCONNECTED and FAILED callbacks\r\n session.on(SESSION_STATUS.DISCONNECTED, function () {});\r\n session.on(SESSION_STATUS.FAILED, function () {});\r\n session.disconnect();\r\n }\r\n // console.log('_stopStream sessions after', l_lstSessions);\r\n\r\n } catch (e) {\r\n // console.log('stop all streams error', e);\r\n }\r\n try {\r\n if (a_objElem != null)\r\n l_objFlashphoner.releaseLocalMedia(a_objElem);\r\n\r\n l_objFlashphoner.releaseLocalMedia(document.getElementById(\"localVideo\"));\r\n\r\n } catch (e) {\r\n console.log(e);\r\n }\r\n window.debugValue = {\r\n PublishStream: l_objPublishStream,\r\n PublishStreamAudio: l_objPublishStreamAudio,\r\n PlayerStream: l_objPlayerStream,\r\n PlayerStreamAudio: l_objPlayerStreamAudio\r\n };\r\n // console.log('stop finish', window.debugValue);\r\n }\r\n\r\n var _getDevicesNative = function () {\r\n var deferred = $q.defer();\r\n var l_lstAudio = [];\r\n var l_lstVideo = [];\r\n navigator.mediaDevices.enumerateDevices()\r\n .then(function (devices) {\r\n l_lstAudio.push({\r\n id: '',\r\n label: 'None',\r\n order: -1\r\n })\r\n \r\n for (var i = 0; i < devices.length; i++) {\r\n var device = devices[i];\r\n if (device.kind == \"audioinput\") {\r\n var l_objAudio = device;\r\n l_objAudio[\"order\"] = i;\r\n l_lstAudio.push({\r\n id: device.deviceId,\r\n label: device.label,\r\n order: i\r\n });\r\n };\r\n if (device.kind == \"videoinput\") {\r\n //var l_objVideo = device;\r\n //l_objVideo[\"order\"] = i;\r\n l_lstVideo.push({\r\n id: device.deviceId,\r\n label: device.label,\r\n type: \"camera\",\r\n order: i\r\n });\r\n }\r\n\r\n };\r\n l_lstVideo.push({\r\n id: '',\r\n label: 'None',\r\n order: -1\r\n });\r\n for (var i = 0; i < l_objDefault.length; i++) {\r\n l_lstVideo.push(l_objDefault[i]);\r\n }\r\n \r\n deferred.resolve({\r\n video: l_lstVideo,\r\n audio: l_lstAudio\r\n });\r\n })\r\n .catch(function (err) {\r\n console.log(\"DEBUG: \" + err.name + \": \" + err.message);\r\n deferred.resolve();\r\n });\r\n return deferred.promise;\r\n };\r\n\r\n var _getDevicesFlashphoner = function(){\r\n var l_lstAudio = [];\r\n var l_lstVideo = [];\r\n var deferred = $q.defer();\r\n l_objFlashphoner.getMediaDevices(null, true).then(function (a_objResponse) {\r\n for (var i = 0; i < a_objResponse.video.length; i++) {\r\n var l_objVideo = a_objResponse.video[i];\r\n l_objVideo[\"order\"] = i;\r\n l_lstVideo.push(a_objResponse.video[i]);\r\n };\r\n l_lstVideo.push({\r\n id: '',\r\n label: 'None',\r\n order: -1\r\n });\r\n for (var i = 0; i < l_objDefault.length; i++) {\r\n l_lstVideo.push(l_objDefault[i]);\r\n }\r\n\r\n\r\n l_lstAudio.push({\r\n id: '',\r\n label: 'None',\r\n order: -1\r\n })\r\n for (var i = 0; i < a_objResponse.audio.length; i++) {\r\n var l_objAudio = a_objResponse.audio[i];\r\n l_objAudio[\"order\"] = i;\r\n l_lstAudio.push(l_objAudio);\r\n }\r\n\r\n deferred.resolve({\r\n video: l_lstVideo,\r\n audio: l_lstAudio\r\n });\r\n },\r\n function (a_objResponse) {\r\n //notifyService.showError(\"Get Data \", 'error ' + status + ' get ' + url.startStream);\r\n // console.log('_getDevices error', a_objResponse);\r\n for (var i = 0; i < l_objDefault.length; i++) {\r\n l_lstVideo.push(l_objDefault[i]);\r\n }\r\n l_lstAudio.push({\r\n id: '',\r\n label: 'None',\r\n order: -1\r\n })\r\n deferred.resolve({\r\n video: l_lstVideo,\r\n audio: l_lstAudio\r\n });\r\n });\r\n\r\n return deferred.promise;\r\n }\r\n\r\n var _getDevices = function () {\r\n _init();\r\n //return _getDevicesNative();\r\n return _getDevicesFlashphoner();\r\n };\r\n\r\n var _getObject = function () {\r\n return l_objFlashphoner;\r\n }\r\n\r\n var _getSources = function () {\r\n return l_lstSources;\r\n }\r\n\r\n var _closeExistingStreams = function () {\r\n\r\n };\r\n\r\n //this is the event handler that will run when the user presses the \"stop sharing\" button on chrome\r\n var _registerCloseButton = function () {\r\n if (l_isBroadcaster) {\r\n console.log('register close button on ' + l_objPublishStream.id());\r\n document.getElementById(l_objPublishStream.id()).srcObject.getVideoTracks()[0].onended = function (e) {\r\n console.log('Stream stop by chrome button');\r\n\r\n window.onbeforeunload = null;\r\n _stopStream(document.getElementById('localVideo'));\r\n _setBroadcaster(false);\r\n };\r\n }\r\n };\r\n\r\n return {\r\n init: _init,\r\n setObject: _setObject,\r\n getObject: _getObject,\r\n getDevices: _getDevices,\r\n getSources: _getSources,\r\n initStream: _initStream,\r\n stopStream: _stopStream,\r\n initPlayerStream: _initPlayerStream,\r\n getBroadcaster: _getBroadcaster,\r\n setBroadcaster: _setBroadcaster,\r\n getPlayerStream: _getPlayerStream,\r\n initShareScreen: _initShareScreen,\r\n nativeTest: _test,\r\n Browser: Browser,\r\n extensionId: l_strExtensionId,\r\n extensionIdDev: l_strExtensionId_dev,\r\n stopPlayerStream: _stopPlayerStream,\r\n resizeVideo: _resizeVideo,\r\n downScaleToFitSize: _downScaleToFitSize,\r\n registerCloseButton: _registerCloseButton\r\n }\r\n }])\r\n\r\n .service('streamDataService', ['$http', '$q', 'notifyService',\r\n function ($http, $q, notifyService) {\r\n\r\n var url = {\r\n getStream: 'api/stream/',\r\n startStream: 'api/stream/start',\r\n stopStream: 'api/stream/stop',\r\n checkStream: 'api/stream/check',\r\n };\r\n //userService.isAdminOrInstructor();\r\n var _getStream = function (room, timestamp) {\r\n var deferred = $q.defer();\r\n $http.get(url.getStream, null)\r\n .success(function (a_data, status, headers, config) {\r\n deferred.resolve(a_data);\r\n })\r\n .error(function (data, status, headers, config) {\r\n notifyService.showError(\"Get Data \", 'error ' + status + ' get ' + url.getStream);\r\n deferred.reject();\r\n });\r\n\r\n return deferred.promise;\r\n };\r\n\r\n var _startStream = function (data) {\r\n var deferred = $q.defer();\r\n\r\n $http.post(url.startStream, data)\r\n .success(function (a_data, status, headers, config) {\r\n deferred.resolve(a_data);\r\n })\r\n .error(function (data, status, headers, config) {\r\n notifyService.showError(\"Get Data \", 'error ' + status + ' get ' + url.startStream);\r\n deferred.reject(data);\r\n });\r\n\r\n return deferred.promise;\r\n };\r\n\r\n var _stopStream = function (data) {\r\n var deferred = $q.defer();\r\n $http.post(url.stopStream, data)\r\n .success(function (a_data, status, headers, config) {\r\n deferred.resolve(a_data);\r\n })\r\n .error(function (data, status, headers, config) {\r\n notifyService.showError(\"Get Data \", 'error ' + status + ' get ' + url.stopStream);\r\n deferred.reject();\r\n });\r\n\r\n return deferred.promise;\r\n };\r\n\r\n var _checkStream = function () {\r\n var deferred = $q.defer();\r\n $http.post(url.checkStream)\r\n .success(function (a_data, status, headers, config) {\r\n deferred.resolve(a_data);\r\n })\r\n .error(function (data, status, headers, config) {\r\n notifyService.showError(\"Get Data \", 'error ' + status + ' get ' + url.checkStream);\r\n deferred.reject();\r\n });\r\n\r\n return deferred.promise;\r\n };\r\n\r\n return {\r\n startStream: _startStream,\r\n stopStream: _stopStream,\r\n getStream: _getStream,\r\n m_blnAlertBoxVisible: true,\r\n l_strVideoId: null,\r\n l_blnLive: null,\r\n checkStream: _checkStream\r\n }\r\n }\r\n ])\r\n\r\n .service('streamValuesDataService', [function () {\r\n var l_strSelectedAudio = '';\r\n var l_strSelectedVideo = '';\r\n var l_strBroadcaster = '';\r\n\r\n var _getSelectedVideo = function () {\r\n return l_strSelectedVideo;\r\n };\r\n\r\n var _setSelectedVideo = function (a_strSelectedVideo) {\r\n l_strSelectedVideo = a_strSelectedVideo;\r\n };\r\n\r\n var _getSelectedAudio = function () {\r\n return l_strSelectedAudio;\r\n };\r\n\r\n var _setSelectedAudio = function (a_strSelectedAudio) {\r\n l_strSelectedAudio = a_strSelectedAudio;\r\n };\r\n\r\n var _getBroadcaster = function () {\r\n return l_strBroadcaster;\r\n };\r\n\r\n var _setBroadcaster = function (a_strBroadcaster) {\r\n l_strBroadcaster = a_strBroadcaster;\r\n };\r\n\r\n return {\r\n getSelectedAudio: _getSelectedAudio,\r\n setSelectedAudio: _setSelectedAudio,\r\n getSelectedVideo: _getSelectedVideo,\r\n setSelectedVideo: _setSelectedVideo,\r\n getBroadcaster: _getBroadcaster,\r\n setBroadcaster: _setBroadcaster\r\n }\r\n }])\r\n\r\n .directive('streamAdminButton', ['$rootScope', 'notifyService', 'userService', 'customStreamDataService', function ($rootScope, notifyService, userService, customStreamDataService) {\r\n return {\r\n link: function (scope, element, attrs) {\r\n\r\n\r\n scope.$on('initial', function (event, data) {\r\n var l_objCurrentUser = userService.getCurrentUser();\r\n\r\n if (l_objCurrentUser.type == 1 || l_objCurrentUser.type == 2) {\r\n element.bind('click', function () {\r\n $rootScope.$broadcast('LoadAdminStreamModal');\r\n });\r\n\r\n element.css('display', 'block');\r\n\r\n }\r\n })\r\n\r\n }\r\n };\r\n }])\r\n\r\n .directive('streamUserButton', ['streamDataService', '$rootScope', '$window', 'notifyService', 'userService', 'chatRoomService', function (streamDataService, $rootScope, $window, notifyService, userService, chatRoomService) {\r\n return {\r\n scope: {\r\n mobile: '@',\r\n },\r\n link: function (scope, element, attrs) {\r\n\r\n scope.$on('ChangeRoom', _streamChanged);\r\n scope.$on('StartStream', _streamChanged);\r\n scope.$on('StopStream', _streamChanged);\r\n\r\n _streamChanged();\r\n\r\n function _streamChanged() {\r\n\r\n scope.l_blnLive = streamDataService.l_blnLive;\r\n\r\n if (scope.l_blnLive) {\r\n element.addClass(\"btnLiveActive\");\r\n } else {\r\n element.removeClass(\"btnLiveActive\");\r\n $('#vidModal').remove();\r\n }\r\n }\r\n\r\n element.bind(\"click\", function () {\r\n\r\n streamDataService.checkStream().then(function (response) {\r\n\r\n if (window.streamPopup) {\r\n window.streamPopup.close()\r\n }\r\n\r\n // console.log('checkStream', response);\r\n if (response.success) {\r\n scope.l_strVideo = streamDataService.l_strVideoId || \"\";\r\n scope.l_strVideo = response.data;\r\n if (scope.mobile != null && scope.mobile == \"1\") {\r\n $window.open('https://www.youtube.com/watch?v=' + scope.l_strVideo, '_blank');\r\n } else {\r\n // console.log('LoadVidboxWidgetModal', {\r\n // videoId: scope.l_strVideo,\r\n // message1: \"No feed available\",\r\n // broadcaster: response.data.broadcaster\r\n //});\r\n $rootScope.$broadcast('LoadVidboxWidgetModal', {\r\n videoId: scope.l_strVideo,\r\n message1: \"No feed available\",\r\n broadcaster: response.data.broadcaster\r\n });\r\n }\r\n } else {\r\n if (response.data && response.data.stream) {\r\n var l_strNames = '';\r\n for (var i = 0; i < response.data.rooms.length; i++) {\r\n l_strNames += response.data.rooms[i].s_name + ' ';\r\n }\r\n $rootScope.$broadcast('LoadVidboxWidgetModal', {\r\n message1: \"This feed is unavailable for you.\",\r\n message2: \"To gain access, unlock any of the following chatrooms: \" + l_strNames\r\n });\r\n } else if (response.data && response.data.upgradeUrl) {\r\n $rootScope.$broadcast('LoadVidboxWidgetModal', {\r\n message1: \"This feed is unavailable for you.\",\r\n upgradeUrl: response.data.upgradeUrl\r\n });\r\n } else {\r\n $rootScope.$broadcast('LoadVidboxWidgetModal', {\r\n message1: \"No feed available\"\r\n });\r\n }\r\n }\r\n });\r\n\r\n })\r\n\r\n }\r\n };\r\n }])\r\n\r\n .directive('streamUserLink', ['streamDataService', '$rootScope', '$window', 'notifyService', 'userService', 'chatRoomService', function (streamDataService, $rootScope, $window, notifyService, userService, chatRoomService) {\r\n return {\r\n scope: {\r\n mobile: '@',\r\n },\r\n link: function (scope, element, attrs) {\r\n element.bind(\"click\", function () {\r\n\r\n streamDataService.checkStream().then(function (response) {\r\n // console.log(response);\r\n if (response.success) {\r\n scope.l_strVideo = streamDataService.l_strVideoId || \"\";\r\n scope.l_strVideo = response.data.videoId;\r\n if (scope.mobile != null && scope.mobile == \"1\") {\r\n $window.open('https://www.youtube.com/watch?v=' + scope.l_strVideo, '_blank');\r\n } else {\r\n $rootScope.$broadcast('LoadVidboxWidgetModal', {\r\n videoId: scope.l_strVideo,\r\n message1: \"No feed available\",\r\n type: response.data.type\r\n });\r\n }\r\n } else {\r\n if (response.data && response.data.stream) {\r\n var l_strNames = '';\r\n for (var i = 0; i < response.data.rooms.length; i++) {\r\n l_strNames += response.data.rooms[i].s_name + ' ';\r\n }\r\n $rootScope.$broadcast('LoadVidboxWidgetModal', {\r\n message1: \"This feed is for Premium users only.\",\r\n message2: \"Unlock any of the following rooms to gain access: \" + l_strNames\r\n\r\n });\r\n } else {\r\n $rootScope.$broadcast('LoadVidboxWidgetModal', {\r\n message1: \"No feed available\"\r\n });\r\n }\r\n }\r\n });\r\n\r\n })\r\n\r\n }\r\n };\r\n }])\r\n\r\n .controller('streamModalAdminCtrl', ['$http', '$scope', '$filter', 'streamDataService', 'notifyService', 'chatRoomService', 'userService', 'customStreamDataService', 'streamValuesDataService',\r\n function ($http, $scope, $filter, streamDataService, notifyService, chatRoomService, userService, customStreamDataService, streamValuesDataService) {\r\n\r\n var l_strVideo = null;\r\n var _avatarFile = null;\r\n var interval;\r\n\r\n $scope.txtUrl = '';\r\n $scope.b_live = false;\r\n $scope.pluginInstalled = false;\r\n $scope.rooms = [];\r\n $scope.custom = {\r\n devices: null,\r\n camera_res: [{\r\n \"id\": \"3\",\r\n \"label\": \"720p (1280x720)\",\r\n \"width\": 1280,\r\n \"height\": 720,\r\n \"ratio\": \"16:9\"\r\n }, {\r\n \"id\": \"2\",\r\n \"label\": \"VGA (640x480)\",\r\n \"width\": 640,\r\n \"height\": 480,\r\n \"ratio\": \"4:3\"\r\n }, {\r\n \"id\": \"1\",\r\n \"label\": \"QVGA (320x240)\",\r\n \"width\": 320,\r\n \"height\": 240,\r\n \"ratio\": \"4:3\"\r\n }],\r\n share_res: [{\r\n \"id\": \"3\",\r\n \"label\": \"HD\",\r\n \"width\": 1920,\r\n \"height\": 1080,\r\n \"ratio\": \"16:9\"\r\n }, {\r\n \"id\": \"2\",\r\n \"label\": \"High\",\r\n \"width\": 720,\r\n \"height\": 480,\r\n \"ratio\": \"16:9\"\r\n }, {\r\n \"id\": \"1\",\r\n \"label\": \"Standard\",\r\n \"width\": 640,\r\n \"height\": 480,\r\n \"ratio\": \"4:3\"\r\n }],\r\n camera_res_val: \"3\",\r\n share_res_val: \"3\",\r\n selectedv: streamValuesDataService.getSelectedVideo(),\r\n selecteda: streamValuesDataService.getSelectedAudio()\r\n };\r\n $scope.isLoading = false;\r\n\r\n $scope.suggestedLinks = [{\r\n url: \"https://www.youtube.com/watch?v=Ga3maNZ0x0w\",\r\n label: \"Bloomberg\"\r\n },\r\n //{ url: \"https://www.youtube.com/watch?v=01bdxGe2b0Y\", label: \"MSNBC\" },\r\n {\r\n url: \"https://www.youtube.com/watch?v=Ah04R0okNbQ\",\r\n label: \"euronews\"\r\n },\r\n //{ url: \"https://www.youtube.com/watch?v=mqafQVNkyN4\", label: \"Sky News\" },\r\n {\r\n url: \"https://www.youtube.com/watch?v=HXeGpCFGu-k\",\r\n label: \"BBC UK\"\r\n },\r\n {\r\n url: \"https://www.youtube.com/watch?v=nVHt1_SWTZg\",\r\n label: \"Al Jazeera English\"\r\n },\r\n ]\r\n\r\n $scope.ChangeSelection = function (a) {\r\n // console.log('change to ' + a);\r\n\r\n if (a == 1000) {\r\n checkScreenSharePlugin();\r\n } else {\r\n\r\n }\r\n }\r\n\r\n $scope.setTxtUrl = function (link) {\r\n if ($scope.isStarted == true) {\r\n return\r\n }\r\n $scope.txtUrl = link\r\n }\r\n\r\n $scope.isRoomPremiumOrPrivate = function () {\r\n return function (room) {\r\n return room.n_type === 2 || room.n_type === 5;\r\n };\r\n };\r\n\r\n var checkScreenSharePlugin = function () {\r\n if (customStreamDataService.Browser.isFirefox()) {\r\n //$(\"#installExtensionButton\").show();\r\n //interval = setInterval(function () {\r\n // if (Flashphoner.firefoxScreenSharingExtensionInstalled) {\r\n // $(\"#extension\").hide();\r\n // $(\"#installExtensionButton\").hide();\r\n // clearInterval(interval);\r\n // onExtensionAvailable();\r\n // }\r\n //}, 500);\r\n } else if (customStreamDataService.Browser.isChrome()) {\r\n interval = setInterval(function () {\r\n var screenSharingExtensionId = (window.location.host.indexOf(\".dev.\") !== -1 || window.location.host.indexOf(\"localhost\") !== -1) ?\r\n customStreamDataService.extensionIdDev :\r\n customStreamDataService.extensionId\r\n\r\n chrome.runtime.sendMessage(screenSharingExtensionId, {\r\n type: \"isInstalled\"\r\n }, function (response) {\r\n // console.log('chrome.runtime.sendMessage', response);\r\n if (response) {\r\n clearInterval(interval);\r\n $scope.pluginInstalled = true;\r\n $scope.$apply();\r\n } else {\r\n $scope.pluginInstalled = false;\r\n }\r\n });\r\n }, 500);\r\n\r\n }\r\n }\r\n\r\n var getConstraints = function () {\r\n var constraints = {};\r\n if ($scope.custom.selectedv == '') {\r\n //no video\r\n constraints.video = false;\r\n } else {\r\n var l_objSelectedRes = getSelectedObject($scope.custom.camera_res, $scope.custom.camera_res_val);\r\n\r\n constraints.video = {\r\n deviceId: $scope.custom.selectedv,\r\n frameRate: 10,\r\n width: l_objSelectedRes.width,\r\n height: l_objSelectedRes.height,\r\n //type: \"screen\",\r\n quality: 100\r\n }\r\n // console.log('l_objSelectedRes', $scope.custom.camera_res, $scope.custom.camera_res_val, l_objSelectedRes, constraints.video);\r\n\r\n }\r\n // console.log('selecteda', $scope.custom.selecteda);\r\n if ($scope.custom.selecteda == '') {\r\n constraints.audio = false;\r\n } else {\r\n constraints.audio = {\r\n deviceId: $scope.custom.selecteda\r\n }\r\n }\r\n // console.log('selecteda after', $scope.custom);\r\n\r\n return constraints;\r\n }\r\n\r\n var getScreenShareConstraints = function () {\r\n var constraints = {};\r\n if ($scope.custom.selectedv == '') {\r\n //no video\r\n constraints.video = false;\r\n } else {\r\n var l_objSelectedRes = getSelectedObject($scope.custom.share_res, $scope.custom.share_res_val);\r\n\r\n constraints.video = {\r\n width: l_objSelectedRes.width,\r\n height: l_objSelectedRes.height,\r\n frameRate: 10,\r\n \"type\": \"screen\",\r\n quality: 100\r\n }\r\n }\r\n\r\n if ($scope.custom.selecteda == '') {\r\n constraints.audio = false;\r\n } else {\r\n constraints.audio = {\r\n deviceId: $scope.custom.selecteda\r\n }\r\n }\r\n // console.log('selecteda after', $scope.custom);\r\n //constraints.video.type= 'screen';\r\n // console.log('getScreenShareConstraints', constraints, constraints.video, constraints.video[\"type\"]);\r\n return constraints;\r\n }\r\n\r\n var getSelectedObject = function (a_objColl, a_strSelectedId) {\r\n for (var i = 0; i < a_objColl.length; i++) {\r\n if (a_objColl[i].id == a_strSelectedId)\r\n return a_objColl[i];\r\n }\r\n }\r\n\r\n $scope.$on('LoadAdminStreamModal', function (event, data) {\r\n\r\n $scope.teamName = userService.getTeamProperties().s_name\r\n\r\n $scope.hasWarnForScreenShare = (window.location.host.indexOf(\".echofin.co\") === -1 || window.isDesktopClient)\r\n\r\n $scope.rooms = chatRoomService.getAll();\r\n customStreamDataService.getDevices().then(function (a_objResponse) {\r\n // console.log('get devices', a_objResponse);\r\n console.log('devices1', a_objResponse);\r\n $scope.custom.devices = a_objResponse;\r\n if (streamValuesDataService.getSelectedVideo() == '' && a_objResponse.video.length > 0) {\r\n $scope.custom.selectedv = a_objResponse.video[0].id;\r\n \r\n console.log(\"length more than 0\", a_objResponse.video[0].id, a_objResponse.video);\r\n } else {\r\n $scope.custom.selectedv = streamValuesDataService.getSelectedVideo();\r\n console.log(\"already selected\", $scope.custom.selectedv);\r\n }\r\n $scope.custom.selecteda = streamValuesDataService.getSelectedAudio();\r\n });\r\n\r\n streamDataService.getStream().then(function (response) {\r\n var data = response.data;\r\n if (data != null) {\r\n // console.log('LoadStreamModal', data);\r\n if (data.type == 1) {\r\n $scope.txtUrl = data.s_streamUrl;\r\n $scope.custom.selectedv = \"2000\";\r\n }\r\n $scope.isStarted = data.b_live;\r\n for (var s = 0; s < $scope.rooms.length; s++) {\r\n $scope.rooms[s].b_selected = false;\r\n }\r\n for (var i = 0; i < data.room.length; i++) {\r\n for (var s = 0; s < $scope.rooms.length; s++) {\r\n if (data.room[i] == $scope.rooms[s].s_clearKey) {\r\n $scope.rooms[s].b_selected = true;\r\n }\r\n }\r\n }\r\n };\r\n $('#streamModalAdmin').modal('show');\r\n });\r\n });\r\n\r\n $scope.Start = function () {\r\n var l_objCurrentUser = userService.getCurrentUser();\r\n\r\n if (l_objCurrentUser.type != 1 && l_objCurrentUser.type != 2)\r\n return;\r\n\r\n streamValuesDataService.setSelectedAudio($scope.custom.selecteda)\r\n streamValuesDataService.setSelectedVideo($scope.custom.selectedv)\r\n var selectedRooms = '';\r\n for (var i = 0; i < $scope.rooms.length; i++) {\r\n if ($scope.rooms[i].b_selected) {\r\n selectedRooms = selectedRooms + $scope.rooms[i].s_clearKey + ',';\r\n }\r\n };\r\n\r\n if ($scope.custom.selectedv == 2000 || $scope.custom.selectedv == '2000' || $scope.custom.selectedv == \"2000\") {\r\n streamDataService.startStream({\r\n url: $scope.txtUrl,\r\n selected: selectedRooms\r\n }).then(function (a) {\r\n if (a.success) {\r\n $('#streamModalAdmin').modal('hide');\r\n } else {\r\n notifyService.error(a.error)\r\n }\r\n });\r\n\r\n } else if ($scope.custom.selectedv == 1000 || $scope.custom.selectedv == '1000') {\r\n $scope.isLoading = true;\r\n var l_strCompanyKey = userService.getTeamProperties().s_key;\r\n\r\n $http.get(\"api/stream/close\")\r\n .success(function (a_data, status, headers, config) {\r\n\r\n customStreamDataService.stopStream();\r\n var l_objScreenShare = getScreenShareConstraints();\r\n customStreamDataService.initShareScreen(l_strCompanyKey, window.streamServerUrl + l_strCompanyKey, document.getElementById('localVideo'), l_objScreenShare)\r\n .then(function (a_objStream) {\r\n $scope.isStarted = true;\r\n $('#streamModalAdmin').modal('hide');\r\n\r\n streamDataService.startStream({\r\n url: window.streamServerUrl + l_strCompanyKey,\r\n selected: selectedRooms,\r\n type: 'screen'\r\n }).then(function (a) {\r\n if (a.success) {\r\n customStreamDataService.registerCloseButton();\r\n } else {\r\n notifyService.error(a.error)\r\n }\r\n $scope.isLoading = false;\r\n });\r\n window.onbeforeunload = function () {\r\n return \"You are broadcasting live, if you leave the stream will be stopped!\";\r\n }\r\n\r\n $scope.isLoading = false;\r\n }, function (a_objError) {\r\n // console.log('error', a_objError);\r\n $scope.isLoading = false;\r\n\r\n });\r\n\r\n })\r\n } else {\r\n $scope.isLoading = true;\r\n var l_strCompanyKey = userService.getTeamProperties().s_key;\r\n // console.log('startStream', getConstraints());\r\n //customStreamDataService.nativeTest();\r\n //$scope.isLoading = false;\r\n\r\n $http.get(\"api/stream/close\")\r\n .success(function (a_data, status, headers, config) {\r\n customStreamDataService.stopStream();\r\n setTimeout(function () {\r\n customStreamDataService.initStream(l_strCompanyKey, window.streamServerUrl + l_strCompanyKey,\r\n document.getElementById('localVideo'), getConstraints()).then(function (a_objStream) {\r\n\r\n $scope.isStarted = true;\r\n $('#streamModalAdmin').modal('hide');\r\n\r\n streamDataService.startStream({\r\n url: window.streamServerUrl + l_strCompanyKey,\r\n selected: selectedRooms,\r\n type: 'webcam'\r\n }).then(function (a) {\r\n if (a.success) {\r\n\r\n } else {\r\n notifyService.error(a.error)\r\n }\r\n $scope.isLoading = false;\r\n });\r\n window.onbeforeunload = function () {\r\n return \"You are broadcasting live, if you leave the stream will be stopped!\";\r\n }\r\n\r\n\r\n }).then(function () {\r\n $scope.isLoading = false;\r\n\r\n });\r\n }, 1000)\r\n });\r\n\r\n }\r\n\r\n };\r\n\r\n $scope.Stop = function () {\r\n\r\n var l_objCurrentUser = userService.getCurrentUser();\r\n\r\n if (l_objCurrentUser.type != 1 && l_objCurrentUser.type != 2) {\r\n $('#vidboxModal').modal('hide');\r\n return;\r\n }\r\n\r\n switch ($scope.custom.selectedv) {\r\n case '2000': //youtube\r\n streamDataService.stopStream({\r\n url: $scope.txtUrl\r\n }).then(function (a) {\r\n if (a.success) {\r\n $scope.isStarted = false;\r\n //$('#streamModalAdmin').modal('hide');\r\n } else {\r\n notifyService.error(a.error)\r\n };\r\n });\r\n break;\r\n case '1000': //Screen Share\r\n window.onbeforeunload = null;\r\n streamDataService.stopStream({\r\n url: $scope.txtUrl\r\n }).then(function (a_objResponse) {\r\n if (a_objResponse.success) {\r\n customStreamDataService.stopStream(document.getElementById('localVideo'));\r\n $scope.isStarted = false;\r\n //$('#streamModalAdmin').modal('hide');\r\n } else {\r\n notifyService.error(a_objResponse.error)\r\n };\r\n });\r\n customStreamDataService.setBroadcaster(false);\r\n break;\r\n default: //WebCam\r\n window.onbeforeunload = null;\r\n streamDataService.stopStream({\r\n url: $scope.txtUrl\r\n }).then(function (a_objResponse) {\r\n if (a_objResponse.success) {\r\n customStreamDataService.stopStream(document.getElementById('localVideo'));\r\n $scope.isStarted = false;\r\n //$('#streamModalAdmin').modal('hide');\r\n } else {\r\n notifyService.error(a_objResponse.error)\r\n };\r\n });\r\n customStreamDataService.setBroadcaster(false);\r\n break;\r\n }\r\n }\r\n\r\n $scope.$on('SessionStatusChange', function (event, data) {\r\n // console.log('SessionStatusChange', data);\r\n if (data == 'DISCONNECTED') {\r\n $scope.Stop();\r\n var l_objModal = $('#connErrorModal');\r\n l_objModal.css('top', '100px');\r\n l_objModal.modal('show');\r\n\r\n }\r\n });\r\n }\r\n ])","'use strict';\r\n\r\nangular\r\n .module('chat.settings', [\r\n 'chat.user'\r\n ])\r\n .directive('settingsMenu', settingsMenu)\r\n .directive('settingsModal', settingsModal)\r\n .controller('settingsModalCtrl', settingsModalCtrl)\r\n\r\nsettingsMenu.$inject = ['userService']\r\n\r\nfunction settingsMenu(userService) {\r\n return {\r\n link: function (scope, element, attrs) {\r\n scope.activeMenu = 1;\r\n scope.select = function (a_intSelection) {\r\n scope.activeMenu = a_intSelection;\r\n }\r\n }\r\n }\r\n}\r\n\r\nfunction settingsModal() {\r\n return {\r\n templateUrl: 'settings-modal.html',\r\n controller: \"settingsModalCtrl\",\r\n link: function (scope, element, attrs) {}\r\n }\r\n}\r\n\r\nsettingsModalCtrl.$inject = ['$scope', 'userService', 'chatRoomService', 'notifyService']\r\n\r\nfunction settingsModalCtrl($scope, userService, chatRoomService, notifyService) {\r\n var _avatarFile = null;\r\n $scope.userDateformat = [];\r\n $scope.userSubscriptions = [];\r\n $scope.billingPreview = false;\r\n Dropzone.autoDiscover = false;\r\n\r\n $(\"#uploadAvatar\").dropzone({\r\n url: \"http://www.torrentplease.com/dropzone.php\",\r\n clickable: '#btnAvatarUpload',\r\n paramName: \"file\",\r\n maxFilesize: 500,\r\n uploadMultiple: false,\r\n thumbnailWidth: \"150\",\r\n thumbnailHeight: \"150\",\r\n acceptedMimeTypes: \"image/*,image/gif\",\r\n previewTemplate: '
',\r\n accept: function (file, done) {\r\n // console.log('dropzone accept', file, done);\r\n _avatarFile = file;\r\n },\r\n thumbnail: function (file, dataUrl) {\r\n // console.log('dropzone thumbnail', file, dataUrl);\r\n $(\"#imgAvatarThumb\").attr('src', dataUrl);\r\n }\r\n });\r\n\r\n $(\"#btnAvatarReset\").click(function () {\r\n userService.getUserDefaultAvatar($scope.txtFullname).then(function (data) {\r\n // console.log('sidebar btnAvatarReset', data);\r\n $(\"#imgAvatarThumb\").attr('src', 'data:image/png;base64,' + data);\r\n _avatarFile = {\r\n name: 'generated'\r\n }\r\n })\r\n });\r\n\r\n $scope.$on('LoadSettingsModal', function (event, data) {\r\n // console.log('Sidebar LoadSettings', userService.getUserFullname(), userService.getUserTimezone());\r\n // console.log(userService.getSettings().notifications);\r\n var l_objUser = userService.getCurrentUser();\r\n var l_objSettings = userService.getSettings();\r\n var l_objTeamProperties = userService.getTeamProperties();\r\n\r\n if (l_objTeamProperties.s_key != '875960cc') {\r\n $scope.enableChangeBillingDetails = true\r\n } else {\r\n $scope.enableChangeBillingDetails = false\r\n }\r\n\r\n $scope.billingPreview = l_objTeamProperties.b_enableBillingPreview;\r\n userService.getUserSubscriptions().then(function (response) {\r\n if (response.success) {\r\n $scope.userSubscriptions = response.data;\r\n }\r\n });\r\n $scope.CalcelSub = function (id) {\r\n if (id != null) {\r\n notifyService.confirmCustom('You will not be charged again. Your access will remain active until the end of the current billing period.', function () {\r\n\r\n userService.cancelUserSubscription(id).then(function (response) {\r\n if (response.success) {\r\n userService.getUserSubscriptions().then(function (response) {\r\n if (response.success) {\r\n $scope.userSubscriptions = response.data;\r\n }\r\n });\r\n }\r\n });\r\n }, function () {\r\n\r\n }, \"Cancel Billing\", \"Nevermind\");\r\n\r\n }\r\n };\r\n\r\n $scope.userKey = l_objUser.s_clearkey;\r\n $scope.chkDirect = l_objSettings.notifications.notifyDMs;\r\n $scope.chkAll = l_objSettings.notifications.notifyRooms;\r\n $scope.chkMentions = l_objSettings.notifications.notifyMentions;\r\n $scope.chkAllowFree = l_objSettings.allowFree;\r\n $scope.chkNotifyFromAdmins = l_objSettings.notifications.notifyFromAdmins\r\n $scope.testSpin = false\r\n\r\n var _userRoomProperties = userService.getUserRoomProperties()\r\n $scope.settingRooms = _.chain(chatRoomService.getAll())\r\n .filter(function (room) {\r\n return room.n_type == 1 || room.n_type == 2 || room.n_type == 5\r\n })\r\n .sortBy(\"n_sort\")\r\n .map(function (room) {\r\n room.hasAccess = room.haveAccessToRoom\r\n room.enableNotification = false\r\n\r\n var roomProp = _.find(_userRoomProperties, function (rp) {\r\n return rp.s_key == room.s_clearKey\r\n })\r\n if (roomProp) {\r\n let hasAccess = (room.type == 5) ? roomProp.b_allow : room.hasAccess\r\n room.enableNotification = (hasAccess) ? roomProp.b_notifications : false\r\n room.hasAccess = hasAccess\r\n }\r\n\r\n return room\r\n\r\n })\r\n .value()\r\n\r\n $scope.txtFullname = userService.getUserFullname();\r\n $scope.txtUsername = l_objUser.userName;\r\n $scope.userDateFormat = userService.getUserDateFormat();\r\n $scope.isStripeCustomer = l_objSettings.isStripeCustomer;\r\n $scope.isAdmin = (l_objUser.type == 1);\r\n $scope.isSpecial = (l_objUser.type == 1) || (l_objUser.type == 2) || (l_objUser.type == 3); //any type above user\r\n\r\n $('#settingsModal').modal('show');\r\n // $('#settingsModal').css('top', '100px');\r\n //$('.modal-backdrop').css('z-index', '1000');\r\n //$('.modal-backdrop').css('display', 'none');\r\n $(\"#imgAvatarThumb\").attr('src', userService.getCurrentUser().s_avatar);\r\n\r\n $('[data-toggle=\"tooltip\"]').tooltip()\r\n\r\n loadBlockBanLists();\r\n\r\n setTimeout(function () {\r\n userService.getTimezones().then(function (data) {\r\n $scope.timezones = data;\r\n $scope.userTimezone = userService.getUserTimezone();\r\n // console.log('LoadSettings', data, $scope.userTimezone);\r\n })\r\n }, 1000)\r\n });\r\n\r\n $scope.SaveSettings = function (a) {\r\n var postObj = {\r\n name: $scope.txtFullname,\r\n timezone: $scope.userTimezone,\r\n dateFormat: $scope.userDateFormat,\r\n notifyDMs: $scope.chkDirect,\r\n notifyRooms: $scope.chkAll,\r\n notifyMentions: $scope.chkMentions,\r\n allowFree: $scope.chkAllowFree,\r\n notifyFromAdmins: $scope.chkNotifyFromAdmins,\r\n };\r\n if (_avatarFile) {\r\n postObj.avatarData = $(\"#imgAvatarThumb\").attr('src');\r\n postObj.avatarFilename = _avatarFile.name;\r\n };\r\n // console.log('SaveSettings', postObj);\r\n userService.updateUserSettings(postObj);\r\n\r\n var postNotifObj = {\r\n isNotifyDirect: $scope.chkDirect,\r\n isNotifyMentions: $scope.chkMentions,\r\n isNotifyRooms: $scope.chkAll,\r\n notifyRoomsList: _.chain($scope.settingRooms)\r\n .filter(function (room) {\r\n return room.hasAccess\r\n })\r\n .reduce(function (hash, value) {\r\n var key = value['s_clearKey']\r\n hash[key] = value['enableNotification']\r\n return hash\r\n }, {})\r\n .value(),\r\n }\r\n userService.updateUserNotificationSettings(postNotifObj);\r\n\r\n $('#settingsModal').modal('hide');\r\n $('.modal-backdrop').css('display', 'block');\r\n\r\n };\r\n\r\n $scope.userRemoveBlock = function (a_objBlock) {\r\n\r\n userService\r\n .unblockUser({\r\n userKey: a_objBlock.s_key\r\n })\r\n .then(function () {\r\n loadBlockBanLists()\r\n });\r\n }\r\n\r\n $scope.userRemoveMute = function (a_objMute) {\r\n\r\n userService\r\n .unmuteUser({\r\n userKey: a_objMute.userKey,\r\n roomKey: a_objMute.roomKey\r\n })\r\n .then(function () {\r\n loadBlockBanLists()\r\n });\r\n }\r\n\r\n $scope.userRemoveBan = function (a_objBan) {\r\n\r\n userService\r\n .unbanUser({\r\n userKey: a_objBan.s_key\r\n })\r\n .then(function () {\r\n loadBlockBanLists()\r\n });\r\n\r\n }\r\n\r\n function loadBlockBanLists() {\r\n\r\n\r\n $scope.objBlockedUsers = [];\r\n $scope.objMutedUsers = [];\r\n $scope.objBannedUsers = [];\r\n\r\n userService.getAll().forEach(function (l_objUser) {\r\n if (l_objUser.isBanned) {\r\n $scope.objBannedUsers.push(l_objUser);\r\n }\r\n if (l_objUser.isBlocked) {\r\n $scope.objBlockedUsers.push(l_objUser);\r\n }\r\n })\r\n\r\n userService.getAllMuted().forEach(function (a_objUser) {\r\n\r\n var l_objRoom = null;\r\n var l_objUser = null;\r\n chatRoomService\r\n .getAll()\r\n .forEach(function (room) {\r\n if (room.s_key.indexOf(a_objUser.roomKey) != -1) {\r\n l_objRoom = room;\r\n }\r\n })\r\n userService\r\n .getAll()\r\n .forEach(function (user) {\r\n if (user.s_key.indexOf(a_objUser.userKey) != -1) {\r\n l_objUser = user;\r\n }\r\n })\r\n $scope.objMutedUsers.push({\r\n roomKey: a_objUser.roomKey,\r\n userKey: a_objUser.userKey,\r\n room: l_objRoom,\r\n user: l_objUser,\r\n });\r\n });\r\n }\r\n\r\n\r\n}","'use strict';\r\n\r\nangular\r\n .module('chat.payment', [\r\n 'chat.user',\r\n 'chat.room',\r\n 'chat.error'\r\n ])\r\n .service('paymentData', paymentData)\r\n .directive('paymentModal', paymentModal)\r\n .controller('paymentModalCtrl', paymentModalCtrl)\r\n .directive('bootTip', [function () {\r\n return {\r\n scope: {\r\n tiptitle: '@'\r\n },\r\n link: function (scope, element, attrs) {\r\n\r\n scope.$watch(\"tiptitle\", function (newValue, oldValue) {\r\n $(element).tooltip('destroy')\r\n attrs.$set('title', scope.tiptitle);\r\n if (scope.tiptitle != null && scope.tiptitle != '')\r\n $(element).tooltip();\r\n // console.log('bootTip link', scope.tiptitle);\r\n }, true);\r\n }\r\n }\r\n }]);\r\n\r\npaymentData.$inject = ['$http', '$q'];\r\n\r\nfunction paymentData($http, $q) {\r\n\r\n var url = {\r\n paymentData: 'api/payment',\r\n };\r\n\r\n var _service = {\r\n stripeLoaded: false,\r\n initPaymentData: _initPaymentData,\r\n getPaymentData: _getPaymentData,\r\n getStripeToken: _getStripeToken,\r\n submitPayment: _submitPayment\r\n\r\n }\r\n\r\n function _initPaymentData() {\r\n Stripe.setPublishableKey(window.l_strStripePublicKey);\r\n _service.stripeLoaded = true;\r\n // console.debug(\"Stripe initialized with key:\", window.l_strStripePublicKey)\r\n }\r\n\r\n\r\n function _getPaymentData(id) {\r\n var deferred = $q.defer();\r\n $http.get(url.paymentData + '/' + id)\r\n .success(function (a_data, status, headers, config) {\r\n deferred.resolve(a_data);\r\n })\r\n .error(function (data, status, headers, config) {\r\n notifyService.showError(\"Get Data \", 'error ' + status + ' get ' + url.paymentData);\r\n deferred.reject();\r\n });\r\n\r\n return deferred.promise;\r\n };\r\n\r\n function _submitPayment(a_objSettings) {\r\n var deferred = $q.defer();\r\n $http.post(url.paymentData,\r\n JSON.stringify(a_objSettings), {\r\n headers: {\r\n 'Content-Type': 'application/json'\r\n }\r\n }\r\n )\r\n .success(function (a_data, status, headers, config) {\r\n deferred.resolve(a_data);\r\n })\r\n .error(function (data, status, headers, config) {\r\n //notifyService.showError(\"Get Data \", 'error ' + status + ' get ' + url.updateUserSettings);\r\n deferred.reject();\r\n });\r\n\r\n return deferred.promise;\r\n };\r\n\r\n function _getStripeToken(a_objCreditCardData, a_haveChild) {\r\n var d = $q.defer();\r\n Stripe.card.createToken(a_objCreditCardData, function (status, response) {\r\n if (response.error)\r\n d.reject(response);\r\n else {\r\n if (a_haveChild) {\r\n Stripe.card.createToken(a_objCreditCardData, function (status, response1) {\r\n if (response1.error) {\r\n d.reject(response1);\r\n } else {\r\n d.resolve([response, response1]);\r\n }\r\n });\r\n } else {\r\n d.resolve([response]);\r\n }\r\n }\r\n });\r\n return d.promise;\r\n\r\n };\r\n\r\n return _service\r\n}\r\n\r\npaymentModalCtrl.$inject = ['$interval', '$scope', '$window', '$route', '$location', 'userService', 'paymentData', 'chatRoomService', 'notifyService', 'messageService', 'AppError', '$sce']\r\n\r\nfunction paymentModalCtrl($interval, $scope, $window, $route, $location, userService, paymentData, chatRoomService, notifyService, messageService, AppError, $sce) {\r\n var l_objModal = $('#payment-modal');\r\n var l_arrErrors = [];\r\n var l_intType = 1;\r\n $scope.formData = {\r\n cardName: null,\r\n address: null,\r\n postCode: null,\r\n city: null,\r\n country: null,\r\n cardNumber: null,\r\n month: null,\r\n year: null,\r\n ccv: null,\r\n planKey: null,\r\n stripeId: null,\r\n cardId: null,\r\n roomKey: null,\r\n errors: null\r\n };\r\n $scope.haveChild = false;\r\n $scope.nocardtrial = false;\r\n\r\n $scope.isPaymentsEnabled = true;\r\n $scope.$on('initial', function (event, data) {\r\n var l_strTeamKey = userService.getTeamProperties().s_key;\r\n if (l_strTeamKey == 'b7e64405') {// || l_strTeamKey == '450d9432') { // jesus\r\n $scope.isPaymentsEnabled = false;\r\n }\r\n })\r\n\r\n l_objModal.css('top', '100px');\r\n\r\n l_objModal.on('hidden.bs.modal', function () {\r\n\r\n if ($scope.interv) {\r\n $interval.cancel($scope.interv);\r\n }\r\n\r\n if ($scope.progress == 'success') {\r\n location.reload();\r\n return;\r\n }\r\n if (l_intType == 1) {\r\n $window.history.back();\r\n }\r\n\r\n //chatRoomService.getDefaul\r\n\r\n });\r\n\r\n $scope.$on('LoadPayment', function (event, model) {\r\n var data = model.chatroom,\r\n config = model.config;\r\n if (model.config.type == null)\r\n l_intType = 1;\r\n else\r\n l_intType = model.config.type;\r\n //console.log('LoadPayment model', model);\r\n $scope.paymentTitle = null;\r\n $scope.progress = false;\r\n $scope.quickPay = false;\r\n $scope.doReportConvertion = false;\r\n $scope.isTrial = false;\r\n $scope.pDescr = null;\r\n\r\n $scope.ChangeDetailsForm = function () {\r\n $scope.quickPay = false;\r\n // console.log('alala0');\r\n }\r\n if (!data.s_key) {\r\n return; //return if we don't have a key \r\n }\r\n\r\n if (data.s_key && data.s_key.substring(0, 10) == 'private-r-') {\r\n return; //private rooms - no payment\r\n }\r\n\r\n if (data.s_key && (data.s_key.substring(0, 8) == 'private-' || data.s_key.substring(0, 7) == 'hyphen-' || data.s_key.substring(0, 7) == 'widget-') && data.s_key.substring(0, 10) != 'private-u-') {\r\n $scope.planData = {};\r\n\r\n if (l_blnDebug) {\r\n $scope.formData = {\r\n cardName: 'test1',\r\n address: 'test address',\r\n postCode: '12345',\r\n city: 'testCity',\r\n country: 1,\r\n cardNumber: '4242424242424242',\r\n month: '1',\r\n year: '2020',\r\n ccv: '123',\r\n planKey: null,\r\n stripeId: null,\r\n cardId: null,\r\n roomKey: null,\r\n errors: null\r\n };\r\n } else {\r\n $scope.formData = {}\r\n }\r\n\r\n\r\n $scope.chatRoom = data;\r\n // console.log(data.chatRoom);\r\n $scope.formData.roomKey = $scope.chatRoom.s_key;\r\n\r\n paymentData.getPaymentData($scope.formData.roomKey.replace('private-', '').replace('hyphen-', '').replace('widget-', '')).then(function (a_objData) {\r\n // console.log('getPaymentData', a_objData);\r\n $scope.quickPay = a_objData.data.isStripe;\r\n $scope.nocardtrial = a_objData.data.nocardtrial;\r\n $scope.isTrial = a_objData.data.nocardtrial;\r\n if (a_objData.data.plan) {\r\n $scope.formData.planKey = a_objData.data.plan.key;\r\n $scope.planData = a_objData.data.plan;\r\n $scope.planRooms = a_objData.data.rooms;\r\n $scope.paymentTitle = a_objData.data.title;\r\n $scope.pDescr = a_objData.data.plan.description;\r\n // console.log('getPaymentData', a_objData.data, $scope.pDescr);\r\n\r\n } else {\r\n l_arrErrors.push(\"No valid plan assigned\");\r\n $scope.formData.errors = l_arrErrors;\r\n //$scope.inProgress = true;\r\n }\r\n $scope.countries = a_objData.data.countries;\r\n $scope.haveChild = a_objData.data.haveChild;\r\n if (window.mixpanel)\r\n mixpanel.track(\"billing-form\", {\r\n \"Room Name\": $scope.chatRoom.s_url,\r\n \"Billing Plan\": $scope.paymentTitle,\r\n });\r\n\r\n });\r\n\r\n //$scope.progress = 'pending';\r\n if (config.data) {\r\n if (config.data.havePendingSubscriptions) {\r\n startCheckPayment()\r\n }\r\n }\r\n\r\n l_objModal.modal('show');\r\n\r\n\r\n } else {\r\n l_objModal.modal('hide');\r\n }\r\n\r\n });\r\n\r\n //$scope.$on('ChangeRoom', function (event, data) {\r\n //});\r\n\r\n $scope.Payment = function () {\r\n $scope.formData.errors = [];\r\n\r\n AppError.Send('Payment Button Pressed', userService.getCurrentUser());\r\n\r\n //$scope.inProgress = true;\r\n\r\n $scope.progress = \"submitted\"\r\n\r\n if (window.mixpanel)\r\n mixpanel.track(\"billing-start\", {\r\n \"Room Name\": $scope.chatRoom.s_url,\r\n \"Billing Plan\": $scope.paymentTitle,\r\n });\r\n\r\n\r\n if ($scope.quickPay) {\r\n charge([{\r\n id: null,\r\n card: {\r\n id: null\r\n }\r\n }]);\r\n } else if ($scope.nocardtrial) {\r\n charge([{\r\n id: null,\r\n card: {\r\n id: null\r\n }\r\n }]);\r\n } else {\r\n if ($scope.formData.cardName == null) {\r\n $scope.formData.errors.push('Please Enter Your Name');\r\n $scope.progress = false;\r\n return;\r\n };\r\n var l_strCountry = '';\r\n var l_objCountry = $scope.countries[$scope.formData.country - 1];\r\n if (l_objCountry != null)\r\n l_strCountry = l_objCountry.s_description;\r\n\r\n paymentData\r\n .getStripeToken({\r\n name: $scope.formData.cardName,\r\n address_line1: $scope.formData.address,\r\n address_zip: $scope.formData.postCode,\r\n address_city: $scope.formData.city,\r\n address_country: l_strCountry,\r\n number: $scope.formData.cardNumber,\r\n cvc: $scope.formData.ccv,\r\n exp_month: $scope.formData.month,\r\n exp_year: $scope.formData.year\r\n }, $scope.haveChild).then(function (response) {\r\n charge(response);\r\n\r\n }, function (response) { //on error\r\n if (window.mixpanel)\r\n mixpanel.track(\"billing-end\", {\r\n \"Room Name\": $scope.chatRoom.s_url,\r\n \"Billing Plan\": $scope.paymentTitle,\r\n \"Payment Status\": \"fail\",\r\n });\r\n\r\n $scope.formData.errors.push(response.error.message);\r\n $scope.progress = false\r\n }).finally(function () {\r\n //$scope.inProgress = false;\r\n\r\n });\r\n\r\n }\r\n\r\n }\r\n\r\n function charge(response) {\r\n var l_objCountry = $scope.countries[$scope.formData.country - 1],\r\n l_objCountryDescr = '';\r\n\r\n if (l_objCountry != null)\r\n l_objCountryDescr = l_objCountry.s_description;\r\n paymentData\r\n .submitPayment({\r\n name: $scope.formData.cardName,\r\n address_line1: $scope.formData.address,\r\n address_zip: $scope.formData.postCode,\r\n address_city: $scope.formData.city,\r\n address_country_id: $scope.formData.country,\r\n //------------Required------------//\r\n chatRoomKey: $scope.formData.roomKey.replace('private-', ''),\r\n planKey: $scope.formData.planKey,\r\n stripeToken: response[0].id,\r\n cardToken: response[0].card.id,\r\n stripeToken2: response[1] == null ? null : response[1].id,\r\n cardToken2: response[1] == null ? null : response[1].card.id,\r\n }).then(function (response1) {\r\n // console.log(response1);\r\n if (response1.success) {\r\n\r\n reportConvertion()\r\n\r\n if (window.mixpanel)\r\n mixpanel.track(\"billing-end\", {\r\n \"Room Name\": $scope.chatRoom.s_url,\r\n \"Billing Plan\": $scope.paymentTitle,\r\n \"Payment Status\": \"success\",\r\n });\r\n\r\n\r\n //notifyService.paymentSucccess();\r\n startCheckPayment()\r\n } else {\r\n if (window.mixpanel)\r\n mixpanel.track(\"billing-end\", {\r\n \"Room Name\": $scope.chatRoom.s_url,\r\n \"Billing Plan\": $scope.paymentTitle,\r\n \"Payment Status\": \"fail\",\r\n });\r\n\r\n //notifyService.error(response1.error);\r\n $scope.formData.errors.push(response1.error);\r\n $scope.progress = false\r\n }\r\n }, function (response1) {\r\n if (window.mixpanel)\r\n mixpanel.track(\"billing-end\", {\r\n \"Room Name\": $scope.chatRoom.s_url,\r\n \"Billing Plan\": $scope.paymentTitle,\r\n \"Payment Status\": \"fail\",\r\n });\r\n\r\n $scope.formData.errors.push(response1.message);\r\n $scope.progress = false\r\n }).finally(function () {\r\n //$scope.inProgress = false;\r\n\r\n });\r\n }\r\n\r\n function reportConvertion() {\r\n var tp = window._settings.reportConvertionScript\r\n if (tp) {\r\n\r\n var temp = document.createElement(\"textarea\");\r\n temp.innerHTML = tp;\r\n $scope.reportConvertionScript = $sce.trustAsHtml(temp.value)\r\n $scope.doReportConvertion = true\r\n }\r\n }\r\n\r\n $scope.testpay = function () {\r\n reportConvertion()\r\n }\r\n\r\n function startCheckPayment() {\r\n // console.debug(\"startCheckPayment\")\r\n\r\n $scope.progress = 'pending';\r\n\r\n var tries = 0;\r\n\r\n $scope.interv = $interval(function () {\r\n if (tries > 5) {\r\n $interval.cancel($scope.interv);\r\n return;\r\n }\r\n\r\n messageService\r\n .getRoomMessages($scope.formData.roomKey, '')\r\n .then(function (response) {\r\n // console.debug(\"startCheckPayment\", response);\r\n\r\n if (!response.success) {\r\n $scope.progress = 'fail';\r\n $interval.cancel($scope.interv);\r\n AppError.Send(new Error(\"CheckPayment failed\"), response)\r\n return\r\n }\r\n\r\n if (response.auth) {\r\n $scope.progress = 'success';\r\n $interval.cancel($scope.interv);\r\n return\r\n }\r\n\r\n if (response.data) {\r\n if (response.data.havePendingSubscriptions) {\r\n $scope.progress = 'success';\r\n $interval.cancel($scope.interv);\r\n return\r\n }\r\n }\r\n }, function (err) {\r\n $scope.progress = 'fail';\r\n $interval.cancel($scope.interv);\r\n AppError.Send(new Error(\"CheckPayment failed\"), err)\r\n })\r\n .finally(function () {\r\n tries++\r\n })\r\n }, 2000)\r\n }\r\n\r\n}\r\n\r\npaymentModal.$inject = ['paymentData'];\r\n\r\nfunction paymentModal(paymentData) {\r\n\r\n var injectScript = function (callback) {\r\n var scriptTag = document.createElement('script');\r\n scriptTag.setAttribute('charset', 'utf-8');\r\n scriptTag.setAttribute('src', 'https://js.stripe.com/v2/?1');\r\n scriptTag.onreadystatechange = scriptTag.onload = function () {\r\n callback();\r\n };\r\n document.getElementsByTagName('head')[0].appendChild(scriptTag);\r\n };\r\n\r\n return {\r\n templateUrl: 'payment-modal.html',\r\n scope: { },\r\n link: function (scope, elem) {\r\n\r\n $('#payment-modal').on('show.bs.modal', function (e) {\r\n\r\n if (!paymentData.stripeLoaded) {\r\n injectScript(function () {\r\n paymentData.initPaymentData();\r\n });\r\n }\r\n })\r\n\r\n },\r\n controller: \"paymentModalCtrl\"\r\n }\r\n}","'use strict';\r\n\r\nangular.module('chat.room', [\r\n 'chat.push',\r\n 'chat.user'\r\n ])\r\n\r\n .service('chatRoomData', ['$http', '$q', function ($http, $q) {\r\n\r\n var _getUserRoomAccess = function (a_strRoomKey) {\r\n var l_strUrl = 'api/user/getuserroomaccess?a_strRoomKey=' + a_strRoomKey;\r\n var deferred = $q.defer();\r\n $http.get(l_strUrl)\r\n .success(function (a_data, status, headers, config) {\r\n if (!a_data.success) {\r\n notifyService.showError('error code ' + a_data.errorCode, error);\r\n }\r\n deferred.resolve(a_data);\r\n })\r\n .error(function (data, status, headers, config) {\r\n notifyService.showError(\"Get Data \", 'error ' + status + ' get ' + l_strUrl);\r\n deferred.reject();\r\n });\r\n\r\n return deferred.promise;\r\n };\r\n\r\n return {\r\n getUserRoomAccess: _getUserRoomAccess\r\n }\r\n }])\r\n\r\n .service('chatRoomService', ['$location', '$rootScope', '$routeParams', '$route', '$window', 'pushService', 'userService', 'brokersService',\r\n function ($location, $rootScope, $routeParams, $route, $window, pushService, userService, brokersService) {\r\n var _chatRooms = [],\r\n totalUnread,\r\n _history = [];\r\n\r\n var _getDefaultRoom = function () {\r\n var l_objRoom = null;\r\n if (_chatRooms.length > 0)\r\n l_objRoom = _chatRooms[0];\r\n\r\n return l_objRoom;\r\n };\r\n\r\n var _addToHistory = function (a_objRoom) {\r\n _history.push(a_objRoom);\r\n\r\n if (_history.length > 3) //no more than 3\r\n _history.splice(-1, 1);\r\n };\r\n\r\n var _changeRoom = function (a_objRoom) {\r\n if (a_objRoom != null) {\r\n $rootScope.$broadcast('BeforeChangeRoom', a_objRoom);\r\n _addToHistory(a_objRoom);\r\n $location.url('/' + a_objRoom.s_url);\r\n }\r\n };\r\n\r\n var _gotoPrevious = function () {\r\n if (_history.length > 1) {\r\n _history.splice(-1, 1);\r\n $location.url('/' + _history[_history.length - 1].s_url);\r\n }\r\n\r\n };\r\n\r\n var _getCurrent = function () {\r\n var chatRoomName = '';\r\n if (typeof ($routeParams.id) == 'undefined') { //room\r\n chatRoomName = '#' + $location.hash();\r\n } else { //direct to user\r\n chatRoomName = $routeParams.id;\r\n }\r\n return chatRoomName;\r\n };\r\n\r\n var _findRoomByName = function (a_strChatName) {\r\n //consolelog('_findRoomByName', a_strChatName)\r\n for (var i = 0; i < _chatRooms.length; i++) {\r\n if (a_strChatName == _chatRooms[i].s_name.replace('private-', '').replace('private-r-', ''))\r\n return _chatRooms[i];\r\n };\r\n return null;\r\n };\r\n\r\n var _findRoomByClearKey = function (a_strChatKey) {\r\n //consolelog('_findRoomByName', a_strChatName)\r\n for (var i = 0; i < _chatRooms.length; i++) {\r\n // console.log(a_strChatKey, _chatRooms[i].s_key.substring(_chatRooms[i].s_key.length - 8, _chatRooms[i].s_key.length));\r\n if (a_strChatKey == _chatRooms[i].s_key.substring(_chatRooms[i].s_key.length - 8, _chatRooms[i].s_key.length))\r\n return _chatRooms[i];\r\n };\r\n return null;\r\n };\r\n\r\n var _findRoomByKey = function (a_strChatKey) {\r\n //consolelog('_findRoomByName', a_strChatName)\r\n for (var i = 0; i < _chatRooms.length; i++) {\r\n if (a_strChatKey == _chatRooms[i].s_key)\r\n return _chatRooms[i];\r\n };\r\n return null;\r\n };\r\n\r\n var _getCurrentRoom = function () {\r\n // console.log('_getCurrentRoom', typeof ($routeParams.id), $routeParams.id, _chatRooms);\r\n // console.log(\"_getCurrentRoom\",$routeParams);\r\n var chatRoom = {};\r\n\r\n angular.forEach(_chatRooms, function (room, key) {\r\n // console.log(\"inv\", room.s_name)\r\n room.isVisible = false\r\n })\r\n angular.forEach(brokersService.brokers, function (room, key) {\r\n //console.log(\"inv\", room.s_name)\r\n //room.isVisible = false\r\n })\r\n\r\n if (typeof ($routeParams.id) == 'undefined') { //the # is not route param so this is chatroom\r\n chatRoom = _findRoomByName($location.hash());\r\n // // console.log('_getCurrentRoom', typeof ($routeParams.id), $location.hash(), chatRoom, _chatRooms);\r\n if (chatRoom != null) {\r\n chatRoom.s_url = '#' + $location.hash();\r\n chatRoom.roomType = 1;\r\n }\r\n } else if ($routeParams.id.substring(0, 1) == '~') { //the ~ is for iframes\r\n // console.log('_getCurrentRoom', typeof ($routeParams.id), $routeParams.id, _chatRooms);\r\n chatRoom = _findRoomByName($routeParams.id.substring(1));\r\n if (chatRoom != null) {\r\n chatRoom.roomType = 3;\r\n chatRoom.s_url = $routeParams.id;\r\n //chatRoom.serviceURL = '/redirect/index/' + chatRoom.s_clearKey;\r\n chatRoom.isVisible = true;\r\n };\r\n } else if ($routeParams.id.substring(0, 1) == '@') {\r\n chatRoom = userService.getUserByName($location.path().substring(2))\r\n if (chatRoom != null) {\r\n chatRoom.s_url = '@' + chatRoom.userName\r\n chatRoom.roomType = 2;\r\n }\r\n } else if ($routeParams.id.substring(0, 1) == '$') {\r\n\r\n var _title = $location.path().substring(2)\r\n\r\n chatRoom = _.find(brokersService.brokers, function (o) {\r\n return o.s_title.toLowerCase() == _title;\r\n });\r\n\r\n if (chatRoom != null) {\r\n chatRoom.roomType = 4;\r\n }\r\n }\r\n return chatRoom;\r\n };\r\n\r\n var _initChatRooms = function (a_strPusherKey, a_lstChatRooms) {\r\n _chatRooms = _.sortBy(a_lstChatRooms, \"n_sort\");\r\n\r\n pushService.initPusher(a_strPusherKey);\r\n // console.log('_initChatRooms', _chatRooms);\r\n //subscribe all\r\n for (var i = 0; i < _chatRooms.length; i++) {\r\n _chatRooms[i].s_clearKey = _chatRooms[i].s_key.substring(_chatRooms[i].s_key.length - 8, _chatRooms[i].s_key.length);\r\n _chatRooms[i].n_count = 0;\r\n if (_chatRooms[i].n_type == 2 || _chatRooms[i].n_type == 1 || _chatRooms[i].n_type == 5) {\r\n _chatRooms[i].s_url = '#' + _chatRooms[i].s_name;\r\n pushService.subscribeChatRoom(_chatRooms[i].s_key);\r\n } else if (_chatRooms[i].n_type == 3) {\r\n _chatRooms[i].s_url = '~' + _chatRooms[i].s_name;\r\n }\r\n };\r\n\r\n if (_getCurrent() == '#steamroom' && _chatRooms.length > 0) {\r\n $location.hash('#members-only');\r\n };\r\n\r\n if (_getCurrent() == \"#\" && _chatRooms.length > 0) {\r\n var firstRoom = _.find(_chatRooms, function (r) {\r\n return r.n_type == 1 || r.n_type == 2 || r.n_type == 5\r\n })\r\n //var firstRoom = _chatRooms[0]\r\n // console.log(\"firstRoom\",firstRoom)\r\n $location.hash(firstRoom.s_name);\r\n } else {\r\n $route.reload();\r\n };\r\n\r\n // console.log('_initChatRooms', _chatRooms, _getCurrent());\r\n };\r\n\r\n var _getAll = function () {\r\n return _chatRooms;\r\n };\r\n\r\n var _sendMixdata = function (data) {\r\n if (!data || !window.mixpanel) return;\r\n mixpanel.track(\"room-change\", {\r\n \"Room Name\": data.s_url,\r\n });\r\n }\r\n\r\n return {\r\n totalUnread: totalUnread,\r\n getCurrent: _getCurrent,\r\n getCurrentRoom: _getCurrentRoom,\r\n getAll: _getAll,\r\n initChatRooms: _initChatRooms,\r\n findRoomByKey: _findRoomByKey,\r\n findRoomByClearKey: _findRoomByClearKey,\r\n getDefaultRoom: _getDefaultRoom,\r\n changeRoom: _changeRoom,\r\n SendMixdata: _sendMixdata,\r\n }\r\n }\r\n ])\r\n\r\n .controller('nosuchRoomCtrl', ['$scope', '$location', '$window', 'chatRoomService', function ($scope, $location, $window, chatRoomService) {\r\n var l_objModal = $('#nosuchRoomModal');\r\n l_objModal.css('top', '100px');\r\n $scope.$on('initial', function () {\r\n $scope.$on('$routeChangeStart', function (next, previous) {\r\n // console.log(\"next, previous\",next, previous)\r\n var l_objRoom = chatRoomService.getCurrentRoom();\r\n // console.log('$routeChangeStart', l_objRoom)\r\n if (l_objRoom == null) {\r\n //l_objModal.modal('show');\r\n }\r\n });\r\n });\r\n\r\n $scope.gotoDefault = function () {\r\n // console.log('gotoDefault')\r\n //$location.hash(chatRoomService.getDefaultRoom().s_name);\r\n\r\n $location.url('/#' + chatRoomService.getDefaultRoom().s_name);\r\n\r\n $window.location.reload();\r\n }\r\n\r\n }])\r\n\r\n .directive('privateRoomModal', ['$rootScope', '$window', 'chatRoomData', 'chatRoomService', function ($rootScope, $window, chatRoomData, chatRoomService) {\r\n return {\r\n replace: true,\r\n templateUrl: 'private-room-modal.html',\r\n link: function ($scope) {\r\n //private-room-modal\r\n\r\n var l_objModal = $('#private-room-modal');\r\n\r\n l_objModal.css('top', '100px');\r\n\r\n l_objModal.on('hidden.bs.modal', function () {\r\n\r\n if ($scope.interv) {\r\n $interval.cancel($scope.interv);\r\n }\r\n $window.history.back();\r\n\r\n });\r\n\r\n var checkRoom = function () {\r\n var l_objChatRoom = chatRoomService.getCurrentRoom();\r\n chatRoomData\r\n .getUserRoomAccess(l_objChatRoom.s_key)\r\n .then(function (response) {\r\n // console.log('getUserRoomAccess', response);\r\n if (response.success && !response.result)\r\n l_objModal.modal('show');\r\n else\r\n l_objModal.modal('hide');\r\n });\r\n }\r\n //$rootScope.$on('initial', function (event, data) {\r\n // checkRoom();\r\n //});\r\n $scope.$on('ChangeRoom', function (event, data) {\r\n // console.log(\"ChangeRoom\",data)\r\n if (data && data.n_type == 5) {\r\n // console.log(\"this is a private room...\")\r\n checkRoom();\r\n }\r\n });\r\n $scope.Close = function () {\r\n l_objModal.modal('hide');\r\n }\r\n }\r\n }\r\n }]);","'use strict';\r\n\r\nangular.module('chat.popover', [\r\n 'chat.user',\r\n 'chat.notify',\r\n 'chat.pinned'\r\n])\r\n\r\n.directive('userPopoverContainer', ['userService', 'notifyService', '$rootScope', '$location', 'chatRoomService', 'pinnedData',\r\n function (userService, notifyService, $rootScope, $location, chatRoomService, pinnedData) {\r\n return {\r\n scope: {\r\n senderKey: '@'\r\n },\r\n templateUrl: 'popover.html',\r\n link: function ($scope, $element) {\r\n var l_objTeamProperties = userService.getTeamProperties();\r\n var l_objCurrentUser = userService.getCurrentUser();\r\n var l_objPanelUser = userService.getUserByKey($scope.senderKey);\r\n var l_blnIsSpecial = (l_objCurrentUser.type == 1 || l_objCurrentUser.type == 2 || l_objCurrentUser.type == 3);\r\n var l_blnDestIsSpecial = (l_objPanelUser.type == 1 || l_objPanelUser.type == 2 || l_objPanelUser.type == 3);\r\n $scope.user = l_objPanelUser;\r\n $scope.canBan = (l_objCurrentUser.type == 1 || l_objCurrentUser.type == 2 || l_objCurrentUser.type == 3);\r\n $scope.isAdmin = (l_objCurrentUser.type == 1);\r\n $scope.dm = function () {\r\n if (l_objPanelUser.b_isCurrent)\r\n return;\r\n if (l_objPanelUser.isBlockedU) {\r\n notifyService.error('you have been blocked from contacting this user!');\r\n return;\r\n };\r\n //if (l_objTeamProperties.blockAllDMs) {\r\n // notifyService.error('Direct messages between users are disabled');\r\n // return;\r\n //}\r\n // console.log('popover', l_objCurrentUser, l_objPanelUser);\r\n if (l_objTeamProperties.blockAllDMs) {\r\n if (!l_blnIsSpecial && !l_blnDestIsSpecial) {\r\n notifyService.error('Direct messages are not allowed');\r\n return;\r\n }\r\n } else {\r\n if (userService.blockDMs() && (l_objPanelUser.b_allowDirectFromFree == null || l_objPanelUser.b_allowDirectFromFree == false)) {\r\n notifyService.error('Direct messages only allowed from premium users');\r\n return;\r\n }\r\n }\r\n \r\n $rootScope.$broadcast('StartDirectChat', l_objPanelUser);\r\n $scope.Exit();\r\n \r\n };\r\n $scope.BanUser = function () {\r\n // console.log('rightpanels BanUser 1', user);\r\n if (!l_objPanelUser.isBanned)\r\n userService.banUser({\r\n userKey: l_objPanelUser.s_key\r\n }).then(function (data) {\r\n $scope.Exit();\r\n notifyService.info('User Banned');\r\n // console.log('rightpanels BanUser 2', user, data);\r\n });\r\n else\r\n userService.unbanUser({\r\n userKey: l_objPanelUser.s_key\r\n }).then(function (data) {\r\n $scope.Exit();\r\n notifyService.info('User Unbanned');\r\n // console.log('rightpanels BanUser 2', user, data);\r\n });\r\n };\r\n $scope.BlockUser = function () {\r\n // console.log('rightpanels BanUser 1', user);\r\n if (!l_objPanelUser.isBlocked)\r\n userService.blockUser({\r\n userKey: l_objPanelUser.s_key\r\n }).then(function (data) {\r\n $scope.Exit();\r\n notifyService.info('User Blocked');\r\n // console.log('rightpanels BanUser 2', user, data);\r\n });\r\n else\r\n userService.unblockUser({\r\n userKey: l_objPanelUser.s_key\r\n }).then(function (data) {\r\n $scope.Exit();\r\n notifyService.info('User Unblocked');\r\n // console.log('rightpanels BanUser 2', user, data);\r\n });\r\n };\r\n $scope.MuteUser = function () {\r\n userService.muteUser({\r\n userKey: l_objPanelUser.s_key,\r\n roomKey: chatRoomService.getCurrentRoom().s_key\r\n }).then(function (data) {\r\n $scope.Exit();\r\n notifyService.info('User Muted');\r\n // console.log('rightpanels mute', l_objPanelUser, userService.getAll());\r\n });\r\n };\r\n\r\n // console.log(chatRoomService.getCurrentRoom().roomType == 1);\r\n $scope.canMute = function () {\r\n var l_objChatRoom = chatRoomService.getCurrentRoom();\r\n if (l_objChatRoom == null)\r\n return false;\r\n else\r\n return (l_objChatRoom.roomType == 1);\r\n };\r\n $scope.isMuted = function () {\r\n var l_objChatRoom = chatRoomService.getCurrentRoom();\r\n if (l_objChatRoom != null && l_objChatRoom.roomType == 1) {\r\n return userService.isMuted(l_objPanelUser.s_key, chatRoomService.getCurrentRoom().s_key); //l_strUserKey, l_strRoomKey\r\n }\r\n };\r\n $scope.Exit = function () {\r\n $('.user-popover').each(function () {\r\n $(this).removeClass('user-popover');\r\n $(this).popover('hide');\r\n });\r\n\r\n }\r\n\r\n $('[data-toggle=\"tooltip\"]').tooltip()\r\n }\r\n }\r\n}])\r\n\r\n.directive('userPopover', ['userService', '$compile', '$rootScope', function (userService, $compile, $rootScope) {\r\n return {\r\n scope: {\r\n senderKey: '@'\r\n },\r\n link: function ($scope, $element) {\r\n var l_objCurrentUser = userService.getCurrentUser();\r\n // console.log('userPopover', $scope.senderKey, userService.getCurrentUser().s_key);\r\n // console.log('userPopover', $scope.avatarUrl);\r\n \r\n if (l_objCurrentUser && l_objCurrentUser.s_key != $scope.senderKey) {\r\n $element.css('cursor', 'pointer');\r\n //$element.on('mouseenter', function () {\r\n // $element.css('cursor', 'hand');\r\n //});\r\n //$element.on('mouseleave', function () {\r\n // $element.css('cursor', 'pointer');\r\n //});\r\n $($element).popover({\r\n container: 'body',\r\n trigger: 'manual',\r\n content: function () {\r\n return $compile('
')($rootScope);\r\n },\r\n template: '
',\r\n placement: \"left top\",\r\n html: true\r\n }).click(function () {\r\n // console.log('click');\r\n //$compile('
')($rootScope);\r\n $($element).popover('toggle');\r\n\r\n var popoverPos = $(this).offset().top;\r\n if (popoverPos > ($(window).height() / 2)) {\r\n $('.popover.in').offset({ top: parseInt(popoverPos - 380) });\r\n }\r\n var popoverPosLeft = $(this).offset().left;\r\n if (popoverPosLeft > ($(window).width() / 2)) {\r\n $('.popover.in').offset({ left: parseInt(popoverPosLeft - parseInt($('#dvTools').css('width')) - 30) });\r\n }\r\n $(this).find('.arrow').css('display', 'none');\r\n //$scope.$apply();\r\n //$('.popover').attr('data-trigger', 'focus');\r\n });\r\n // console.log(l_objCurrentUser, $scope.item);\r\n\r\n //http://getbootstrap.com/javascript/#popovers-usage\r\n //show.bs.popover\tThis event fires immediately when the show instance method is called.\r\n //shown.bs.popover\tThis event is fired when the popover has been made visible to the user (will wait for CSS transitions to complete).\r\n //hide.bs.popover\tThis event is fired immediately when the hide instance method has been called.\r\n //hidden.bs.popover\tThis event is fired when the popover has finished being hidden from the user (will wait for CSS transitions to complete).\r\n //inserted.bs.popover\tThis event is fired after the show.bs.popover event when the popover template has been added to the DOM.\r\n $($element).on('show.bs.popover', function () {\r\n\r\n $('.user-popover').not(this).each(function () {\r\n $(this).popover('hide');\r\n })\r\n $(this).addClass('user-popover');\r\n\r\n \r\n\r\n });\r\n $($element).on('hide.bs.popover', function () {\r\n // console.log('click hide');\r\n $(this).removeClass('user-popover');\r\n });\r\n\r\n };\r\n //$('body').not('.user-popover').on('click', function () {\r\n // // console.log($(this));\r\n // //$('.user-popover').each(function () {\r\n // // $(this).popover('hide');\r\n // //})\r\n //});\r\n }\r\n }\r\n}])\r\n\r\n;\r\n","'use strict';\r\nangular\r\n .module('chat.alertstream', [])\r\n .directive('alertStream', alertStream)\r\n\r\nalertStream.$inject = ['streamDataService', '$timeout', '$rootScope'];\r\nfunction alertStream(streamDataService, $timeout, $rootScope) {\r\n\r\n return {\r\n \r\n templateUrl: 'alertstream.html',\r\n controller: function ($scope) {\r\n\r\n $scope.$on('ChangeRoom', _streamChanged);\r\n $scope.$on('StartStream', _streamChanged);\r\n $scope.$on('StopStream', _streamChanged);\r\n\r\n $scope.HideAlertBox = _hideAlertBox;\r\n $scope.OpenStreamModal = _openStreamModal;\r\n\r\n _streamChanged();\r\n\r\n function _openStreamModal() {\r\n\r\n if ($scope.l_strVideo == null) {\r\n $log.debug(\"No video stream feed were found\");\r\n return;\r\n }\r\n\r\n if ($scope.mobile != null && $scope.mobile == \"1\") {\r\n $window.open('https://www.youtube.com/watch?v=' + $scope.l_strVideo, '_blank');\r\n } else {\r\n $rootScope.$broadcast('LoadVidboxWidgetModal', {\r\n videoId: $scope.l_strVideo,\r\n });\r\n }\r\n\r\n }\r\n\r\n function _streamChanged() {\r\n $timeout(function () {\r\n $scope.l_strVideo = streamDataService.l_strVideoId;\r\n $scope.l_blnLive = streamDataService.l_blnLive;\r\n $scope.l_blnAlertBoxVisible = streamDataService.m_blnAlertBoxVisible;\r\n $scope.l_alertBoxShow = ($scope.l_blnLive && $scope.l_blnAlertBoxVisible);\r\n\r\n }, 250);\r\n }\r\n\r\n function _hideAlertBox() {\r\n streamDataService.m_blnAlertBoxVisible = false;\r\n $scope.l_blnAlertBoxVisible = false;\r\n $scope.l_alertBoxShow = ($scope.l_blnLive && $scope.l_blnAlertBoxVisible);\r\n }\r\n }\r\n\r\n }\r\n}","'use strict';\r\n\r\nangular.module('chat.pinned', [\r\n 'chat.room',\r\n 'chat.notify',\r\n 'chat.user',\r\n 'chat.templates'\r\n])\r\n\r\n.service('pinnedCore', [\"$location\", function ($location) {\r\n var l_lstUsers = [];\r\n\r\n var _exists = function (a_strUserKey) {\r\n for (var i = 0; i < l_lstUsers.length; i++) {\r\n if (l_lstUsers[i].s_key == a_strUserKey //compare either the roomkey or the userkey\r\n || l_lstUsers[i].s_key.substring(l_lstUsers[i].s_key.length - 8, l_lstUsers[i].s_key.length) == a_strUserKey) {\r\n return true;\r\n }\r\n };\r\n return false;\r\n }\r\n\r\n var _getPinnedUser = function (a_strUserKey) {\r\n for (var i = 0; i < l_lstUsers.length; i++) {\r\n if (l_lstUsers[i].s_key == a_strUserKey //compare either the roomkey or the userkey\r\n || l_lstUsers[i].s_key.substring(l_lstUsers[i].s_key.length - 8, l_lstUsers[i].s_key.length) == a_strUserKey) {\r\n return l_lstUsers[i];\r\n }\r\n };\r\n return null;\r\n }\r\n\r\n var _getUsers = function () {\r\n return l_lstUsers;\r\n }\r\n\r\n var _addUser = function (a_objUser) {\r\n // console.log('pinnedCore addUser', a_objUser);\r\n if (!_exists(a_objUser.s_key)) {\r\n l_lstUsers.push(a_objUser);\r\n }\r\n }\r\n\r\n var _removeUser = function (a_strUserKey) {\r\n for (var i = 0; i < l_lstUsers.length; i++) {\r\n if (l_lstUsers[i].s_key.substring(l_lstUsers[i].s_key.length - 8, l_lstUsers[i].s_key.length) == a_strUserKey.substring(a_strUserKey.length - 8, a_strUserKey.length)) {\r\n l_lstUsers.splice(i, 1);\r\n // console.log('pinnedCore removeUser', l_lstUsers);\r\n return;\r\n }\r\n };\r\n }\r\n\r\n return {\r\n getUsers: _getUsers,\r\n addUser: _addUser,\r\n removeUser: _removeUser,\r\n getPinnedUser: _getPinnedUser\r\n }\r\n}])\r\n\r\n.service('pinnedData', ['$http', '$q', 'notifyService', 'pinnedCore', function ($http, $q, notifyService, pinnedCore) {\r\n var url = {\r\n setPin: 'api/pin'\r\n }\r\n\r\n /// data = {Key: '', Pin: true}\r\n var _setPin = function (a_strUserKey, a_blnPin, a_strSenderKey) {\r\n var deferred = $q.defer();\r\n $http.post(url.setPin,\r\n JSON.stringify({ Key: a_strUserKey, Pin: a_blnPin, SenderKey: a_strSenderKey }),\r\n {\r\n headers: {\r\n 'Content-Type': 'application/json'\r\n }\r\n }\r\n )\r\n .success(function (a_data, status, headers, config) {\r\n deferred.resolve(a_data);\r\n })\r\n .error(function (data, status, headers, config) {\r\n notifyService.showError(\"Get Data \", 'error ' + status + ' get ' + url.setPin);\r\n deferred.reject();\r\n });\r\n\r\n return deferred.promise;\r\n };\r\n\r\n return {\r\n setPin: _setPin\r\n }\r\n\r\n}])\r\n\r\n.service('pinnedLogic', ['$rootScope', '$location', 'pinnedCore', 'pinnedData', 'userService', 'chatRoomService', function ($rootScope, $location, pinnedCore, pinnedData, userService, chatRoomService) {\r\n\r\n $rootScope.$on('PinAction', function (event, data) {\r\n var l_objCurrentUser = userService.getCurrentUser();\r\n // console.log('pinnedUsers PinAction', data, l_objCurrentUser);\r\n if (data.Pin) {\r\n var l_objUser = userService.getUserByClearKey(data.Key);\r\n pinnedCore.addUser(l_objUser);\r\n // console.log(l_objCurrentUser.s_clearkey, data.Key);\r\n if (l_objCurrentUser.s_clearkey == data.SenderKey)\r\n $location.url('/@' + l_objUser.userName);\r\n } else {\r\n pinnedCore.removeUser(data.Key);\r\n\r\n var l_lstUsers = pinnedCore.getUsers();\r\n if (l_lstUsers.length > 0) {\r\n $location.url('@' + l_lstUsers[0].userName);\r\n } else {\r\n chatRoomService.changeRoom(chatRoomService.getDefaultRoom());\r\n }\r\n\r\n }\r\n });\r\n\r\n return { };\r\n}])\r\n\r\n.directive('pinnedHandler', ['pinnedLogic', function(pinnedLogic){\r\n return {\r\n scope: {},\r\n link: function (scope, element) {\r\n }\r\n }\r\n}])\r\n\r\n.directive('pinnedUsers', ['pinnedCore', 'pinnedData', '$rootScope', '$location', 'userService', 'chatRoomService',\r\n function (pinnedCore, pinnedData, $rootScope, $location, userService, chatRoomService) {\r\n return {\r\n scope: {},\r\n replace: true,\r\n templateUrl: 'direct-messages.html',\r\n link: function (scope, element) {\r\n scope.users = pinnedCore.getUsers();\r\n\r\n // console.log('pinnedUsers', scope.users);\r\n \r\n scope.$on('StartDirectChat', function (event, data) {\r\n var l_objCurrentUser = userService.getCurrentUser();\r\n // console.log('pinnedUsers StartDirectChat', data);\r\n\r\n\r\n pinnedData.setPin(data.s_clearkey, true, l_objCurrentUser.s_clearkey).then(function (responseData) {\r\n // console.log('pinnedUsers StartDirectChat2', data);\r\n pinnedCore.addUser(data);\r\n var l_objUser = userService.getUserByClearKey(data.s_clearkey);\r\n $location.url('/@' + l_objUser.userName);\r\n });\r\n });\r\n scope.safeApply = function (fn) {\r\n var phase = this.$root.$$phase;\r\n if (phase == '$apply' || phase == '$digest') {\r\n if (fn && (typeof (fn) === 'function')) {\r\n fn();\r\n }\r\n } else {\r\n this.$apply(fn);\r\n }\r\n };\r\n scope.$on('IncomingMessage', function (event, data) {\r\n // console.log('pinnedUsers IncomingMessage', data);\r\n var l_objUser = userService.getUserByName(data.Sender);\r\n var l_objCurrentUser = userService.getCurrentUser();\r\n //Add last date\r\n var l_objPinnedUser = pinnedCore.getPinnedUser(data.SenderKey);\r\n //console.log('IncomingMessage pinned 0', data.ReceiverKey, l_objCurrentUser.s_key);\r\n\r\n if (l_objCurrentUser && l_objCurrentUser.s_key && data.ReceiverKey && data.ReceiverKey.indexOf(l_objCurrentUser.s_key) > -1){\r\n if (l_objPinnedUser) {\r\n // console.log('IncomingMessage pinned ', l_objPinnedUser);\r\n l_objPinnedUser.n_lastDate = moment.utc(data.Submitted).valueOf();\r\n }\r\n if (l_objUser)\r\n {\r\n l_objUser.n_lastDate = moment.utc(data.Submitted).valueOf();\r\n }\r\n if (l_objUser.s_key != l_objCurrentUser.s_key && data.RoomKey.substring(0, 10) == 'private-u-') { //private chat\r\n //var l_objCurrentUser = userService.getCurrentUser();\r\n // console.log('pinnedUsers incoming message', data)\r\n pinnedData.setPin(l_objUser.s_clearkey, true, l_objUser.s_clearkey).then(function (responseData) {\r\n pinnedCore.addUser(l_objUser);\r\n });\r\n }\r\n scope.safeApply();\r\n }\r\n });\r\n scope.$on('ChangeRoom', function (event, data) {\r\n // console.log('ChangeRoom', data);\r\n if (data != null && data.s_key != null && data.s_key.isDirect) {\r\n var l_objPinnedUser = pinnedCore.getPinnedUser(data.s_clearKey);\r\n if (l_objPinnedUser != null) {\r\n l_objPinnedUser.n_count = 0;\r\n scope.$apply();\r\n }\r\n }\r\n });\r\n scope.$on('initial', function (event, data) {\r\n //scope.$apply();\r\n\r\n // console.log('pinned initial', pinnedCore.getUsers())\r\n });\r\n scope.$on('RoomReaded', function (event, data) {\r\n // console.log('RoomReaded', data);\r\n var l_objPinnedUser = pinnedCore.getPinnedUser(data.Room.substring(data.Room.length - 8, data.Room.length));\r\n if (l_objPinnedUser != null) {\r\n l_objPinnedUser.n_count = 0;\r\n scope.$apply();\r\n }\r\n });\r\n element.bind(\"click\", function () {\r\n\r\n });\r\n scope.Change = function () {\r\n // console.log('lalalala');\r\n }\r\n }\r\n }\r\n }])\r\n\r\n.directive('pinnedHideButton', ['$location', 'pinnedCore', 'chatRoomService', 'pinnedData', 'userService',\r\n function ($location, pinnedCore, chatRoomService, pinnedData, userService) {\r\n return {\r\n scope: {\r\n userkey: '@'\r\n },\r\n link: function (scope, element) {\r\n element.bind(\"click\", function () {\r\n var l_objCurrentUser = userService.getCurrentUser();\r\n pinnedData.setPin(scope.userkey, false, l_objCurrentUser.s_clearkey).then(function (responseData) {\r\n // console.log('unpin', scope.userkey);\r\n \r\n });\r\n });\r\n }\r\n }\r\n }])\r\n\r\n.directive('pinnedUserTitle', ['pinnedCore', '$rootScope', 'pinnedLogic', function (pinnedCore, $rootScope, pinnedLogic) {\r\n return {\r\n template: '
  • DIRECT MESSAGES
  • ',\r\n link: function (scope, element) {\r\n var users = null;\r\n scope.safeApply = function (fn) {\r\n var phase = this.$root.$$phase;\r\n if (phase == '$apply' || phase == '$digest') {\r\n if (fn && (typeof (fn) === 'function')) {\r\n fn();\r\n }\r\n } else {\r\n this.$apply(fn);\r\n }\r\n };\r\n\r\n var _calcShow = function () {\r\n users = pinnedCore.getUsers();\r\n if (users != null && users.length > 0) {\r\n element.show();\r\n }\r\n else {\r\n element.hide();\r\n }\r\n scope.safeApply();\r\n }\r\n //$rootScope.$on('IncomingMessage', _calcShow);\r\n scope.$on('PinAction', _calcShow);\r\n scope.$on('initial', _calcShow);\r\n }\r\n }\r\n}]);","'use strict';\r\n\r\nangular.module('chat.filterpanel', [\r\n 'chat.user',\r\n 'chat.message',\r\n 'luegg.directives'\r\n])\r\n\r\n .service('panelCore', [function () {\r\n var l_lstMessages = [],\r\n l_lstPending = [];\r\n\r\n var _exists = function (a_strSender, a_strCreated) {\r\n for (var i = 0; i < l_lstMessages.length; i++) {\r\n if (l_lstMessages[i].s_sender + l_lstMessages[i].d_created == a_strSender + a_strCreated) { //compare with Sender and Date Created as key\r\n return i;\r\n }\r\n };\r\n return null;\r\n }\r\n\r\n var _uploadDone = function (a_strFileToken) {\r\n for (var i = 0; i < l_lstMessages.length; i++) {\r\n // console.log('_findByFileToken', _list[i].s_fileToken, a_strFileToken, _list[i].s_fileToken == a_strFileToken);\r\n if (l_lstMessages[i].s_fileToken == a_strFileToken) {\r\n l_lstMessages[i].b_isUploaded = true;\r\n return l_lstMessages[i];\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n var _getMessages = function () {\r\n return l_lstMessages;\r\n }\r\n\r\n var _addMessage = function (a_objMessage) {\r\n if (_exists(a_objMessage.s_sender, a_objMessage.d_created) == null) {\r\n a_objMessage.b_thumb = a_objMessage.s_extension != null &&\r\n (a_objMessage.s_extension.toLowerCase() == 'jpg' ||\r\n a_objMessage.s_extension.toLowerCase() == 'jpeg' ||\r\n a_objMessage.s_extension.toLowerCase() == 'png' ||\r\n a_objMessage.s_extension.toLowerCase() == 'bmp' ||\r\n a_objMessage.s_extension.toLowerCase() == 'gif' ||\r\n a_objMessage.s_extension.toLowerCase() == 'ico');\r\n var _fileUpAlready = _checkFile(a_objMessage.s_fileToken);\r\n if (_fileUpAlready != null) {\r\n l_lstPending.splice(_fileUpAlready, 1);\r\n a_objMessage.b_isUploaded = true;\r\n }\r\n l_lstMessages.push(a_objMessage);\r\n }\r\n }\r\n\r\n var _removeMessage = function (a_strSender, a_strCreated) {\r\n var l_intIdx = _exists(a_strSender, a_strCreated);\r\n if (l_intIdx >= 0) {\r\n l_lstMessages.splice(l_intIdx, 1);\r\n }\r\n }\r\n\r\n var _checkFile = function (a_strToken) {\r\n for (var i = 0; i < l_lstPending.length; i++) {\r\n if (l_lstPending[i] == a_strToken) {\r\n return i;\r\n }\r\n }\r\n return null;\r\n };\r\n\r\n var _addPendingFile = function (a_strToken) {\r\n l_lstPending.push(a_strToken);\r\n };\r\n\r\n return {\r\n getMessages: _getMessages,\r\n addMessage: _addMessage,\r\n removeMessage: _removeMessage,\r\n uploadDone: _uploadDone,\r\n addPendingFile: _addPendingFile\r\n }\r\n }])\r\n\r\n .service('panelData', ['$http', '$q', 'notifyService', 'panelCore', function ($http, $q, notifyService, panelCore) {\r\n var _timestamp = '';\r\n var _getMessages = function () {\r\n var deferred = $q.defer();\r\n $http.get('api/filtermessage?timestamp=' + _timestamp, null)\r\n .success(function (a_data, status, headers, config) {\r\n if (a_data.success && a_data.data != null) {\r\n _timestamp = a_data.data[0].d_lastEdit;\r\n // console.log('filtermessage', a_data.data[0].d_lastEdit, a_data.data[19].d_lastEdit);\r\n }\r\n deferred.resolve(a_data);\r\n })\r\n .error(function (data, status, headers, config) {\r\n notifyService.showError(\"Get Data \", 'error ' + status + ' get /filtermessage');\r\n deferred.reject();\r\n });\r\n\r\n return deferred.promise;\r\n };\r\n\r\n return {\r\n getMessages: _getMessages\r\n }\r\n\r\n }])\r\n\r\n .directive('whenFilterPanelScrolled', ['$timeout', '$rootScope', '$q', 'panelData', 'userService', 'panelCore', function ($timeout, $rootScope, $q, panelData, userService, panelCore) {\r\n return function (scope, elm, attr) {\r\n var raw = elm[0];\r\n scope.status = {\r\n loading: false,\r\n loaded: false\r\n };\r\n\r\n var _loadMore = function () {\r\n var deferred = $q.defer();\r\n // console.log('filterMessages loadMore');\r\n if (!scope.status.loading) {\r\n scope.status.loading = true;\r\n panelData.getMessages().then(function (response) {\r\n if (response != null && response.data != null) {\r\n for (var i = 0; i < response.data.length; i++) {\r\n var l_objUser = userService.getUserByName(response.data[i].s_sender);\r\n\r\n if (l_objUser != null) {\r\n var l_objMessage = {\r\n sender: response.data[i].s_sender,\r\n senderKey: l_objUser.s_key,\r\n message: response.data[i].s_message,\r\n d_lastEdit: response.data[i].d_lastEdit,\r\n s_avatar: l_objUser.s_avatar,\r\n s_typeAvatar: l_objUser.s_typeAvatar,\r\n s_path: '//cdn.echofin.co/uploads/' + l_objUser.s_key.substring(10) + '/',\r\n s_fileName: response.data[i].s_fileName,\r\n s_fileToken: response.data[i].s_fileToken,\r\n s_extension: response.data[i].s_extension,\r\n n_fileType: response.data[i].n_fileType,\r\n s_fileDescr: response.data[i].s_fileDescr,\r\n s_fileLink: response.data[i].s_fileLink,\r\n b_isUploaded: true\r\n };\r\n panelCore.addMessage(l_objMessage);\r\n }\r\n }\r\n scope.messages = panelCore.getMessages();\r\n scope.status.loading = false;\r\n scope.status.loaded = true;\r\n deferred.resolve();\r\n } else {\r\n deferred.reject();\r\n }\r\n });\r\n } else {\r\n deferred.reject();\r\n }\r\n return deferred.promise;\r\n };\r\n\r\n elm.bind('scroll', function () {\r\n if (raw.scrollHeight - raw.scrollTop < 300) {\r\n // console.log('scroll', raw.scrollHeight, raw.scrollTop, raw.scrollHeight - raw.scrollTop)\r\n //$rootScope.$broadcast('MoveToBottom', raw);\r\n }\r\n if (raw.scrollTop == 0) {\r\n var sh = raw.scrollHeight\r\n //_loadMore().then(function () {\r\n //});\r\n scope.$apply(_loadMore)\r\n .then(function () {\r\n $timeout(function () {\r\n raw.scrollTop = raw.scrollHeight - sh;\r\n })\r\n });\r\n }\r\n });\r\n };\r\n }])\r\n\r\n .directive('filterPanel', ['panelCore', 'panelData', '$rootScope', '$location', 'userService', 'chatRoomService', 'messageDatasource',\r\n function (panelCore, panelData, $rootScope, $location, userService, chatRoomService, messageDatasource) {\r\n return {\r\n scope: {},\r\n link: function (scope, element) {\r\n scope.safeApply = function (fn) {\r\n var phase = this.$root.$$phase;\r\n if (phase == '$apply' || phase == '$digest') {\r\n if (fn && (typeof (fn) === 'function')) {\r\n fn();\r\n }\r\n } else {\r\n this.$apply(fn);\r\n }\r\n };\r\n\r\n $rootScope.$on('StartDirectChat', function (event, data) {\r\n var l_objCurrentUser = userService.getCurrentUser();\r\n // console.log('pinnedUsers StartDirectChat', data);\r\n //pinnedData.setPin(data.s_clearkey, true, l_objCurrentUser.s_clearkey).then(function (responseData) {\r\n // // console.log('pinnedUsers StartDirectChat2', data);\r\n // pinnedCore.addUser(data);\r\n //});\r\n });\r\n scope.$on('IncomingMessage', function (event, data) {\r\n //temporary\r\n var l_objUser = userService.getUserByName(data.Sender);\r\n //temporary until the server side updates\r\n //var l_objUser = userService.getUserByClearKey(data.SenderKey);\r\n var l_objCurrentUser = userService.getCurrentUser();\r\n\r\n\r\n var l_blnIsFiltered = false;\r\n\r\n try {\r\n l_blnIsFiltered = (l_objUser.s_clearkey && l_objUser.s_clearkey == 'bc1396f5');\r\n } catch (e) { }\r\n\r\n if (!l_blnIsFiltered) { //check again in case there's no clearKey\r\n try {\r\n l_blnIsFiltered = (l_objUser.s_key && l_objUser.s_key.substring(10) == 'bc1396f5');\r\n } catch (e) { }\r\n }\r\n\r\n // console.log('filterPanel IncomingMessage', data, l_objUser);\r\n if (l_blnIsFiltered) //bc1396f5 wallstjesus //e2e67d98 george\r\n {\r\n var l_objMessage = {\r\n sender: data.Sender,\r\n senderKey: l_objUser.s_key,\r\n message: data.Text,\r\n d_lastEdit: moment.utc(data.Submitted).format().toString(),\r\n s_avatar: l_objUser.s_avatar,\r\n s_typeAvatar: l_objUser.s_typeAvatar,\r\n s_path: '//cdn.echofin.co/uploads/' + l_objUser.s_key.substring(10) + '/',\r\n s_fileName: data.Filename,\r\n s_fileToken: data.Media,\r\n s_extension: data.Extension,\r\n n_fileType: data.n_fileType,\r\n s_fileDescr: data.s_fileDescr,\r\n s_fileLink: data.s_fileLink,\r\n b_isUploaded: (data.n_fileType == 2)\r\n };\r\n panelCore.addMessage(l_objMessage);\r\n // console.log('IncomingMessage', l_objMessage, panelCore.getMessages());\r\n\r\n scope.safeApply();\r\n\r\n var scrollcontainer = \"#dvFilterMessages\";\r\n $(scrollcontainer).scrollTop($(scrollcontainer)[0].scrollHeight);\r\n }\r\n });\r\n\r\n }\r\n }\r\n }])\r\n\r\n .directive('filterMessages', ['panelCore', 'panelData', 'userService', '$rootScope', function (panelCore, panelData, userService, $rootScope) {\r\n return {\r\n controller: function ($scope) {\r\n // // console.log('run');\r\n },\r\n link: function (scope, element) {\r\n scope.messages = panelCore.getMessages();\r\n scope.safeApply = function (fn) {\r\n var phase = this.$root.$$phase;\r\n if (phase == '$apply' || phase == '$digest') {\r\n if (fn && (typeof (fn) === 'function')) {\r\n fn();\r\n }\r\n } else {\r\n this.$apply(fn);\r\n }\r\n };\r\n scope.$on('initial', function (event, data) {\r\n\r\n var s_key = userService.getTeamProperties().s_key\r\n if (s_key != '875960cc' && s_key != '1a6638d0') {\r\n return\r\n }\r\n\r\n panelData.getMessages().then(function (response) {\r\n if (response != null && response.data != null) {\r\n for (var i = 0; i < response.data.length; i++) {\r\n var l_objUser = userService.getUserByName(response.data[i].s_sender);\r\n\r\n if (l_objUser != null) {\r\n var l_objMessage = {\r\n sender: response.data[i].s_sender,\r\n senderKey: l_objUser.s_key,\r\n message: response.data[i].s_message,\r\n d_lastEdit: response.data[i].d_lastEdit,\r\n s_avatar: l_objUser.s_avatar,\r\n s_typeAvatar: l_objUser.s_typeAvatar,\r\n s_path: '//cdn.echofin.co/uploads/' + l_objUser.s_key.substring(10) + '/',\r\n s_fileName: response.data[i].s_fileName,\r\n s_fileToken: response.data[i].s_fileToken,\r\n s_extension: response.data[i].s_extension,\r\n n_fileType: response.data[i].n_fileType,\r\n s_fileDescr: response.data[i].s_fileDescr,\r\n s_fileLink: response.data[i].s_fileLink,\r\n b_isUploaded: true\r\n };\r\n panelCore.addMessage(l_objMessage);\r\n }\r\n }\r\n scope.messages = panelCore.getMessages();\r\n // console.log('filterMessages scope.messages', scope.messages);\r\n\r\n var scrollcontainer = \"#dvFilterMessages\";\r\n $(scrollcontainer).scrollTop($(scrollcontainer)[0].scrollHeight);\r\n }\r\n });\r\n });\r\n $rootScope.$on('UploadDone', function (event, data) {\r\n panelCore.uploadDone(data.s_token);\r\n panelCore.addPendingFile(data.s_token);\r\n });\r\n $('#dvFilterPanel').bind(\"animationend webkitAnimationEnd oAnimationEnd MSAnimationEnd transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd\", function () {\r\n // console.log('TogglePanel transitionend')\r\n $(element).scrollTop($(element)[0].scrollHeight);\r\n });\r\n\r\n }\r\n }\r\n }])\r\n ;","'use strict';\r\n\r\nangular.module('chat.widget.tradingview', [\r\n 'chat.browser'\r\n])\r\n\r\n .directive('btntrading', ['$rootScope', function ($rootScope) {\r\n return {\r\n replace: true,\r\n scope: {},\r\n template: '',\r\n link: function ($scope, $elem) {\r\n $elem.bind('click', function () {\r\n // console.log('click');\r\n $rootScope.$broadcast('LoadTradingWidgetModal');\r\n });\r\n }\r\n }\r\n }])\r\n\r\n .directive('tradingviewwidget', ['userService', function (userService) {\r\n return {\r\n scope: { },\r\n templateUrl: 'tradingview-widget.html',\r\n controller: function ($scope) {\r\n $('.embed-responsiveTrading').css('height', \"100%\");\r\n },\r\n link: function ($scope, $elem) {\r\n \r\n $scope.$on('LoadTradingWidgetModal', function (event, data) {\r\n // console.log('LoadTradingWidgetModal', data);\r\n var l_objTeam = userService.getTeamProperties();\r\n // console.log('LoadTradingWidgetModal', l_objTeam);\r\n if (l_objTeam != null && (l_objTeam.s_key == '875960cc')) {\r\n $scope.frameSrc = '//www.firewaterelements.com/#/firechart';\r\n } else {\r\n\r\n var l_strSpecific = '';\r\n\r\n if (data) {\r\n l_strSpecific += '?s=' + data;\r\n }\r\n\r\n $scope.frameSrc = 'js/templates/tradingview-container.html' + l_strSpecific;\r\n \r\n // console.log('TradingFrame', $scope.frameSrc);\r\n }\r\n $(\"#tradingModal\").css(\"z-index\", lastZIndex++)\r\n $('#tradingModal').modal('show');\r\n \r\n });\r\n\r\n var timeoutId = 0;\r\n\r\n $('#tradingModal > .ui-widget-header')\r\n .on('mousedown', function () {\r\n $(\".custom-backdrop\").show()\r\n $(\"#tradingModal\").css(\"z-index\", lastZIndex++)\r\n }).on('mouseup', function () {\r\n $(\".custom-backdrop\").hide()\r\n });\r\n\r\n $('#tradingModal')\r\n .draggable({\r\n handle: \"div.ui-widget-header\",\r\n containment: \"document\",\r\n start: function (event, ui) {\r\n $(\".custom-backdrop\").show()\r\n $(\"#tradingModal\").css(\"z-index\", lastZIndex++)\r\n },\r\n stop: function (event, ui) {\r\n $(\".custom-backdrop\").hide()\r\n }\r\n })\r\n .resizable({\r\n containment: \"document\",\r\n minWidth: 400,\r\n minHeight: 350,\r\n aspectRatio: false,\r\n handles: \"se\",\r\n start: function (event, ui) {\r\n $(\".custom-backdrop\").show()\r\n $(\"#tradingModal\").css(\"z-index\", lastZIndex++)\r\n },\r\n stop: function (event, ui) {\r\n $(\".custom-backdrop\").hide()\r\n }\r\n });\r\n\r\n $scope.Close = function () {\r\n // console.log('lala');\r\n $('#tradingModal').modal('hide');\r\n }\r\n }\r\n }\r\n\r\n }])\r\n .directive('tradingviewcontainer', [function () {\r\n return {\r\n scope: {},\r\n link: function ($scope, $elem) {\r\n new TradingView.widget({\r\n \"autosize\": true,\r\n \"symbol\": \"NASDAQ:AAPL\",\r\n \"interval\": \"D\",\r\n \"timezone\": \"Etc/UTC\",\r\n \"theme\": \"Black\",\r\n \"style\": \"1\",\r\n \"locale\": \"en\",\r\n \"toolbar_bg\": \"rgba(66, 66, 66, 1)\",\r\n \"enable_publishing\": false,\r\n \"withdateranges\": true,\r\n \"allow_symbol_change\": true,\r\n \"hideideas\": true,\r\n \"referral_id\": \"3495\"\r\n });\r\n }\r\n }\r\n }])\r\n ;","'use strict';\r\n\r\nangular.module('chat.widget.vidbox', ['chat.stream', 'chat.user'])\r\n\r\n .directive('vidboxwidget', ['$sce', '$rootScope', 'customStreamDataService', 'userService', 'tokenService', function ($sce, $rootScope, customStreamDataService, userService, tokenService) {\r\n return {\r\n scope: {},\r\n templateUrl: 'vidbox-widget.html',\r\n link: function (scope, elem) {\r\n\r\n\r\n $('#vidboxModal > .ui-widget-header')\r\n .on('mousedown', function () {\r\n $(\".custom-backdrop\").show()\r\n $(\"#vidboxModal\").css(\"z-index\", lastZIndex++)\r\n }).on('mouseup', function () {\r\n $(\".custom-backdrop\").hide()\r\n });\r\n\r\n $('#vidboxModal')\r\n .draggable({\r\n handle: \"div.ui-widget-header\",\r\n containment: \"document\",\r\n start: function (event, ui) {\r\n $(\".custom-backdrop\").show()\r\n $(\"#vidboxModal\").css(\"z-index\", lastZIndex++)\r\n },\r\n stop: function (event, ui) {\r\n $(\".custom-backdrop\").hide()\r\n\r\n\r\n }\r\n })\r\n .resizable({\r\n containment: \"document\",\r\n minWidth: 400,\r\n minHeight: 225,\r\n aspectRatio: true,\r\n handles: \"se\",\r\n start: function (event, ui) {\r\n $(\".custom-backdrop\").show()\r\n $(\"#vidboxModal\").css(\"z-index\", lastZIndex++)\r\n },\r\n stop: function (event, ui) {\r\n $(\".custom-backdrop\").hide()\r\n $rootScope.$broadcast('VidboxModalResizeEnd', {\r\n event: event,\r\n ui: ui\r\n });\r\n }\r\n });\r\n\r\n scope.$on('LoadVidboxWidgetModal', function (event, data) {\r\n _show()\r\n })\r\n\r\n scope.$on('StopStream', function (event, data) {\r\n scope.Close();\r\n })\r\n\r\n scope.Minimize = function () {\r\n _close(true)\r\n }\r\n\r\n scope.Close = function () {\r\n _close();\r\n customStreamDataService.stopPlayerStream(document.getElementById('localVideo'));\r\n }\r\n\r\n function _show() {\r\n $(\"#vidboxModal\").css(\"z-index\", lastZIndex++)\r\n $('#vidboxModal').modal('show');\r\n scope.modalOpen = true;\r\n }\r\n\r\n function _close(minimize) {\r\n // console.log(\"close video\")\r\n if (!minimize) {\r\n scope.videoId = null;\r\n }\r\n $('#vidboxModal').modal('hide');\r\n scope.modalOpen = false;\r\n // console.log(\"close2 video\")\r\n }\r\n },\r\n controller: function ($scope, $timeout) {\r\n $scope.extra = null;\r\n $scope.isLoading = false;\r\n $scope.videoId = null;\r\n $scope.message1 = null;\r\n $scope.typeId = 1; //default youtube\r\n $scope.streamCheck = false;\r\n $scope.$on('LoadVidboxWidgetModal', function (event, data) {\r\n\r\n console.log('LoadVidboxWidgetModal', data);\r\n if (data.broadcaster) {\r\n var l_objBroadcaster = userService.getUserByClearKey(data.broadcaster);\r\n if (l_objBroadcaster && data.videoId == 2)\r\n $scope.extra = ' @' + l_objBroadcaster.userName;\r\n }\r\n $scope.message1 = data.message1;\r\n $scope.message2 = data.message2;\r\n $scope.upgradeUrl = data.upgradeUrl;\r\n $scope.typeId = null;\r\n if (data.videoId) {\r\n $scope.typeId = data.videoId.type;\r\n }\r\n\r\n if (window.isDesktopClient) {\r\n $timeout(function () {\r\n // console.log(\"LoadVidboxWidgetModal data\", data)\r\n $scope.Close()\r\n $scope.videoId = data.videoId.videoId\r\n var _params = _getParams()\r\n // console.log(\"LoadVidboxWidgetModal data\", data, _params)\r\n window.parent.postMessage({\r\n event: \"popup\",\r\n params: _params\r\n }, \"*\");\r\n }, 1000)\r\n return\r\n }\r\n\r\n $timeout(function () {\r\n if ($scope.videoId == data.videoId) {\r\n return\r\n }\r\n _start(data.videoId.videoId)\r\n })\r\n });\r\n\r\n $scope.$on('StartStream', function (event, data) {\r\n if (data == null) {\r\n // console.log(\"StartStream data is null\");\r\n } else {\r\n $scope.typeId = data.type;\r\n // console.log(\"dd StartStream\", data)\r\n if ($scope.modalOpen) {\r\n _start(data.videoId);\r\n }\r\n\r\n if (data.broadcaster) {\r\n var l_objBroadcaster = userService.getUserByClearKey(data.broadcaster);\r\n if (l_objBroadcaster)\r\n $scope.extra = 'by ' + l_objBroadcaster.userName;\r\n }\r\n }\r\n })\r\n\r\n $scope.popout = function () {\r\n\r\n var _params = _getParams();\r\n var title = userService.getTeamProperties().s_name // + \" / @\" + userService.getCurrentUser().userName\r\n var windowFeatures = 'width=600,height=400,resizeable,location=no'\r\n\r\n var streamForm = document.createElement(\"form\");\r\n streamForm.target = \"streamWindow\";\r\n streamForm.method = \"POST\";\r\n streamForm.action = _params.url;\r\n\r\n for (var k in _params.data) {\r\n if (_params.data.hasOwnProperty(k)) {\r\n var mapInput = document.createElement(\"input\");\r\n mapInput.type = \"hidden\";\r\n mapInput.name = k;\r\n mapInput.value = _params.data[k];\r\n streamForm.appendChild(mapInput);\r\n }\r\n }\r\n\r\n document.body.appendChild(streamForm);\r\n\r\n window.streamPopup = window.open('', \"streamWindow\", windowFeatures);\r\n if (window.streamPopup) {\r\n streamForm.submit();\r\n } else {\r\n alert('You must allow popups.');\r\n }\r\n\r\n $scope.Close()\r\n }\r\n\r\n function _start(videoId) {\r\n if (videoId && videoId != \"-STOPPED-\") {\r\n // console.log('_start', videoId, $scope.typeId, customStreamDataService.getBroadcaster())\r\n $scope.videoId = videoId;\r\n if ($scope.typeId == 1) {\r\n $scope.videoUrl = $sce.trustAsResourceUrl(\"https://www.youtube.com/embed/\" + videoId + \"?autoplay=1&rel=0\");\r\n } else if ($scope.typeId == 2) {\r\n if (!customStreamDataService.getBroadcaster()) {\r\n $scope.isLoading = true;\r\n l_strCompanyKey = userService.getTeamProperties().s_key;\r\n\r\n customStreamDataService.initPlayerStream(l_strCompanyKey, window.streamServerUrl + l_strCompanyKey, document.getElementById('localVideo'), null)\r\n .then(function (a_objReturn) {\r\n var STREAM_STATUS = a_objReturn.Flashphoner.constants.STREAM_STATUS;\r\n $scope.isLoading = false;\r\n\r\n a_objReturn.stream.on(STREAM_STATUS.PLAYING, function () {\r\n\r\n var CalcWindow = function () {\r\n var streamResolution = a_objReturn.stream.videoResolution();\r\n var l_objTarget = {\r\n height: $('#vidboxModal').height() - 30,\r\n width: $('#vidboxModal').width()\r\n };\r\n var l_objLocalVideo = $('#localVideo');\r\n var l_objStream = $('#' + a_objReturn.stream.id());\r\n var l_dblRatio = null;\r\n\r\n if (streamResolution.width != null && streamResolution.height != null) {\r\n // console.log('got streamResolution... possible flash browser');\r\n\r\n l_dblRatio = streamResolution.width / streamResolution.height;\r\n var l_intHeightCalc = Math.floor(l_objTarget.width / l_dblRatio);\r\n\r\n if (l_intHeightCalc > l_objTarget.height) {\r\n l_objLocalVideo.height(l_objTarget.height);\r\n l_objLocalVideo.width(l_objTarget.height * l_dblRatio);\r\n\r\n l_objStream.height(l_objTarget.height);\r\n l_objStream.width(l_objTarget.height * l_dblRatio);\r\n } else {\r\n l_objLocalVideo.width(l_objTarget.width);\r\n l_objLocalVideo.height(l_intHeightCalc);\r\n\r\n l_objStream.width(l_objTarget.width);\r\n l_objStream.height(l_intHeightCalc);\r\n }\r\n\r\n } else {\r\n var l_objLocalVideo = $('#localVideo');\r\n var l_objStream = $('#' + a_objReturn.stream.id())[0];\r\n // console.log('no video resolution... possible non-flash browser', {\r\n // StreamId: '#' + a_objReturn.stream.id(),\r\n //Width: l_objStream.videoWidth,\r\n //Height: l_objStream.videoHeight\r\n //});\r\n\r\n if (l_objStream != null && l_objStream.videoWidth != null && l_objStream.videoHeight != null) {\r\n if (l_objStream.videoWidth < l_objStream.videoHeight) {\r\n l_objLocalVideo.css('width', '');\r\n l_objLocalVideo.css('height', '100%');\r\n\r\n $('#' + a_objReturn.stream.id()).css('width', '');\r\n $('#' + a_objReturn.stream.id()).css('height', '100%');\r\n } else {\r\n l_objLocalVideo.css('width', '100%');\r\n l_objLocalVideo.css('height', '');\r\n\r\n $('#' + a_objReturn.stream.id()).css('width', '100%');\r\n $('#' + a_objReturn.stream.id()).css('height', '');\r\n }\r\n }\r\n\r\n }\r\n }\r\n\r\n document.getElementById(a_objReturn.stream.id()).addEventListener('resize', function (event) {\r\n CalcWindow();\r\n });\r\n document.getElementById('localVideo').addEventListener('resize', function (event2) {\r\n CalcWindow();\r\n });\r\n document.getElementById('vidboxModal').addEventListener('resize', function (event2) {\r\n CalcWindow();\r\n });\r\n\r\n $rootScope.$on('VidboxModalResizeEnd', function (event, data) {\r\n CalcWindow();\r\n });\r\n });\r\n }, function () {\r\n $scope.isLoading = false;\r\n // console.log('initPlayerStream failed');\r\n });\r\n } else {\r\n\r\n var CalcWindowLocal = function () {\r\n var l_objLocalVideo = $('#localVideo');\r\n var l_objStream = $('#localVideo').children();\r\n // console.log('no video resolution... possible non-flash browser', {\r\n // StreamId: $('#localVideo').children()[0],\r\n //Width: l_objStream.width(),\r\n //Height: l_objStream.height()\r\n //});\r\n\r\n if (l_objStream.width() < l_objStream.height()) {\r\n l_objLocalVideo.css('width', '');\r\n l_objLocalVideo.css('height', '100%');\r\n\r\n $('#localVideo').children().css('width', '');\r\n $('#localVideo').children().css('height', '100%');\r\n } else {\r\n l_objLocalVideo.css('width', '100%');\r\n l_objLocalVideo.css('height', '');\r\n\r\n $('#localVideo').children().css('width', '100%');\r\n $('#localVideo').children().css('height', '');\r\n }\r\n\r\n }\r\n\r\n // console.log('Listeners');\r\n document.getElementById($('#localVideo').children().attr('id')).addEventListener('resize', function (event) {\r\n CalcWindowLocal();\r\n });\r\n document.getElementById('localVideo').addEventListener('resize', function (event2) {\r\n CalcWindowLocal();\r\n });\r\n document.getElementById('vidboxModal').addEventListener('resize', function (event2) {\r\n CalcWindowLocal();\r\n });\r\n\r\n $rootScope.$on('VidboxModalResizeEnd', function (event, data) {\r\n CalcWindowLocal();\r\n });\r\n\r\n\r\n CalcWindowLocal();\r\n }\r\n\r\n }\r\n } else {\r\n $scope.videoId = null\r\n }\r\n }\r\n\r\n function _getParams() {\r\n\r\n if ($scope.typeId == 1) {\r\n return {\r\n url: \"https://\" + userService.getTeamProperties().s_name + \".echofin.co/stream/youtube\",\r\n type: \"youtube\",\r\n params: {\r\n youtubeUrl: \"https://www.youtube.com/embed/\" + $scope.videoId + \"?autoplay=1\",\r\n youtubeID: $scope.videoId,\r\n },\r\n data: {\r\n youtubeID: $scope.videoId,\r\n }\r\n }\r\n } else {\r\n return {\r\n url: \"https://\" + userService.getTeamProperties().s_name + \".echofin.co/stream/broadcast\",\r\n type: \"broadcast\",\r\n params: {},\r\n data: {\r\n token: tokenService.model.access_token\r\n }\r\n }\r\n }\r\n\r\n }\r\n\r\n }\r\n }\r\n\r\n }])","'use strict';\r\nangular\r\n .module('chat.invites', [])\r\n .service('InvitesService', InvitesService)\r\n .directive('invitesPrompt', invitesPrompt)\r\n .directive('invitesTinyPrompt', invitesTinyPrompt)\r\n .directive('invitesModal', invitesModal)\r\n\r\nInvitesService.$inject = ['$http', '$window'];\r\nfunction InvitesService($http, $window) {\r\n var _service = {\r\n Send: _send\r\n }\r\n return _service\r\n\r\n function _send(emails) {\r\n return $http\r\n .post('https://auth.echofin.co/api/account/invite', {\r\n emails: emails\r\n });\r\n }\r\n}\r\n\r\ninvitesPrompt.$inject = ['userService', 'chatRoomService'];\r\nfunction invitesPrompt(userService, chatRoomService) {\r\n\r\n return {\r\n templateUrl: 'invites-prompt.html',\r\n link: function (scope, elem) {\r\n\r\n if (userService.getTeamProperties().b_closedCommunity) {\r\n elem.hide()\r\n }\r\n },\r\n controller: function ($scope) {\r\n $scope.OpenInviteModal = function () {\r\n $(\"#invite-modal\").modal(\"show\")\r\n }\r\n // console.log($scope.currentUser)\r\n $scope.isAdmin = ($scope.currentUser && $scope.currentUser.type == 1);\r\n\r\n var chatRoom = chatRoomService.getCurrentRoom();\r\n //// console.debug(\"chatRoomchatRoomchatRoomchatRoom\", chatRoom)\r\n $scope.isTradingFloorRoom = (chatRoom.s_name == \"TradingFloor\");\r\n $scope.isSignalsRoom = (chatRoom.s_name == \"Signals\");\r\n }\r\n }\r\n}\r\n\r\ninvitesTinyPrompt.$inject = ['$sce', 'userService'];\r\nfunction invitesTinyPrompt($sce, userService) {\r\n\r\n return {\r\n scope: {\r\n forex: \"=\"\r\n },\r\n template: \"
    {{label}}\",\r\n link: function (scope, elem) {\r\n\r\n if (scope.forex) {\r\n scope.target = \"_blank\"\r\n scope.label = \"Create your team\"\r\n scope.link = $sce.trustAsUrl(\"https://echofin.co/register.html\")\r\n scope.target = \"_blank\"\r\n //scope.style = \"background-color: #31acff; border-color: #03A9F4;\"\r\n //scope.label = \"Download desktop app\"\r\n //scope.link = $sce.trustAsUrl(\"https://cdn.echofin.co/downloads/Echofin_Desktop_Setup_Latest.exe\")\r\n }\r\n else {\r\n scope.label = \"Invite your friends\"\r\n elem.on(\"click\", function (e) {\r\n scope.OpenInviteModal()\r\n e.preventDefault()\r\n })\r\n }\r\n\r\n if (userService.getTeamProperties().b_closedCommunity) {\r\n elem.hide()\r\n }\r\n\r\n },\r\n controller: function ($scope) {\r\n $scope.OpenInviteModal = function () {\r\n $(\"#invite-modal\").modal(\"show\")\r\n }\r\n }\r\n }\r\n}\r\n\r\ninvitesModal.$inject = ['userService'];\r\nfunction invitesModal(userService) {\r\n\r\n function validateEmail(email) {\r\n var re = /^(([^<>()\\[\\]\\\\.,;:\\s@\"]+(\\.[^<>()\\[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/;\r\n return re.test(email);\r\n }\r\n\r\n function validateEmails(emails) {\r\n\r\n var _errors = [];\r\n var _emails = [];\r\n\r\n if (!emails.length) {\r\n return false;\r\n }\r\n\r\n var _inviteEmails = angular.copy(emails).split(\",\");\r\n\r\n for (var i = 0; i < _inviteEmails.length; i++) {\r\n var _email = _inviteEmails[i].trim()\r\n\r\n if (validateEmail(_email)) {\r\n _emails.push(_email);\r\n }\r\n else {\r\n _errors.push(_email);\r\n }\r\n }\r\n\r\n return {\r\n errors: _errors,\r\n emails: _emails,\r\n }\r\n\r\n }\r\n\r\n return {\r\n templateUrl: 'invites-modal.html',\r\n scope: {},\r\n link: function (scope, elem) {\r\n\r\n $('#invite-modal').on('show.bs.modal', function (e) {\r\n scope.success = false\r\n scope.isCopied = false\r\n scope.model = {\r\n emails: null\r\n }\r\n })\r\n\r\n },\r\n controller: function ($scope, $http, $window, InvitesService) {\r\n\r\n $scope.$on('initial', function (event, data) {\r\n var props = userService.getTeamProperties()\r\n $scope.teamName = props.s_name\r\n $scope.teamUrl = props.teamUrl\r\n })\r\n $scope._errors = []\r\n $scope._emails = []\r\n\r\n $scope.CloseInviteModal = function () {\r\n $scope.isCopied = false\r\n $(\"#invite-modal\").modal(\"hide\")\r\n }\r\n\r\n $scope.SendInviteModal = function () {\r\n\r\n $scope.error = null\r\n\r\n if (!$scope.model.emails) {\r\n $scope.error = \"Please input a few emails\"\r\n return false;\r\n }\r\n\r\n var _validated = validateEmails($scope.model.emails)\r\n if (_validated.errors.length) {\r\n $scope.error = \"Invalid Emails: \" + _validated.errors.join(\", \")\r\n return;\r\n }\r\n\r\n $scope.loading = true\r\n\r\n InvitesService\r\n .Send(_validated.emails)\r\n .then(function (data) {\r\n if (data) {\r\n\r\n }\r\n $scope.success = true\r\n }, function (err) {\r\n $scope.error = err.message || err.exceptionMessage\r\n })\r\n .finally(function () {\r\n $scope.loading = false\r\n })\r\n\r\n }\r\n }\r\n }\r\n}\r\n\r\n","angular\r\n .module('chat.introtutorial', [])\r\n .service('IntroTutorialService', IntroTutorialService)\r\n\r\nIntroTutorialService.$inject = ['$window', 'userService']\r\n\r\nfunction IntroTutorialService($window, userService) {\r\n\r\n var service = {\r\n setup: setup,\r\n runIfNotViewed: runIfNotViewed,\r\n run: run,\r\n }\r\n\r\n return service\r\n\r\n function setup() {\r\n window.introtutorial_enabled = true;\r\n/*\r\n $(document)\r\n .delegate('.enjoyhint_skip_btn', 'click', function () {\r\n localStorage.setItem(\"tutorialViewed\", true);\r\n });\r\n\r\n $(document)\r\n .delegate('.enjoyhint_close_btn', 'click', function () {\r\n localStorage.setItem(\"tutorialViewed\", true);\r\n });*/\r\n }\r\n\r\n function runIfNotViewed() {\r\n var viewed = localStorage.getItem(\"tutorialViewed\")\r\n if (viewed) return\r\n run()\r\n }\r\n\r\n function run() {\r\n\r\n //var l_strTeamKey = userService.getTeamProperties().s_key;\r\n //if (l_strTeamKey == '875960cc') { // || l_strTeamKey == '450d9432') { // jesus\r\n // return\r\n //}\r\n\r\n //var usertype = userService.getCurrentUser().type\r\n\r\n //var enjoyhint_instance = new EnjoyHint({});\r\n\r\n //var userSteps = [{\r\n // 'next .sidebar-username': 'User preferences: change your profile pic, mute notifications, etc',\r\n // 'shape': 'circle',\r\n // 'radius': 70\r\n // },\r\n // {\r\n // 'next .nav-sidebar': 'Available rooms:
    ' +\r\n // '(if there is a lock icon next to a room, then it is a pay-to-access room
    ' +\r\n // 'if there is an eye icon, then only admins can write)'\r\n // },\r\n // {\r\n // 'next #btnTools': 'Team directory: who is online, mentions, uploads, etc
    ' +\r\n // '(click on any user to send a Direct Message)',\r\n // 'shape': 'circle',\r\n // 'radius': 40\r\n // },\r\n // {\r\n // 'next .navbar-right.hidden-xs.btnAlert.header-button.highlight ': 'Widgets section',\r\n // 'shape': 'circle',\r\n // 'radius': 40\r\n // },\r\n // {\r\n // 'next .footer-invite': 'Invite your fellow traders and friends',\r\n // 'shape': 'circle',\r\n // 'radius': 60\r\n // },\r\n // {\r\n // 'skip .chatDiv': 'Type your message here
    ' +\r\n // 'add emojis, share links and images',\r\n // \"skipButton\": {\r\n // text: \"Got it!\"\r\n // }\r\n // }\r\n //];\r\n\r\n //var adminSteps = [{\r\n // 'next .sidebar-username': 'User preferences: change your profile pic, mute notifications, etc',\r\n // 'shape': 'circle',\r\n // 'radius': 70\r\n // },\r\n // {\r\n // 'next .nav-sidebar': 'Rooms & Services section:
    ' +\r\n // '(you can add as many as you want
    ' +\r\n // 'as well as different types
    ' +\r\n // 'through the admin dashboard)'\r\n // },\r\n // {\r\n // 'next #btnDashboard': 'Access to your administration dashboard
    ' +\r\n // '(where all the interesting stuff take place)',\r\n // 'shape': 'circle',\r\n // 'radius': 70\r\n // },\r\n // {\r\n // 'next #btnStartStream': 'Start a video stream or a screen sharing session',\r\n // 'shape': 'circle',\r\n // 'radius': 70\r\n // },\r\n // {\r\n // 'next #btnTools': 'Team directory: who is online, mentions, uploads, etc
    ' +\r\n // '(click on any user to send a Direct Message, block, ban, etc)',\r\n // 'shape': 'circle',\r\n // 'radius': 40\r\n // },\r\n // {\r\n // 'next .navbar-right.hidden-xs.btnAlert.header-button.highlight ': 'Widgets section. You can install more
    ' +\r\n // 'from the admin dashboard',\r\n // 'shape': 'circle',\r\n // 'radius': 40\r\n // },\r\n // {\r\n // 'next .chatDiv': 'Type your message here
    ' +\r\n // 'add emojis, share links and images'\r\n // },\r\n // {\r\n // 'skip #addon_Signal': 'Click the megaphone icon to publish signals
    ' +\r\n // '(you can select who can use this from the admin panel)',\r\n // \"skipButton\": {\r\n // text: \"Got it!\"\r\n // }\r\n // }\r\n //];\r\n //if (usertype == 1) {\r\n // console.log(\"show admin tutorial\")\r\n //}\r\n //var enjoyhint_script_steps = (usertype == 1 ? adminSteps : userSteps);\r\n\r\n //enjoyhint_instance.set(enjoyhint_script_steps);\r\n //enjoyhint_instance.run();\r\n }\r\n}","'use strict';\r\nangular\r\n .module('chat.brokers', [])\r\n .service('brokersService', brokersService)\r\n .directive('brokersSidebar', brokersSidebar)\r\n .directive('brokersNewModal', brokersNewModal)\r\n\r\nbrokersService.$inject = [];\r\nfunction brokersService() {\r\n\r\n var _service = {\r\n brokers: [],\r\n load: _load,\r\n }\r\n\r\n function _load(data) {\r\n\r\n if (!data) {\r\n brokers = [];\r\n return\r\n }\r\n\r\n var _temp\r\n if (_service.brokers) {\r\n _temp = angular.copy(_service.brokers)\r\n }\r\n\r\n _service.brokers = _.map(data, function (o) {\r\n\r\n var _t = _.find(_temp, { s_key: o.s_key })\r\n\r\n if (_t) {\r\n o.isVisible = _t.isVisible\r\n o.serviceURL = _t.serviceURL\r\n }\r\n\r\n o._source = o.s_url;\r\n o.s_url = \"$\" + encodeURI(o.s_title.toLowerCase())// + \"-\" + o.s_key\r\n return o\r\n })\r\n }\r\n\r\n return _service\r\n}\r\n\r\nbrokersSidebar.$inject = ['brokersService', '$timeout', 'chatRoomService'];\r\nfunction brokersSidebar(brokersService, $timeout, chatRoomService) {\r\n\r\n return {\r\n templateUrl: 'brokers-sidebar.html',\r\n scope: {\r\n selected: \"=\",\r\n brokersEnabled: \"=\",\r\n myBrokers: \"@\",\r\n },\r\n link: function (scope, elem) {\r\n\r\n },\r\n controller: function ($rootScope, $scope) {\r\n\r\n\r\n _loadBrokers()\r\n\r\n function _loadBrokers() {\r\n\r\n $scope.myBrokers = [];\r\n\r\n $scope.myBrokers = _.chain(brokersService.brokers)\r\n .filter({ b_isPromo: true })\r\n .sortBy(\"s_title\")\r\n .value()\r\n\r\n $scope.myBrokers.push.apply($scope.myBrokers, _.chain(brokersService.brokers)\r\n .filter({ b_isPromo: false || null })\r\n .sortBy(\"s_title\")\r\n .value())\r\n\r\n }\r\n\r\n $scope.currentURL = null\r\n\r\n $scope.openNewBrokerModal = function () {\r\n $(\"#brokers-new-modal\").modal(\"show\")\r\n }\r\n\r\n $scope.$on(\"brokers-refresh\", function (data) {\r\n _loadBrokers()\r\n })\r\n\r\n $scope.openBroker = function (broker) {\r\n\t\t\t\tconsole.log(\"openBroker\");\r\n chatRoomService.changeRoom(broker);\r\n $rootScope.$broadcast('ChangeMessageCount', []);\r\n }\r\n }\r\n\r\n }\r\n}\r\n\r\n\r\nbrokersNewModal.$inject = ['$http', '$timeout', 'brokersService'];\r\nfunction brokersNewModal($http, $timeout, brokersService) {\r\n\r\n var re_weburl = new RegExp(\r\n \"^\" +\r\n // protocol identifier\r\n \"(?:(?:https?|ftp)://)\" +\r\n // user:pass authentication\r\n \"(?:\\\\S+(?::\\\\S*)?@)?\" +\r\n \"(?:\" +\r\n // IP address exclusion\r\n // private & local networks\r\n \"(?!(?:10|127)(?:\\\\.\\\\d{1,3}){3})\" +\r\n \"(?!(?:169\\\\.254|192\\\\.168)(?:\\\\.\\\\d{1,3}){2})\" +\r\n \"(?!172\\\\.(?:1[6-9]|2\\\\d|3[0-1])(?:\\\\.\\\\d{1,3}){2})\" +\r\n // IP address dotted notation octets\r\n // excludes loopback network 0.0.0.0\r\n // excludes reserved space >= 224.0.0.0\r\n // excludes network & broacast addresses\r\n // (first & last IP address of each class)\r\n \"(?:[1-9]\\\\d?|1\\\\d\\\\d|2[01]\\\\d|22[0-3])\" +\r\n \"(?:\\\\.(?:1?\\\\d{1,2}|2[0-4]\\\\d|25[0-5])){2}\" +\r\n \"(?:\\\\.(?:[1-9]\\\\d?|1\\\\d\\\\d|2[0-4]\\\\d|25[0-4]))\" +\r\n \"|\" +\r\n // host name\r\n \"(?:(?:[a-z\\\\u00a1-\\\\uffff0-9]-*)*[a-z\\\\u00a1-\\\\uffff0-9]+)\" +\r\n // domain name\r\n \"(?:\\\\.(?:[a-z\\\\u00a1-\\\\uffff0-9]-*)*[a-z\\\\u00a1-\\\\uffff0-9]+)*\" +\r\n // TLD identifier\r\n \"(?:\\\\.(?:[a-z\\\\u00a1-\\\\uffff]{2,}))\" +\r\n // TLD may end with dot\r\n \"\\\\.?\" +\r\n \")\" +\r\n // port number\r\n \"(?::\\\\d{2,5})?\" +\r\n // resource path\r\n \"(?:[/?#]\\\\S*)?\" +\r\n \"$\", \"i\"\r\n );\r\n\r\n function validateUrl(url) {\r\n return re_weburl.test(url)\r\n }\r\n\r\n return {\r\n templateUrl: 'brokers-modal.html',\r\n scope: {\r\n term: \"@\",\r\n tempBrokers: \"@\",\r\n editMode: \"@\",\r\n customEnabled: \"@\",\r\n },\r\n link: function (scope, elem) {\r\n\r\n $('#brokers-modal').on('show.bs.modal', function (e) {\r\n scope.model = {}\r\n scope.editMode = {};\r\n })\r\n },\r\n controller: function ($rootScope, $scope, brokersService) {\r\n\r\n $scope.tempBrokers = [];\r\n $scope.editMode = {};\r\n $scope.term = null;\r\n\r\n var filterTextTimeout;\r\n\r\n $scope.$watch(function () {\r\n return $scope.term\r\n }, function (val) {\r\n if (filterTextTimeout) {\r\n $timeout.cancel(filterTextTimeout);\r\n }\r\n\r\n $scope.brokers = [];\r\n\r\n if (!val) {\r\n return\r\n }\r\n\r\n if (val.length < 2) {\r\n return\r\n }\r\n\r\n filterTextTimeout = $timeout(function () {\r\n\r\n $scope.searching = true\r\n $http\r\n .post(\"api/brokers/search\", {\r\n term: $scope.term,\r\n })\r\n .then(function (response) {\r\n $scope.brokers = response.data\r\n })\r\n .finally(function () {\r\n $scope.searching = false\r\n })\r\n\r\n }, 250);\r\n })\r\n\r\n\r\n $scope.$watch(function () {\r\n return brokersService.brokers\r\n }, function (val) {\r\n $scope.tempBrokers = _.chain(val)\r\n .filter({ b_isPromo: false || null })\r\n .sortBy(\"s_title\")\r\n .value()\r\n\r\n })\r\n\r\n $scope.AddPredifinedBroker = function (broker) {\r\n var _val = true;\r\n _.forEach($scope.editMode, function (value, key) {\r\n if (value) {\r\n var _conf = $scope.confirmBroker(key)\r\n if (!_conf) {\r\n _val = false;\r\n return\r\n }\r\n }\r\n });\r\n\r\n if (_val) {\r\n var _newBroker = {\r\n s_title: null,\r\n fkn_broker: broker.pkn_id,\r\n }\r\n $scope.tempBrokers.unshift(_newBroker)\r\n $scope.editMode[0] = broker.s_name;\r\n }\r\n\r\n }\r\n\r\n $scope.AddCustomBroker = function () {\r\n\r\n $scope.error = false;\r\n\r\n if (!$scope.model.customBrokerTitle || !$scope.model.customBrokerURL) {\r\n $scope.error = {\r\n type: \"warning\",\r\n message: \"You have to type a terminal name and a proper url\"\r\n }\r\n return false;\r\n }\r\n\r\n if (_.findIndex($scope.tempBrokers, function (o, k) {\r\n if (!o.s_title) return false;\r\n return o.s_title.toLowerCase() == $scope.model.customBrokerTitle.toLowerCase();\r\n }) != -1) {\r\n $scope.error = {\r\n type: \"warning\",\r\n message: \"Terminal with name: \" + $scope.model.customBrokerTitle + \" exists\"\r\n }\r\n return false;\r\n }\r\n\r\n\r\n var _newBroker = {\r\n s_title: $scope.model.customBrokerTitle,\r\n s_url: $scope.model.customBrokerURL,\r\n }\r\n $scope.tempBrokers.unshift(_newBroker)\r\n $scope.model.customBrokerTitle = null\r\n $scope.model.customBrokerURL = null\r\n }\r\n\r\n $scope.DeleteBroker = function (index) {\r\n\r\n $scope.tempBrokers.splice(index, 1);\r\n }\r\n\r\n $scope.confirmBroker = function (index) {\r\n $scope.error = false;\r\n\r\n if (_.findIndex($scope.tempBrokers, function (o, k) {\r\n if (!o.s_title) return false;\r\n return o.s_title.toLowerCase() == $scope.editMode[index].toLowerCase() && index != k;\r\n }) != -1) {\r\n $scope.error = {\r\n type: \"warning\",\r\n message: \"Terminal with name: \" + $scope.editMode[index] + \" exists\"\r\n }\r\n return false;\r\n }\r\n\r\n $scope.tempBrokers[index].s_title = $scope.editMode[index];\r\n $scope.editMode[index] = null\r\n return true;\r\n }\r\n\r\n $scope.cancelBroker = function (broker, index) {\r\n $scope.editMode[index] = null\r\n if (broker.s_title == null) {\r\n $scope.DeleteBroker(index)\r\n }\r\n }\r\n\r\n $scope.SaveBrokers = function () {\r\n\r\n var _val = true;\r\n _.forEach($scope.editMode, function (value, key) {\r\n if (value) {\r\n var _conf = $scope.confirmBroker(key)\r\n if (!_conf) {\r\n _val = false;\r\n return\r\n }\r\n }\r\n });\r\n\r\n if (_val) {\r\n\r\n $scope.error = null\r\n\r\n $scope.loading = true\r\n\r\n $http\r\n .post(\"api/brokers\", $scope.tempBrokers)\r\n .then(function (response) {\r\n brokersService.load(response.data);\r\n $scope.closeNewBrokerModal()\r\n }, function (err) {\r\n $scope.error = {\r\n type: \"danger\",\r\n message: err.Message || err.ExceptionMessage\r\n }\r\n })\r\n .finally(function () {\r\n $scope.loading = false\r\n })\r\n }\r\n }\r\n\r\n $scope.closeNewBrokerModal = function () {\r\n $(\"#brokers-new-modal\").modal(\"hide\")\r\n $rootScope.$broadcast(\"brokers-refresh\")\r\n }\r\n }\r\n }\r\n}","'use strict';\r\n\r\nangular\r\n .module('chat.right-panel', [])\r\n .directive('rightPanel', [\r\n '$rootScope', 'userService', 'chatRoomService', 'pushService', '$location', '$sce', '$compile',\r\n function ($rootScope, userService, chatRoomService, pushService, $location, $sce, $compile) {\r\n return {\r\n replace: true,\r\n templateUrl: 'right-panel.html',\r\n transclude: true,\r\n controller: function ($scope, $element) {\r\n\r\n window.addEventListener(\"message\", receiveMessage, false);\r\n\r\n function receiveMessage(event) {\r\n // console.log(\"receiveMessage\", event.data);\r\n //event: {\r\n // key: \"\",\r\n // type: \"\",\r\n //}\r\n\r\n if (!event.data.key) return;\r\n var i = _.findIndex($scope.rightWidgets, function (w) {\r\n return (w.key.indexOf(event.data.key) === 0);\r\n });\r\n if (i === -1) return;\r\n if ($scope.rightWidgets[i].key === $scope.rightWidgetSelected) return;\r\n\r\n switch (event.data.type) {\r\n case \"notify-count\":\r\n $scope.rightWidgets[i].notify++;\r\n break;\r\n case \"notify-alert\":\r\n $scope.rightWidgets[i].notify = -1;\r\n break;\r\n }\r\n\r\n $scope.$apply();\r\n }\r\n\r\n $scope.loadFiles = function (refresh) {\r\n $scope.filesLoading = true\r\n userService\r\n .loadFiles(refresh)\r\n .then(function () { })\r\n .finally(function () {\r\n $scope.filesLoading = false\r\n })\r\n }\r\n\r\n $scope.loadMentions = function (refresh) {\r\n $scope.mentionsLoading = true\r\n userService\r\n .loadMentions(refresh)\r\n .then(function () { })\r\n .finally(function () {\r\n $scope.mentionsLoading = false\r\n })\r\n }\r\n\r\n $scope.$watch(function () {\r\n return userService.getFiles()\r\n }, function (n, o) {\r\n $scope.files = n\r\n })\r\n\r\n $scope.$watch(function () {\r\n return userService.getMentions()\r\n }, function (n, o) {\r\n $scope.mentions = n\r\n })\r\n\r\n //$scope.$on('initial', function (event, data) {\r\n // $scope.loadFiles()\r\n // $scope.loadMentions()\r\n //})\r\n\r\n $scope.ChangeTab = function (tabIndex) {\r\n switch (tabIndex) {\r\n case 1:\r\n break;\r\n case 2:\r\n $scope.loadFiles(true)\r\n break;\r\n case 3:\r\n $scope.loadMentions(true)\r\n break;\r\n }\r\n };\r\n\r\n },\r\n link: function ($scope, $element) {\r\n $scope.rightWidgetSelected = null;\r\n $scope.isadmin = false;\r\n $scope.alertsVisible = false;\r\n $scope.rightWidgets = [];\r\n $scope.wgaVisible = false;\r\n $scope.pluginsVisible = false;\r\n $scope.getRoomName = function (a_strRoomKey) {\r\n var l_objRoom = chatRoomService.findRoomByKey(a_strRoomKey);\r\n // console.log('getRoomName', a_strRoomKey, l_objRoom);\r\n if (l_objRoom != null)\r\n return l_objRoom.name;\r\n else\r\n return null;\r\n }\r\n\r\n $scope.widgetUpgrade = function (widget) {\r\n\r\n $rootScope.$broadcast('LoadPayment', {\r\n chatroom: {\r\n s_key: \"widget-\" + widget.config.roomKey\r\n },\r\n config: {\r\n havePendingSubscriptions: true,\r\n type: 2\r\n }\r\n });\r\n }\r\n $scope.loadWidget = function (w) {\r\n\r\n $scope.rightWidgetSelected = w.key;\r\n w.notify = null;\r\n\r\n if (w.trustUrl) return; //widget is already loaded\r\n\r\n if (!w.config.hasAdvancedConfig) {\r\n _loadWidget(w);\r\n } else {\r\n _loadCustomWidget(w);\r\n }\r\n\r\n }\r\n\r\n function _loadWidget(w) {\r\n w.trustUrl = $sce.trustAsResourceUrl(\"https://\" + w.url);\r\n }\r\n\r\n function _loadCustomWidget(w) {\r\n\r\n try {\r\n var xhr = new XMLHttpRequest();\r\n\r\n xhr.open('GET', \"https://\" + w.url);\r\n xhr.onreadystatechange = function () {\r\n if (this.readyState === this.DONE) {\r\n if (this.status === 200) {\r\n // this.response is a Blob, because we set responseType above\r\n var data_url = URL.createObjectURL(this.response);\r\n w.trustUrl = $sce.trustAsResourceUrl(data_url);\r\n } else {\r\n w.iframeError = true;\r\n }\r\n }\r\n };\r\n xhr.responseType = 'blob';\r\n //xhr.setRequestHeader(\"Content-type\", \"application/x-www-form-urlencoded\");\r\n xhr.setRequestHeader(\"x-token\", w.token);\r\n xhr.send();\r\n\r\n } catch (e) {\r\n w.iframeError = true;\r\n }\r\n }\r\n\r\n $scope.$on('UserStatusChange',\r\n function (event, data) {\r\n // console.log('rightpanels UserStatusChange', data);\r\n $scope.$apply();\r\n });\r\n $scope.$on('CurrentUserUpdate',\r\n function (event, data) {\r\n //$scope.currentUser = data.user;\r\n // if (data.action == 'update')\r\n //userService.getUserByClearKey(data.user.s_clearKey) = data.user;\r\n // console.log('rightpanels CurrentUserUpdate', data);\r\n //$scope.$apply();\r\n });\r\n $scope.GetRoomUrl = function (a_strRoomKey) {\r\n var l_objChatRoom = chatRoomService.findRoomByClearKey(a_strRoomKey);\r\n if (l_objChatRoom != null) {\r\n return l_objChatRoom.s_url;\r\n } else {\r\n return null;\r\n }\r\n }\r\n\r\n $scope.$on('initial',\r\n function (event, data) {\r\n var l_objUserSettings = userService.getSettings();\r\n\r\n $scope.users = userService.getAll();\r\n $scope.alertsVisible = true;\r\n\r\n _.each($scope.rightWidgets,\r\n function (w, index) {\r\n if (w.config.enableCallback && index) {\r\n $scope.loadWidget(w);\r\n }\r\n });\r\n\r\n if ($scope.rightWidgets.length) {\r\n $scope.loadWidget($scope.rightWidgets[0]);\r\n }\r\n\r\n var l_objUser = userService.getCurrentUser();\r\n\r\n $scope.userKey = l_objUser.s_key;\r\n $scope.isadmin = (l_objUser.type == 1);\r\n\r\n var s_key = userService.getTeamProperties().s_key\r\n\r\n //if (s_key == '875960cc' || s_key == '1a6638d0') {\r\n // $scope.wgaVisible = true;\r\n //} else {\r\n $scope.pluginsVisible = true;\r\n //}\r\n\r\n if (!$scope.alertsVisible) {\r\n var speed = 100,\r\n chatDivPadding = 15;\r\n $('#dvRight').css('width', '0px');\r\n $('.right-pad').css('padding-right', '0');\r\n $('.right-marg').css('margin-right', '0');\r\n $('.chatDiv').css('right', chatDivPadding.toString() + 'px');\r\n $('.alertDiv').css('right', '0');\r\n $(\"#dvAlerts\").css('display', 'none');\r\n $(\".btnAlert\").css('display', 'none');\r\n\r\n\r\n } else {\r\n $(\".btnAlert\").css('display', 'block');\r\n };\r\n\r\n });\r\n $scope.$on('ChangeRoom',\r\n function (event, data) { });\r\n\r\n var bLazy = null;\r\n\r\n var _loadBLazy = function () {\r\n bLazy = new Blazy({\r\n container: '#dvTools',\r\n src: 'a-blazy',\r\n success: function (ele) {\r\n // console.log('image loaded');\r\n },\r\n error: function (ele, msg) {\r\n // console.log('image error');\r\n }\r\n });\r\n };\r\n\r\n $scope.flterNameChange = function () {\r\n _loadBLazy();\r\n };\r\n\r\n }\r\n }\r\n }\r\n ]);","angular.module('chat.templates', []).run(['$templateCache', function($templateCache) {$templateCache.put('alert-refresh.html','
    \\r\\n

    Refresh Required

    \\r\\n

    The application has been updated.
    Please refresh your browser.

    \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n\\r\\n');\n$templateCache.put('alertstream.html','
    \\r\\n \\r\\n LIVE\\r\\n \\r\\n
    ');\n$templateCache.put('brokers-modal.html','
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n

    Manage Brokers

    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n {{error.message}}\\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n\\r\\n
    \\r\\n
    \\r\\n Search for brokers\\r\\n or add your own\\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n\\r\\n find your broker\\'s
    web trading terminal using
    the search bar above\\r\\n
    \\r\\n
    \\r\\n \\r\\n {{broker.s_name}}
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n\\r\\n
    \\r\\n
    \\r\\n Add your own broker\\r\\n or add from list\\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n \\r\\n https://\\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 My Terminals\\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n you have no brokers
    in your list yet\\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
    \\r\\n
    \\r\\n \\r\\n {{myBroker.s_title}}\\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
    \\r\\n
    \\r\\n');\n$templateCache.put('brokers-sidebar.html','
  • \\r\\n WEBTRADER\\r\\n \\r\\n
  • \\r\\n
  • \\r\\n No brokers were added\\r\\n
  • \\r\\n
  • \\r\\n \\r\\n \\r\\n \\r\\n {{myBroker.s_title}}\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n
  • ');\n$templateCache.put('direct-messages.html','
  • \\r\\n \\r\\n person_outline {{user.userName}}\\r\\n {{user.n_count}}\\r\\n \\r\\n \\r\\n
  • ');\n$templateCache.put('header-nav.html','\\r\\n');\n$templateCache.put('invites-modal.html','
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n

    Invite your friends

    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n Your invites have been sent!\\r\\n
    \\r\\n
    \\r\\n \\r\\n Loading...\\r\\n
    \\r\\n
    \\r\\n

    \\r\\n Enter the email addresses (comma separated).\\r\\n

    \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n

    \\r\\n Invite people to {{teamName}}
    \\r\\n Share this link with others to let them join the team\\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

    {{error}}

    \\r\\n
    \\r\\n\\r\\n
    \\r\\n
    \\r\\n \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    ');\n$templateCache.put('invites-prompt.html','
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n\\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n support\\r\\n BOT\\r\\n a few moments ago\\r\\n \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    File Uploaded:
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n Hey there team owner!
    \\r\\n \\u039Cake sure to download the\\r\\n \\r\\n windows desktop,\\r\\n \\r\\n Android and\\r\\n \\r\\n iPhone mobile app so you won\\'t miss on the conversation!\\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    New Messages
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n

    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n support\\r\\n BOT\\r\\n a few moments ago\\r\\n \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    File Uploaded:
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n Did you know that our\\r\\n integrated billing feature gives you the ability to create pay-to-access chatrooms such as\\r\\n #Signals or\\r\\n #Webinars?\\r\\n
    So, there is no hassle in sending billing URLs to potential customers risking to loose them in the way.\\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 \\r\\n
    \\r\\n
    \\r\\n support\\r\\n BOT\\r\\n a few moments ago\\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n This is a read-only room, meaning only you the team owner and whoever you give administration rights to can post here.
    \\r\\n It is perfect for posting signals. Posting a signal is very easy and highly customizable. Here\\'s a demo signal:\\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    New Messages
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n

    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n support\\r\\n BOT\\r\\n a few moments ago\\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    SIGNAL
    \\r\\n
    BUY STOP:BTC/USD
    ENTRY:@1819
    TP:@1920
    This is a demo signal
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    New Messages
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n

    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n support\\r\\n BOT\\r\\n a few moments ago\\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n Nice right? To post a signal, you only need to click on the signal button on the bottom right of your chat area (next to the emoji icon).\\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    New Messages
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n

    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n support\\r\\n BOT\\r\\n a few moments ago\\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
    New Messages
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n

    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n support\\r\\n BOT\\r\\n a few moments ago\\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n Here is a short video showing how to use it: https://www.youtube.com/watch?v=0NHr1gZ4t34\\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    ');\n$templateCache.put('lock-modal.html','
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n

    Liquid Lounge bar is Closed

    \\r\\n
    \\r\\n
    \\r\\n Bar hours are between {{sStartTime}} EST - {{sEndTime}} EST Monday - Friday\\r\\n
    \\r\\n
    \\r\\n\\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n');\n$templateCache.put('luckyorange.html','');\n$templateCache.put('message-actions.html','
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n
    \\r\\n
    \\r\\n');\n$templateCache.put('messages-screen.html','
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n You are in Direct Message conversation
    with {{room.s_url}}\\r\\n
    \\r\\n
    \\r\\n
    New Messages
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n

    {{item.dayText}}

    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n \\r\\n ADMIN\\r\\n INSTRUCTOR\\r\\n MODERATOR\\r\\n BOT\\r\\n \\r\\n {{item.b_delivered}}\\r\\n {{item.dateParsed}}\\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n \\r\\n \\r\\n
    \\r\\n
    {{item.timesout}}\\r\\n\\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n New messages\\r\\n
    \\r\\n
    \\r\\n
    ');\n$templateCache.put('payment-modal.html','
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n Locked Chatroom\\r\\n
    \\r\\n
    \\r\\n Please contact team admin\\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n

    \\r\\n Unlock\\r\\n \\r\\n \\r\\n {{chatRoom.name.replace(\\'Widget \\',\\'\\')}}\\r\\n \\r\\n \\r\\n
    \\r\\n {{paymentTitle}}\\r\\n

    \\r\\n
    \\r\\n
    0\">\\r\\n Error!
    {{formData.errors[0]}}\\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n {{isTrial ? \\'Submiting For Trial\\' : \\'Submiting Payment\\'}}
    \\r\\n Please wait...\\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n {{isTrial ? \\'Trial Processing\\' : \\'Payment Processing\\'}}
    \\r\\n Feel free to close this window.
    \\r\\n We will alert you if there\\'s a problem with your payment.\\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n {{isTrial ? \\'Trial Activated\\' : \\'Payment Succeeded\\'}}
    \\r\\n You may close this window\\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n Payment Error
    \\r\\n An error was occured
    \\r\\n Please contact an admin to help you\\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 \\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 \\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 \\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 \\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
    \\r\\n \\r\\n Change Payment Details\\r\\n \\r\\n \\r\\n
    \\r\\n
    \\r\\n\\r\\n
    \\r\\n\\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n');\n$templateCache.put('pin-message.html','
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    ×
    \\r\\n
    \\r\\n
    ');\n$templateCache.put('popover.html','\\r\\n
    \\r\\n
    \\r\\n person_outline {{user.userName}}\\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \"\"\\r\\n
    \\r\\n \\r\\n
    ');\n$templateCache.put('privacy-policy-modal.html','
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n

    PRIVACY POLICY DISCLAIMER

    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n HAHAHA\\r\\n
    \\r\\n
    \\r\\n
    \\r\\n Decline\\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    ');\n$templateCache.put('private-room-modal.html','
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n

    \\r\\n Private room\\r\\n

    \\r\\n
    \\r\\n
    \\r\\n

    \\r\\n This room is accessible by selected members only. Please ask admin for access.\\r\\n

    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    ');\n$templateCache.put('right-panel.html','
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n 0\">{{w.notify}}\\r\\n \\r\\n \\r\\n \\r\\n {{w.label}}\\r\\n \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n There are no widgets enabled yet\\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n {{(w.config.hasBannerMessage)?w.config.bannerMessage:\\'This is a premium Widget\\'}}\\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    This widget has not been\\r\\n
    implemented correctly\\r\\n
    by the widget provider\\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
      \\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
    \\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
    \\r\\n
    \\r\\n @{{file.from.s_key==userKey ? \\'you\\' : file.from.userName}}\\r\\n \\r\\n {{file.dateParsed | vardate2: file.dateOffset}}\\r\\n \\r\\n
    \\r\\n
    \\r\\n \\r\\n \\r\\n \\r\\n shared with {{file.to != null && file.to.s_key==userKey ? \\'you\\' : file.to.userName}}\\r\\n
    \\r\\n
    \\r\\n {{GetRoomUrl(file.s_roomKey)}}\\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n Loading...\\r\\n
    \\r\\n
    \\r\\n \\r\\n
    No files\\r\\n
    were found\\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n Loading...\\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n @{{mention.userName}}\\r\\n {{mention.dateParsed | vardate2: mention.dateOffset}}\\r\\n
    \\r\\n
    \\r\\n {{mention.message}}\\r\\n
    \\r\\n
    \\r\\n {{mention.roomOrUserTo}}\\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    No mentions\\r\\n
    were found\\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    0\">\\r\\n Wall St. Jesus Only\\r\\n info\\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
    \\r\\n \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    ');\n$templateCache.put('rsk-modal.html','
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n

    RISK DISCLAIMER

    \\r\\n

    DISCLAIMER

    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n\\r\\n There is a risk of loss in trading stocks, commodity futures, options, and Forex. The risk can be substantial and therefore investors should carefully consider their financial suitability prior to trading. Past performance is not indicative of future performance. This website and any associated websites and peer-to-peer chatroom interface is for educational purposes only and should not be construed as an express or implied promise or guarantee that you will profit or that losses may be limited in any manner whatsoever. Please trade responsibly.\\r\\n

    \\r\\n Commodity Futures Trading Commission (CFTC) Rule 4.41 HYPOTHETICAL PERFORMANCE RESULTS HAVE MANY INHERENT LIMITATIONS, SOME OF WHICH ARE DESCRIBED BELOW. NO REPRESENTATION IS BEING MADE THAT ANY ACCOUNT WILL OR IS LIKELY TO ACHIEVE PROFITS OR LOSSES SIMILAR TO THOSE SHOWN. IN FACT, THERE ARE FREQUENTLY SHARP DIFFERENCES BETWEEN HYPOTHETICAL PERFORMANCE RESULTS AND THE ACTUAL RESULTS SUBSEQUENTLY ACHIEVED BY ANY PARTICULAR TRADING PROGRAM. ONE OF THE LIMITATIONS OF HYPOTHETICAL PERFORMANCE RESULTS IS THAT THEY ARE GENERALLY PREPARED WITH THE BENEFIT OF HINDSIGHT. IN ADDITION, HYPOTHETICAL TRADING DOES NOT INVOLVE FINANCIAL RISK, AND NO HYPOTHETICAL TRADING RECORD CAN COMPLETELY ACCOUNT FOR THE IMPACT OF FINANCIAL RISK IN ACTUAL TRADING. FOR EXAMPLE, THE ABILITY TO WITHSTAND LOSSES OR ADHERE TO A PARTICULAR TRADING PROGRAM IN SPITE OF TRADING LOSSES ARE MATERIAL POINTS WHICH CAN ALSO ADVERSELY AFFECT ACTUAL TRADING RESULTS. THERE ARE NUMEROUS OTHER FACTORS RELATED TO THE MARKETS IN GENERAL OR TO THE IMPLEMENTATION OF ANY SPECIFIC TRADING PROGRAM WHICH CANNOT BE FULLY ACCOUNTED FOR IN THE PREPARATION OF HYPOTHETICAL PERFORMANCE RESULTS AND ALL OF WHICH CAN ADVERSELY AFFECT ACTUAL TRADING RESULTS. TESTIMONIALS SHOWN ON THE SITE AND REFERENCED FROM TIME TO TIME ARE FROM SELECT CUSTOMERS. THEIR EXPERIENCES MAY NOT BE TYPICAL OF WHAT YOU CAN EXPECT TO ACHIEVE, AS RESULTS MAY VARY.\\r\\n
    \\r\\n
    \\r\\n Risk Disclaimer:
    \\r\\n The content of the educational material (including videos, webinars, seminars, chatrooms) and other forms of educational material offered by Tradehouses, are intended for educational purposes only. It comprises personal opinions of the presenters/authors and should not in any way be construed (either explicitly or implicitly, directly or indirectly) as containing personal recommendations, or investment recommendations, or investment advice, or an offer of, or solicitation for any transactions in financial instruments. Tradehouses, its affiliates, IBs, agents, directors, officers or employees do not guarantee the accuracy, validity, timeliness or completeness of any information/data made available or provided and assumes no liability as to any loss arising from any investment based on the same.\\r\\n

    \\r\\n Legal Registration: Tradehouses is the trading name of Stoa Limited, a company which is registered in Ireland with Registration Number: 626767 and has its registered address at: 3 Cavendish Row Street, D01A2T5, Dublin, Ireland. Tradehouses is not a regulated entity or a licensed investment firm under the Markets in Financial Instrument Directive (as amended), or under any other law or regulation, and is not providing financial services or investment advice or otherwise acting as a licensed entity in providing its services and materials. Tradehouses is not a university, college, school or other licensed educational institution under any laws worldwide and the materials provided by Tradehouses are not approved by any regulatory authority. Certifications by Tradehouses are not recognized by any public or private organization in the world.\\r\\n

    \\r\\n Risk Warning: Tradehouses do not offer Forex and CFD trading, note that Forex and CFD\\u2019s are complex financial instruments. Forex and CFD\\u2019s are complex financial instruments. Trading in such instruments is highly speculative and comes with a high risk of losing money rapidly due to leverage. You may lose more than your initial investment. On average 85% of retail investors lose money when trading in these financial instruments. These products are not suitable for all investors and you should not trade unless you understand how these instruments work, the risks involved and whether you can afford to take the high risk of losing your money. Please carefully read Tradehouses\\u2019 Terms & Conditions and Risk Disclosure Statement before starting to trade. Seek independent expert advice if necessary.\\r\\n

    \\r\\n Restricted Regions: Tradehouses does not provide its services to residents of certain jurisdictions such as Australia, Belgium, Canada, Japan, North Korea and USA.\\r\\n

    \\r\\n This material does not contain, and should not be construed as containing, investment advice or an investment recommendation, or a record of our trading prices, or an offer of, or solicitation for, a transaction in any financial instruments. Past performance is not a guarantee of or prediction of future performance. Tradehouses makes no representation and assumes no liability as to the accuracy or completeness of the information provided, nor any loss arising from any investment based on the use of this material, or based on a recommendation, forecast or other information supplied by an employee of Tradehouses, an affiliate, a third party or otherwise. Consequently, any person acting on it does so entirely at their own risk. This research and analysis does not take into account your specific investment objectives, financial situation and/or the needs of any specific person who may receive it.\\r\\n
    \\r\\n This material has not been prepared in accordance with legal requirements designed to promote the independence of research, and as such it is considered to be marketing communication. Although we are not specifically constrained from dealing ahead of the publication of our research, we do not seek to take advantage of it before we provide it to our clients. All expressions of opinion are subject to change without notice. Any views or opinions expressed are personal to the author and may not reflect the opinions of Tradehouses. This communication must not be reproduced or further distributed without prior permission.\\r\\n
    \\r\\n Forex and CFDs are leveraged products. Trading in these financial instruments may not be suitable for everyone and can result in losing all of your invested capital, so please make sure that you fully understand the risks involved.\\r\\n

    \\r\\n The content, data and information contained in this News Feeds section is provided to Tradehouses by third-party news providers and is not necessarily real-time, nor accurate, and should not in any way be construed, either explicitly or implicitly, directly or indirectly, as investment advice, recommendation, forecast or suggestion of an investment strategy with respect to any financial instrument and it is not intended to provide a sufficient basis on which to make investment decisions, in any manner whatsoever. Any data, information, views or opinions presented in this section have been obtained or derived from sources believed by Tradehouses to be reliable, but Tradehouses makes no representation as to their accuracy or completeness of the information provided. Tradehouses accepts no liability for any loss or damage from reliance on the data and information contained in this News Feds section. Consequently any person acting on it does so entirely at his/her own risk.\\r\\n

    \\r\\n The content, materials, information and data made available or provided in this traderoom is intended for educational purposes only and should not in any way be construed (either explicitly or implicitly, directly or indirectly) as containing personal recommendations, or investment recommendations, or investment advice, or an offer of, or solicitation for any transactions in financial instruments and/or a guarantee and/or prediction of future performance in any manner whatsoever. Tradehouses, its affiliates, IBs, agents, directors, officers or employees do not guarantee the accuracy, validity, timeliness or completeness, of any information and/ data made available or provided and assumes no liability as to any loss arising from any investment based on the same.\\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    ');\n$templateCache.put('settings-modal.html','
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n

    Preferences

    \\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 \\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
    \\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
    \\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 \\r\\n
    \\r\\n

    Receive notifcations from:

    \\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
    \\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
    \\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
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n {{blockedUser.userName}}\\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n You have not blocked any user\\r\\n
    \\r\\n
    \\r\\n\\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n {{mutedUser.user.userName}} / #{{mutedUser.room.s_name}}\\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n You have not muted any user\\r\\n
    \\r\\n
    \\r\\n\\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n {{bannedUser.userName}}\\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n You have not banned any user\\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n

    \\r\\n To update your billing details please click the button below\\r\\n

    \\r\\n

    \\r\\n \\r\\n Upgrade Billing Details\\r\\n \\r\\n

    \\r\\n
    \\r\\n
    \\r\\n

    \\r\\n You don\\'t have any billing plans\\r\\n

    \\r\\n
    \\r\\n
    0\" style=\"padding-top:10px\">\\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\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n
    PlanCharge
    {{item.planName}}{{item.text}}active until {{item.canceled | formatdate }}next renew at {{item.periodEnd | formatdate }}trial until {{item.trialEnd | formatdate }}
    \\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
    \\r\\n
    \\r\\n
    ');\n$templateCache.put('sidebar-company-header.html','
    \\r\\n \\r\\n

    \\r\\n {{teamName}}\\r\\n
    {{memberText}}\\r\\n

    \\r\\n
    \\r\\n');\n$templateCache.put('sidebar.html','
    \\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 powered by echofin\\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n\\r\\n
    \\r\\n\\r\\n');\n$templateCache.put('tc-modal.html','
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n

    Terms & Conditions

    \\r\\n
    \\r\\n
    \\r\\n Futures, equities, and options trading involve substantial risk. The valuation of leveraged investment positions may fluctuate, and as a result, you may lose more than your original investment. In no event should the content of any Sang Lucci (including Sang Lucci Trading, LLC and WallStJesus.com, as well as their affiliates and representatives) email, website, or product be construed as an expression of an implied promise, guarantee or implication by or from Sang Lucci, its owners or affiliates that you will profit or that losses can or will be limited in any manner whatsoever. PAST PERFORMANCE IS NOT NECESSARILY INDICATIVE OF FUTURE RESULTS. Information provided on any Sang Lucci email, website, or product is intended solely for informative and educational purposes and is obtained from sources believed to be reliable but has not been independently verified by Sang Lucci, it owners or affiliates. Information is in no way guaranteed to be accurate. No guarantee of any kind is implied or possible where projections of future conditions are attempted. By receiving any communication from Sang Lucci, you agree that any information provided is solely the opinion of Sang Lucci and not considered to be investment advice of any kind.\\r\\n

    \\r\\n You agree that all trading decisions you make using information provided by Sang Lucci is at your own risk and you agree to seek your own professional advice before investing.\\r\\n

    \\r\\n The information contained on the Sanglucci.com and WallStJesus.com websites or any other website that has Sang Lucci content with the approval of Sang Lucci, is provided for educational and informational purposes only. The information is not guaranteed to be correct, complete or current. Sang Lucci makes no warranty, expressed or implied, about the accuracy or reliability of the information at this website or at any other website to which it is linked. Recipients of content from this website or directly from Sang Lucci should not act or refrain from acting on the basis of any information included in the site without seeking appropriate investment advice from a licensed Industry representative; such as, but not limited to a Broker/Dealer, Introducing Broker, Futures Commission Merchant and and/or Registered Investment Advisor.\\r\\n

    \\r\\n Neither Sang Lucci nor Anand Sanghvi are licensed to provide individualized investment advice or to receive compensation relating to sales or purchases of securities or commodities. No information herein is intended as securities brokerage, investment, tax, accounting, or legal advice, as an offer or solicitation of an offer to sell or buy, or as an endorsement, recommendation or sponsorship of any company, security or fund. Sang Lucci cannot and does not assess, verify or guarantee the adequacy, accuracy or completeness of any information, the suitability or profitability of any particular investment, or the potential value of any investment or informational source. You bear responsibility for your own investment research and decisions, should seek the advice of a qualified securities professional before making any investment, and investigate and fully understand any and all risks before investing. In addition, Sang Lucci accepts no liability whatsoever for any direct or consequential loss arising from any use of this information. The information provided is not intended to be used as the sole basis of any investment decision, and should not be construed as advice designed to meet the investment needs of any particular investor. All purchasers of the Sang Lucci Training or other Sang Lucci products are encouraged to speak with a licensed representative of their choice regarding the appropriateness of investing/trading or of any particular investment/trading strategy. Sang Lucci expressly disclaims all liability with respect to actions taken or not taken by the recipient based on any or all of the information or other contents of this site. Sang Lucci is committed to transparency; however, Sang Lucci does not guarantee the accuracy of any trade information found online or supplied by Sang Lucci, including but not limited to trades discussed in Sang Lucci chat rooms. You should be aware that Anand Sanghvi may or may not have established positions that are identical or opposite to trades discussed in Sang Lucci chat rooms, and you should not assume that he has no monetary interest related to the trades that are discussed in Sang Lucci chat rooms.\\r\\n

    \\r\\n Any information sent to Sang Lucci via Internet e-mail or through the website is not secure and you should be aware that any such communications may be compromised despite reasonable precautions taken by Sang Lucci. Any such communications, however, will be treated as a confidential by Sang Lucci and will be afforded reasonable protection as required by law.\\r\\n
    \\r\\n
    \\r\\n Decline\\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    ');\n$templateCache.put('tradingview-container.html','\\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\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n\\r\\n');\n$templateCache.put('tradingview-widget.html','
    \\r\\n
    \\r\\n Charts\\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    ');\n$templateCache.put('users-group.html','
    0\" class=\"userGroupContainer\">\\r\\n
    \\r\\n \\r\\n {{grouptitle}}\\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n \"alt-text\"\\r\\n {{user.userName}} (you)\\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    ');\n$templateCache.put('vidbox-widget.html','
    \\r\\n
    \\r\\n LIVE BROADCASTING {{extra}}\\r\\n
    \\r\\n \\r\\n \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n {{message1}}
    \\r\\n {{message2}}
    \\r\\n Please Upgrade\\r\\n
    \\r\\n
    \\r\\n \\r\\n Loading...\\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    ');\n$templateCache.put('widgets-top-modals.html','
    200) ? w.config.width : 200,\\'height\\':(w.config.height > 100) ? w.config.height : 100,\\'border\\':\\'none\\',\\'background\\':\\'#000\\'}\">\\r\\n
    \\r\\n {{w.label}}\\r\\n
    \\r\\n \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n {{(w.config.hasBannerMessage)?w.config.bannerMessage:\\'This is a premium Widget\\'}}\\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n This widget has not been
    implemented correctly
    by the widget provider\\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n \\r\\n
    \\r\\n');}]);","'use strict';\r\nangular\r\n .module('chat.alert.refresh', [])\r\n .directive('alertRefresh', alertRefresh)\r\n\r\nalertRefresh.$inject = [];\r\nfunction alertRefresh() {\r\n\r\n return {\r\n templateUrl: 'alert-refresh.html',\r\n scope: {\r\n isShown: \"@\",\r\n },\r\n link: function (scope, elem) {\r\n scope.$watch(function () {\r\n return scope.isShown\r\n }, function (value, oldValue) {\r\n if (!value) {\r\n elem.hide();\r\n }\r\n })\r\n scope.$on(\"alert-refresh\", function () {\r\n scope.isShown = true;\r\n elem.show();\r\n })\r\n },\r\n controller: function ($scope, $window) {\r\n $scope.refresh = function () {\r\n $window.location.reload();\r\n }\r\n },\r\n }\r\n}","'use strict';\r\n\r\nangular\r\n .module('chat.widgets-top', [])\r\n .directive('widgetsTopModals',\r\n [\r\n '$rootScope', 'userService', 'chatRoomService', 'pushService', '$location', '$sce', '$compile',\r\n function ($rootScope, userService, chatRoomService, pushService, $location, $sce, $compile) {\r\n return {\r\n //replace: true,\r\n templateUrl: 'widgets-top-modals.html',\r\n transclude: true,\r\n controller: function ($scope, $element) {\r\n\r\n },\r\n link: function ($scope, $element) {\r\n $scope.topWidgets = [];\r\n\r\n $scope.loadTopWidget = function (w) {\r\n $scope.topWidgetSelected = w.key;\r\n w.notify = null;\r\n\r\n if (w.trustUrl) {\r\n _show(w)\r\n return; //widget is already loaded\r\n }\r\n\r\n if (!w.config.hasAdvancedConfig) {\r\n _loadWidget(w);\r\n }\r\n else {\r\n _loadCustomWidget(w);\r\n }\r\n\r\n _show(w)\r\n\r\n $(\"#widget-top-modal-\" + w.key + ' > .ui-widget-header')\r\n .on('mousedown', function () {\r\n $(\".custom-backdrop\").show()\r\n $(\"#widget-top-modal-\" + w.key).css(\"z-index\", lastZIndex++)\r\n }).on('mouseup', function () {\r\n $(\".custom-backdrop\").hide()\r\n });\r\n\r\n $(\"#widget-top-modal-\" + w.key)\r\n .draggable({\r\n handle: $(\"#widget-top-modal-\" + w.key + ' > .ui-widget-header'),\r\n containment: \"document\",\r\n start: function (event, ui) {\r\n $(\".custom-backdrop\").show()\r\n $(\"#widget-top-modal-\" + w.key).css(\"z-index\", lastZIndex++)\r\n },\r\n stop: function (event, ui) {\r\n $(\".custom-backdrop\").hide()\r\n }\r\n })\r\n .resizable({\r\n containment: \"document\",\r\n //minWidth: (w.config.width > 200) ? w.config.width : 200,\r\n //minHeight: (w.config.height > 100) ? w.config.height : 100,\r\n aspectRatio: w.config.aspectRatio || false,\r\n handles: \"se\",\r\n start: function (event, ui) {\r\n $(\".custom-backdrop\").show()\r\n $(\"#widget-top-modal-\" + w.key).css(\"z-index\", lastZIndex++)\r\n },\r\n stop: function (event, ui) {\r\n $(\".custom-backdrop\").hide()\r\n }\r\n });\r\n\r\n }\r\n\r\n $scope.MinimizeTopModal = function (w) {\r\n _close(w)\r\n }\r\n\r\n $scope.CloseTopModal = function (w) {\r\n _close(w);\r\n w.trustUrl = null;\r\n }\r\n\r\n function _show(w) {\r\n $(\"#widget-top-modal-\" + w.key).css(\"z-index\", lastZIndex++);\r\n $(\"#widget-top-modal-\" + w.key).modal('show');\r\n }\r\n\r\n function _close(w, minimize) {\r\n $(\"#widget-top-modal-\" + w.key).modal('hide');\r\n }\r\n\r\n function _loadWidget(w) {\r\n var url = \"https://\" + w.url.replace(/^\\/\\//, '')\r\n w.trustUrl = $sce.trustAsResourceUrl(url);\r\n }\r\n\r\n function _loadCustomWidget(w) {\r\n\r\n try {\r\n var xhr = new XMLHttpRequest();\r\n\r\n xhr.open('GET', \"https://\" + w.url);\r\n xhr.onreadystatechange = function () {\r\n if (this.readyState === this.DONE) {\r\n if (this.status === 200) {\r\n // this.response is a Blob, because we set responseType above\r\n var data_url = URL.createObjectURL(this.response);\r\n w.trustUrl = $sce.trustAsResourceUrl(data_url);\r\n } else {\r\n w.iframeError = true;\r\n }\r\n }\r\n };\r\n xhr.responseType = 'blob';\r\n //xhr.setRequestHeader(\"Content-type\", \"application/x-www-form-urlencoded\");\r\n xhr.setRequestHeader(\"x-token\", w.token);\r\n xhr.send();\r\n\r\n } catch (e) {\r\n w.iframeError = true;\r\n }\r\n }\r\n\r\n\r\n $scope.$on('initial',\r\n function (event, data) {\r\n _.each($scope.topWidgets,\r\n function (w, index) {\r\n if (w.config.enableCallback && index) {\r\n $scope.loadTopWidget(w);\r\n }\r\n });\r\n\r\n //$scope.$apply();\r\n // console.log($scope.rightWidgets);\r\n });\r\n\r\n //$.each($('.widget-top-modal > .ui-widget-header'), function (index, item) {\r\n // // console.log(\"ui-widget-header of \", item)\r\n // $(item).on('mousedown', function () {\r\n // $(item).find(\".custom-backdrop\").show()\r\n // $(\"#vidboxModal\").css(\"z-index\", lastZIndex++)\r\n // }).on('mouseup', function () {\r\n // $(item).find(\".custom-backdrop\").hide()\r\n // });\r\n //});\r\n\r\n //$.each($('.widget-top-modal'), function (index, item) {\r\n // // console.log(\"widget-top-modal \", item)\r\n // $(item).draggable({\r\n // handle: $(item).find(\"div.ui-widget-header\"),\r\n // containment: \"document\",\r\n // start: function (event, ui) {\r\n // $(item).find(\".custom-backdrop\").show()\r\n // $(\"#vidboxModal\").css(\"z-index\", lastZIndex++)\r\n // },\r\n // stop: function (event, ui) {\r\n // $(item).find(\".custom-backdrop\").hide()\r\n // }\r\n // })\r\n // .resizable({\r\n // containment: \"document\",\r\n // minWidth: 400,\r\n // minHeight: 225,\r\n // aspectRatio: true,\r\n // handles: \"se\",\r\n // start: function (event, ui) {\r\n // $(item).find(\".custom-backdrop\").show()\r\n // $(\"#vidboxModal\").css(\"z-index\", lastZIndex++)\r\n // },\r\n // stop: function (event, ui) {\r\n // $(item).find(\".custom-backdrop\").hide()\r\n // }\r\n // });\r\n //});\r\n\r\n\r\n //$scope.loadWidget($scope.rightWidgets[0]);\r\n }\r\n }\r\n }\r\n ]);\r\n","angular\r\n .module('chat.analytics.google', [\r\n 'angular-google-analytics',\r\n ])\r\n .config(['AnalyticsProvider', function (AnalyticsProvider) {\r\n var l_lstTrackers = [{\r\n tracker: 'UA-89853491-7'\r\n }];\r\n\r\n if (window.analyticsKey && window.analyticsKey != '')\r\n l_lstTrackers.push({\r\n tracker: window.analyticsKey\r\n })\r\n\r\n AnalyticsProvider.setAccount(l_lstTrackers);\r\n\r\n // Track all routes (default is true). \r\n AnalyticsProvider.trackPages(true);\r\n\r\n // Track all URL query params (default is false). \r\n AnalyticsProvider.trackUrlParams(true);\r\n\r\n // Ignore first page view (default is false). \r\n // Helpful when using hashes and whenever your bounce rate looks obscenely low. \r\n AnalyticsProvider.ignoreFirstPageLoad(true);\r\n AnalyticsProvider.delayScriptTag(true);\r\n // URL prefix (default is empty). \r\n // Helpful when the app doesn't run in the root directory. \r\n //AnalyticsProvider.trackPrefix(window.location.hostname);\r\n\r\n // Change the default page event name. \r\n // Helpful when using ui-router, which fires $stateChangeSuccess instead of $routeChangeSuccess. \r\n //AnalyticsProvider.setPageEvent('$stateChangeSuccess');\r\n\r\n // RegEx to scrub location before sending to analytics. \r\n // Internally replaces all matching segments with an empty string. \r\n //AnalyticsProvider.setRemoveRegExp(/\\/\\d+?$/);\r\n\r\n // Activate reading custom tracking urls from $routeProvider config (default is false) \r\n // This is more flexible than using RegExp and easier to maintain for multiple parameters. \r\n // It also reduces tracked pages to routes (only those with a templateUrl) defined in the \r\n // $routeProvider and therefore reduces bounce rate created by redirects. \r\n // NOTE: The following option requires the ngRoute module \r\n AnalyticsProvider.readFromRoute(true);\r\n AnalyticsProvider.setDomainName(window.location.hostname);\r\n }])\r\n .run(['Analytics', function (Analytics) {}])\r\n .service('AnalyticsActions', ['Analytics', function (Analytics) {\r\n var _setUsername = function (a_strUsername) {\r\n // console.log('AnalyticsActions');\r\n Analytics.registerScriptTags();\r\n Analytics.registerTrackers();\r\n Analytics.set('userId', a_strUsername);\r\n };\r\n return {\r\n setUsername: _setUsername\r\n }\r\n }])","'use strict';\r\n\r\n\r\nangular.module('chat.layout', [\r\n 'chat.message',\r\n 'chat.room',\r\n 'chat.user',\r\n 'chat.auth',\r\n 'chat.notify',\r\n 'chat.emojis'\r\n])\r\n\r\n .directive('headerNav', [\r\n 'IntroTutorialService', '$sce', '$rootScope', '$location', '$timeout',\r\n 'chatRoomService', 'tokenService', 'userService',\r\n function (\r\n IntroTutorialService, $sce, $rootScope, $location, $timeout,\r\n chatRoomService, tokenService, userService) {\r\n return {\r\n replace: true,\r\n templateUrl: \"header-nav.html\",\r\n controller: function ($scope, $element) {\r\n $scope.room = null;\r\n $scope.showFilterButton = false;\r\n $scope.showDataFlash = false;\r\n var bLazy = null;\r\n\r\n $scope.show = false;\r\n\r\n var _loadBLazy = function () {\r\n bLazy = new Blazy({\r\n container: '#dvTools',\r\n src: 'a-blazy',\r\n success: function (ele) { },\r\n error: function (ele, msg) { }\r\n });\r\n };\r\n\r\n if ($(window).width() < 768) { //mobile screen\r\n var dvRightVisible = false;\r\n var toolsVisible = false;\r\n var dvfilterPanelVisible = false;\r\n\r\n var dvToolsWidth = 0;\r\n var dvFilterPanel = 0;\r\n dvToolsWidth = dvAlertsWidth = $(window).width();\r\n\r\n } else {\r\n var dvRightVisible = true;\r\n var toolsVisible = false;\r\n var dvfilterPanelVisible = false;\r\n\r\n var dvToolsWidth = 220;\r\n var dvAlertsWidth = 500;\r\n var dvRightWidth = 500;\r\n var dvFilterPanelWidth = 400;\r\n }\r\n\r\n\r\n //$('#dvTools').css('display', \"none\");\r\n\r\n\r\n var calcAction = function (action) {\r\n\r\n if (action == 1) { //dvTools\r\n if (toolsVisible) {\r\n dvRightWidth = $('#dvRight').width() - dvToolsWidth;\r\n $('#dvTools').css('width', 0);\r\n $('#dvTools').css('display', \"none\");\r\n } else {\r\n dvRightWidth = $('#dvRight').width() + dvToolsWidth;\r\n $('#dvTools').css('width', dvToolsWidth);\r\n $('#dvTools').css('display', \"inherit\");\r\n }\r\n toolsVisible = !toolsVisible;\r\n } else if (action == 0) { //dvAlerts\r\n if (dvRightVisible) {\r\n dvRightWidth = $('#dvRight').width() - dvAlertsWidth;\r\n $('#dvAlerts').css('width', '0px');\r\n $('#dvAlerts').css('border-left', '0px');\r\n //$('.right-pad').css('padding-right', '0px');\r\n } else {\r\n dvRightWidth = $('#dvRight').width() + dvAlertsWidth;\r\n $('#dvAlerts').css('width', dvAlertsWidth);\r\n $('#dvAlerts').css('border-left', 'solid 1px #111;');\r\n //$('.right-marg').css('padding-right', '500px');\r\n }\r\n dvRightVisible = !dvRightVisible;\r\n } else if (action == 2) { //dvFilterPanel\r\n if (dvfilterPanelVisible) {\r\n dvRightWidth = $('#dvRight').width() - dvFilterPanelWidth - 1;\r\n $('#dvFilterPanel').css('width', '0px');\r\n } else {\r\n dvRightWidth = $('#dvRight').width() + dvFilterPanelWidth + 1;\r\n $('#dvFilterPanel').css('width', dvFilterPanelWidth);\r\n }\r\n dvfilterPanelVisible = !dvfilterPanelVisible;\r\n var scrollcontainer = \"#dvFilterMessages\";\r\n $(scrollcontainer).scrollTop($(scrollcontainer)[0].scrollHeight);\r\n }\r\n\r\n // an extremely very ugly huge hack for ie\r\n // something is wrongly calculated\r\n //var uaparser = new UAParser();\r\n //var _b = uaparser.getBrowser().name;\r\n //if (_b == \"Edge\" || _b == \"IE\") {\r\n // dvRightWidth += 17;\r\n //}\r\n // end of the extremely very ugly huge hack for ie\r\n\r\n\r\n $('#dvRight').css('width', dvRightWidth);\r\n\r\n $('.right-marg').css('margin-right', dvRightWidth);\r\n $('.chatDiv').css('right', dvRightWidth + 25);\r\n\r\n\r\n $timeout(_loadBLazy, 500, true);\r\n\r\n $rootScope.$broadcast('TogglePanel', action);\r\n }\r\n\r\n var calcAction_old = function (action) { //0 - alerts, 1 - tools\r\n var toolsVisible = $(\"#dvTools\").css('display') != 'none',\r\n alertsVisible = $(\"#dvAlerts\").css('display') != 'none',\r\n speed = 100,\r\n chatDivPadding = 15;\r\n\r\n //when alert's is shutting down\r\n //false true 0\r\n\r\n if (toolsVisible && alertsVisible) {\r\n if (action == 0) {\r\n $('#dvAlerts').toggle(\"slide\", {\r\n direction: \"right\"\r\n }, speed, function () {\r\n $('#dvRight').animate({\r\n 'width': toolsWidth.toString() + 'px'\r\n }, speed);\r\n $('.right-pad').animate({\r\n 'padding-right': toolsWidth.toString() + 'px'\r\n }, speed);\r\n $('.right-marg').animate({\r\n 'margin-right': toolsWidth.toString() + 'px'\r\n }, speed);\r\n $('.chatDiv').animate({\r\n 'right': (toolsWidth + chatDivPadding).toString() + 'px'\r\n }, speed);\r\n $('.alertDiv').animate({\r\n 'right': (toolsWidth).toString() + 'px'\r\n }, speed);\r\n _loadBLazy();\r\n });\r\n } else if (action == 1) {\r\n $('#dvTools').toggle(\"slide\", {\r\n direction: \"right\"\r\n }, speed, function () {\r\n $('#dvRight').css({\r\n 'width': alertsWidth.toString() + 'px'\r\n }, speed);\r\n $('.right-pad').animate({\r\n 'padding-right': alertsWidth.toString() + 'px'\r\n }, speed);\r\n $('.right-marg').animate({\r\n 'margin-right': alertsWidth.toString() + 'px'\r\n }, speed);\r\n $('.chatDiv').animate({\r\n 'right': (alertsWidth + chatDivPadding).toString() + 'px'\r\n }, speed);\r\n $('.alertDiv').animate({\r\n 'right': (alertsWidth).toString() + 'px'\r\n }, speed);\r\n });\r\n }\r\n //width 2x\r\n } else {\r\n if (toolsVisible) {\r\n if (action == 0) {\r\n $('#dvRight').css('width', (toolsWidth + alertsWidth).toString() + 'px');\r\n $('.right-pad').animate({\r\n 'padding-right': (toolsWidth + alertsWidth).toString() + 'px'\r\n }, speed);\r\n $('.right-marg').animate({\r\n 'margin-right': (toolsWidth + alertsWidth).toString() + 'px'\r\n }, speed);\r\n $('#dvAlerts').toggle(\"slide\", {\r\n direction: \"right\"\r\n }, speed);\r\n $('.chatDiv').animate({\r\n 'right': (toolsWidth + alertsWidth + chatDivPadding).toString() + 'px'\r\n }, speed);\r\n $('.alertDiv').animate({\r\n 'right': (toolsWidth + alertsWidth).toString() + 'px'\r\n }, speed);\r\n _loadBLazy();\r\n } else if (action == 1) {\r\n $('#dvRight').css('width', '0px');\r\n //$('.emoji-menu').css('left', '200px');\r\n //$('.emoji-menu').css('left', alertsWidth.toString() + 'px');\r\n $('#dvTools').toggle(\"slide\", {\r\n direction: \"right\"\r\n }, speed);\r\n $('.right-pad').animate({\r\n 'padding-right': '0px'\r\n }, speed);\r\n $('.right-marg').animate({\r\n 'margin-right': '0px'\r\n }, speed);\r\n $('.chatDiv').animate({\r\n 'right': chatDivPadding.toString() + 'px'\r\n }, speed);\r\n $('.chatDiv').css('right', chatDivPadding.toString() + 'px');\r\n $('.alertDiv').animate({\r\n 'right': '0'\r\n }, speed);\r\n $('.alertDiv').css('right', '0');\r\n } //width 1x\r\n } else if (alertsVisible) {\r\n if (action == 0) {\r\n //$('#dvRight').css('width', '0px', 'important');\r\n $('#dvRight').each(function () {\r\n this.style.setProperty('width', '0px', 'important');\r\n })\r\n $('#dvAlerts').toggle(\"slide\", {\r\n direction: \"right\"\r\n }, speed);\r\n //$('.emoji-menu').css('left', '200px');\r\n //$('.emoji-menu').css('left', alertsWidth.toString() + 'px');\r\n $('.right-pad').animate({\r\n 'padding-right': '0px'\r\n }, speed);\r\n $('.right-marg').animate({\r\n 'margin-right': '0px'\r\n }, speed);\r\n $('.right-marg').css('margin-right', '0');\r\n $('.chatDiv').animate({\r\n 'right': chatDivPadding.toString() + 'px'\r\n }, speed);\r\n $('.alertDiv').animate({\r\n 'right': '0'\r\n }, speed);\r\n //consolelog('pass');\r\n } else if (action == 1) {\r\n $('#dvRight').css('width', (toolsWidth + alertsWidth).toString() + 'px');\r\n $('.right-pad').animate({\r\n 'padding-right': (toolsWidth + alertsWidth).toString() + 'px'\r\n }, speed);\r\n $('.right-marg').animate({\r\n 'margin-right': (toolsWidth + alertsWidth).toString() + 'px'\r\n }, speed);\r\n $('#dvTools').toggle(\"slide\", {\r\n direction: \"right\"\r\n }, speed);\r\n $('.chatDiv').animate({\r\n 'right': (toolsWidth + alertsWidth + chatDivPadding).toString() + 'px'\r\n }, speed);\r\n $('.alertDiv').animate({\r\n 'right': (toolsWidth + alertsWidth).toString() + 'px'\r\n }, speed);\r\n _loadBLazy();\r\n }\r\n //width 1x\r\n } else {\r\n if (action == 0) {\r\n $('#dvRight').css('width', alertsWidth.toString() + 'px');\r\n $('#dvAlerts').toggle(\"slide\", {\r\n direction: \"right\"\r\n }, speed);\r\n $('.right-pad').animate({\r\n 'padding-right': alertsWidth.toString() + 'px'\r\n }, speed);\r\n $('.right-marg').animate({\r\n 'margin-right': alertsWidth.toString() + 'px'\r\n }, speed);\r\n $('.chatDiv').animate({\r\n 'right': (alertsWidth + chatDivPadding).toString() + 'px'\r\n }, speed);\r\n $('.alertDiv').animate({\r\n 'right': (alertsWidth).toString() + 'px'\r\n }, speed);\r\n } else {\r\n $('#dvRight').css('width', toolsWidth.toString() + 'px');\r\n $('#dvTools').toggle(\"slide\", {\r\n direction: \"right\"\r\n }, speed);\r\n $('.right-pad').animate({\r\n 'padding-right': toolsWidth.toString() + 'px'\r\n }, speed);\r\n $('.right-marg').animate({\r\n 'margin-right': toolsWidth.toString() + 'px'\r\n }, speed);\r\n $('.chatDiv').animate({\r\n 'right': (toolsWidth + chatDivPadding).toString() + 'px'\r\n }, speed);\r\n $('.chatDiv').css('right', (toolsWidth + chatDivPadding).toString() + 'px');\r\n $('.alertDiv').animate({\r\n 'right': (toolsWidth).toString() + 'px'\r\n }, speed);\r\n $('.alertDiv').css('right', (toolsWidth).toString() + 'px');\r\n _loadBLazy();\r\n }\r\n //width 0x\r\n }\r\n }\r\n\r\n\r\n }\r\n\r\n $scope.calcAction = calcAction\r\n\r\n $scope.ChangeStatus = function (a_intStatus) {\r\n userService.updateOnlineStatus(a_intStatus);\r\n };\r\n\r\n //$rootScope.$on('TogglePanel', function (event, data) {\r\n // calcAction(data);\r\n //});\r\n\r\n $rootScope.$on('ChangeRoom', function (event, data) {\r\n if (!data)\r\n return;\r\n $('.right-marg').css('marginRight', $('#dvRight').width()); //fix right-marg\r\n $scope.room = data;\r\n if (data.roomType == 2) {\r\n $scope.memberCount = 2;\r\n } else if (data.roomType == 1) {\r\n $scope.memberCount = userService.getAll().length;\r\n } else if (data.roomType == 3) {\r\n $scope.memberCount = null;\r\n } else if (data.roomType == 4) {\r\n $scope.memberCount = null;\r\n }\r\n //HandlePusherNewMessage(data.message);\r\n if ($scope.room != null && $scope.room.s_url != null)\r\n $scope.room.isDirect = ($scope.room.s_url.substring(0, 1) == '@');\r\n\r\n });\r\n\r\n\r\n $rootScope.$on('initial', function (event, data) {\r\n var l_objTeam = userService.getTeamProperties();\r\n\r\n $scope.teamName = l_objTeam.s_name\r\n\r\n\r\n var uaparser = new UAParser();\r\n var OpenInAppdevice = uaparser.getDevice()\r\n if (OpenInAppdevice.type == \"mobile\" && l_objTeam.s_key != '875960cc') {\r\n $scope.showOpenInApp = true\r\n }\r\n\r\n if (l_objTeam && l_objTeam.s_key != '875960cc') {\r\n $scope.show = true;\r\n };\r\n\r\n var l_lstUsers = userService.getAll();\r\n if (l_lstUsers != null)\r\n $scope.memberCount = l_lstUsers.length;\r\n $scope.room = chatRoomService.getCurrentRoom();\r\n if ($scope.room != null && $scope.room.s_url != null)\r\n $scope.room.isDirect = ($scope.room.s_url.substring(0, 1) == '@');\r\n\r\n var l_strTeamKey = userService.getTeamProperties().s_key;\r\n if (l_strTeamKey == '875960cc' || l_strTeamKey == '1a6638d0') {\r\n //$scope.lblAlerts = 'TOOLKIT';\r\n $scope.showFilterButton = true;\r\n //$scope.lblAlertsIconText = 'trending_up';\r\n $scope.lblAlerts = 'WIDGETS';\r\n $scope.lblAlertsIconText = 'apps';\r\n } else {\r\n $scope.lblAlerts = 'WIDGETS';\r\n $scope.lblAlertsIconText = 'apps';\r\n }\r\n });\r\n\r\n $rootScope.$on('CurrentUserUpdate', function (event, data) {\r\n $scope.currentUser = data.user;\r\n _loadBLazy();\r\n });\r\n\r\n $scope.Logout = function () {\r\n if (window.mixpanel)\r\n mixpanel.reset();\r\n tokenService.Logout();\r\n };\r\n\r\n $scope.ViewTutorial = function () {\r\n IntroTutorialService.run()\r\n }\r\n\r\n }, //Embed a custom controller in the directive\r\n link: function ($scope, element, attrs) { } //DOM manipulation\r\n };\r\n }\r\n ])\r\n\r\n .directive('sidebar', function () {\r\n return {\r\n replace: true,\r\n templateUrl: 'sidebar.html',\r\n controller: function ($window, $scope, $element, $rootScope, $location, chatRoomService, userService, $sce, brokersService) {\r\n $scope.users = [];\r\n $scope.chatRooms = [];\r\n $scope.userDateformat = [];\r\n\r\n $scope.isAdmin = false;\r\n\r\n var _avatarFile = null;\r\n\r\n var _findChatRoom = function (a_strKey) {\r\n for (var i = 0; i < $scope.chatRooms.length; i++) {\r\n if ($scope.chatRooms[i].s_key == a_strKey)\r\n return $scope.chatRooms[i];\r\n }\r\n };\r\n\r\n var _findChatRoomClearKey = function (a_strKey) {\r\n for (var i = 0; i < $scope.chatRooms.length; i++) {\r\n if ($scope.chatRooms[i].s_clearKey == a_strKey)\r\n return $scope.chatRooms[i];\r\n }\r\n };\r\n\r\n var _findUserChat = function (a_strKey) {\r\n for (var i = 0; i < $scope.users.length; i++) {\r\n if ($scope.users[i].s_key == a_strKey)\r\n return $scope.users[i];\r\n }\r\n };\r\n\r\n var _gotoDefaultRoom = function () {\r\n if ($scope.chatRooms.length > 0)\r\n chatRoomService.changeRoom($scope.chatRooms[0]);\r\n };\r\n\r\n var _calculateTotalUnread = function () {\r\n var chatroomsTotalUnread = $scope.chatRooms.reduce(function (a, i) { return a + i.n_count }, 0)\r\n var usersTotalUnread = userService.getCounters();\r\n chatRoomService.totalUnread = chatroomsTotalUnread + usersTotalUnread;\r\n $rootScope.$broadcast(\"TotalUnreadsChanged\", chatRoomService.totalUnread);\r\n }\r\n\r\n $scope.changeRoom = function (a_objRoom) {\r\n\r\n if (a_objRoom.b_openBlank) {\r\n $window.open(\"https://\" + $window.location.host + \"/redirect/index/\" + a_objRoom.s_key.replace(\"hyphen-\", \"\"));\r\n return;\r\n }\r\n\r\n $(\".popover\").each(function () {\r\n $(this).popover('hide');\r\n });\r\n\r\n chatRoomService.changeRoom(a_objRoom);\r\n\r\n }\r\n\r\n $scope.$on('ChangeRoom', function (event, data) {\r\n var chatRoom = null;\r\n if (!data)\r\n return;\r\n\r\n if (data.roomType == 1) {\r\n chatRoom = _findChatRoom(data.s_key);\r\n $scope.roomName = data.s_name;\r\n $scope.roomHref = data.s_url;\r\n } else if (data.roomType == 2) {\r\n chatRoom = _findUserChat(data.s_key);\r\n $scope.roomName = data.userName;\r\n $scope.roomHref = '@' + data.userName;\r\n } else if (data.roomType == 3) {\r\n chatRoom = _findChatRoom(data.s_key);\r\n $scope.roomName = data.s_name;\r\n $scope.roomHref = data.s_url;\r\n } else if (data.roomType == 4) {\r\n $scope.roomName = data.s_key;\r\n $scope.roomHref = data.s_url;\r\n } else if (data.roomType == 5) {\r\n chatRoom = _findChatRoom(data.s_key);\r\n $scope.roomName = data.s_name;\r\n $scope.roomHref = data.s_url;\r\n }\r\n\r\n if (chatRoom != null)\r\n chatRoom.n_count = 0;\r\n\r\n //consolelog('sidebar ChangeRoom', chatRoom, data, $scope.roomName);\r\n _calculateTotalUnread();\r\n });\r\n\r\n $scope.$on('NewMessageNotFocused', function (event, data) {\r\n if (data.RoomKey.substring(0, 10) == \"private-u-\") {\r\n var _user = userService.getUserByKey(data.RoomKey);\r\n _user.n_count += 1;\r\n _user.b_isPinned = true;\r\n $scope.users.pushIfNotExist(_user, function (e) {\r\n if (e.s_key == _user.s_key) {\r\n return true;\r\n }\r\n return false;\r\n });\r\n } else {\r\n _findChatRoom(data.RoomKey).n_count += 1;\r\n }\r\n\r\n //consolelog(_findChatRoom(data.RoomKey));\r\n _calculateTotalUnread();\r\n $scope.$apply();\r\n });\r\n\r\n $scope.$on('initial', function (event, data) {\r\n $scope.chatRooms = chatRoomService.getAll();\r\n\r\n $scope.myBrokers = brokersService.brokers\r\n\r\n $scope.users = userService.getAll();\r\n $scope.currentUser = userService.getCurrentUser();\r\n\r\n $scope.isAdmin = ($scope.currentUser && $scope.currentUser.type == 1);\r\n\r\n var l_lstActiveCons = userService.getActiveConvs();\r\n for (var i = 0; i < l_lstActiveCons.length; i++) {\r\n var l_objUser = userService.getUserByClearKey(l_lstActiveCons[i].s_key);\r\n if (l_objUser != null) {\r\n l_objUser.b_isPinned = true;\r\n l_objUser.n_count = l_lstActiveCons[i].n_count;\r\n } else {\r\n var chatRoom = _findChatRoomClearKey(l_lstActiveCons[i].s_key);\r\n if (chatRoom != null) {\r\n chatRoom.n_count = l_lstActiveCons[i].n_count;\r\n }\r\n }\r\n }\r\n \r\n _calculateTotalUnread();\r\n\r\n var l_strTeamKey = userService.getTeamProperties().s_key;\r\n\r\n $scope.isFootnoteVisible = true\r\n $scope.isTutorialVisible = true\r\n $scope.brokersEnabled = userService.getTeamProperties().showWebTrader\r\n\r\n if (l_strTeamKey == '14e9b3ad') { // forex.echofin\r\n $scope.isForex = true\r\n }\r\n\r\n if (l_strTeamKey == '875960cc') {// || l_strTeamKey == '450d9432') { // jesus\r\n $scope.isTutorialVisible = false\r\n }\r\n\r\n });\r\n\r\n $rootScope.$on('UserStatusChange', function (event, data) {\r\n var user = userService.getUserByClearKey(data.user);\r\n\r\n if (user == null)\r\n user = userService.getUserByKey(data.user);\r\n\r\n if (user != null) {\r\n user.status = data.status;\r\n $scope.$apply();\r\n } else {\r\n }\r\n });\r\n\r\n $rootScope.$on('CurrentUserUpdate', function (event, data) {\r\n if (data.action == 'update')\r\n $scope.currentUser.s_avatar = $scope.currentUser.s_avatar + '?' + (new Date()).getTime().toString();\r\n });\r\n\r\n\r\n //$scope.HideChat = function (a_objUser) {\r\n // userService.getUserByKey(a_objUser.s_key).b_isPinned = false;\r\n // if ($location.url().indexOf(a_objUser.userName) > -1)\r\n // _gotoDefaultRoom();\r\n // userService.savePinnedRooms();\r\n //};\r\n\r\n $scope.statuses = [{\r\n id: 1,\r\n name: \"Low\"\r\n }, {\r\n id: 2,\r\n name: \"Normal\"\r\n }, {\r\n id: 3,\r\n name: \"High\"\r\n }, {\r\n id: 4,\r\n name: \"Urgent\"\r\n }, {\r\n id: 5,\r\n name: \"Immediate\"\r\n }];\r\n\r\n $scope.LoadSettings = function () {\r\n $rootScope.$broadcast('LoadSettingsModal');\r\n };\r\n\r\n $($element).find(\".webinars-sidebar-header\").click(function () {\r\n //slide up all the link lists\r\n $(\"#products-list\").slideUp();\r\n //slide down the link list below the h3 clicked - only if its closed\r\n if ($(\"#products-list\").is(\":visible\")) {\r\n $(\"#products-icon\").removeClass(\"fa-minus\").addClass(\"fa-plus\");\r\n $(\"#products-list\").slideUp();\r\n } else {\r\n $(\"#products-icon\").removeClass(\"fa-plus\").addClass(\"fa-minus\");\r\n $(\"#products-list\").slideDown();\r\n }\r\n });\r\n\r\n }\r\n }\r\n })\r\n\r\n .directive('textingarea', [function () {\r\n var l_strTextingTemplate = '
    ';\r\n return {\r\n replace: true,\r\n template: l_strTextingTemplate,\r\n controller: function ($scope, $element) { }\r\n }\r\n }])\r\n\r\n .directive('composerDirective', ['emojiService', 'tokenService', 'userService', 'chatRoomService', 'notifyService', 'messageService', 'messageDatasource',\r\n function (emojiService, tokenService, userService, chatRoomService, notifyService, messageService, messageDatasource) {\r\n return {\r\n controller: function ($scope, $element) {\r\n var chatBoxVariables = null;\r\n\r\n\r\n\r\n var _createChatBox = function () {\r\n var currentRoom = chatRoomService.getCurrentRoom();\r\n var currentUser = userService.getCurrentUser();\r\n if (currentRoom == null || currentUser == null)\r\n return false;\r\n chatBoxVariables = {\r\n accessToken: tokenService.model.access_token,\r\n userList: userService.getForChatbox(),\r\n uploadURI: \"api/file/uploadfile\",\r\n clipboardURI: \"api/file/uploadclipboard\",\r\n //emojis: emojiService.getEmojisForChatbox(),\r\n debugMode: l_blnDebug,\r\n emojiAbsPath: '//cdnjs.echofin.co/plugins/chatBox/emojis/',\r\n senderKey: currentUser.s_key,\r\n roomKey: currentRoom.s_key,\r\n roomName: currentRoom.s_url,\r\n teamName: userService.getTeamProperties().s_name,\r\n alertCallback: function (a_intType, a_strMessage) {\r\n if (a_intType == 1)\r\n notifyService.error(a_strMessage);\r\n },\r\n addons: {\r\n signals: true,\r\n download: true\r\n }\r\n };\r\n\r\n chatBoxVariables.onLoaded = function () {\r\n $.extend($.fn.chatBoxAddons, $.fn.chatBox);\r\n $.fn.chatBoxAddons(this);\r\n }\r\n\r\n var l_strCompanyKey = userService.getTeamProperties().s_key;\r\n if (l_strCompanyKey == '875960cc') {\r\n chatBoxVariables.addons.signals = false\r\n }\r\n\r\n $('body').chatBox(chatBoxVariables, function (response) {\r\n var l_objRoom = chatRoomService.getCurrentRoom();\r\n var l_objUser = userService.getCurrentUser();\r\n\r\n if (response.type == \"bot\") {\r\n\r\n var l_lngTime = moment.utc().valueOf();\r\n var l_strMessageKey = Math.random().toString(36).substring(2) + l_lngTime.toString();\r\n var l_objUser = userService.getUserByName(response.user);\r\n\r\n if (!l_objUser) {\r\n return\r\n }\r\n\r\n var l_objMessage = {\r\n sender: l_objUser.userName,\r\n senderKey: l_objUser.s_key,\r\n message: response.message,\r\n date: moment.utc().valueOf(),\r\n s_avatar: l_objUser.s_avatar,\r\n s_typeAvatar: l_objUser.s_typeAvatar,\r\n messageKey: l_strMessageKey,\r\n b_isDelivered: true,\r\n type: \"bot\",\r\n };\r\n\r\n messageDatasource.addToMessageList(l_objMessage, 1);\r\n return\r\n }\r\n\r\n if (response.message != null) {\r\n var l_objResponse = response;\r\n var l_lngTime = moment.utc().valueOf();\r\n var l_strMessageKey = Math.random().toString(36).substring(2) + l_lngTime.toString();\r\n\r\n l_objResponse.message = $.trim(response.message);\r\n l_objResponse.roomType = l_objRoom.roomType;\r\n l_objResponse.roomkey = l_objRoom.s_key;\r\n l_objResponse.time = l_lngTime;\r\n l_objResponse.messageKey = l_strMessageKey;\r\n messageService.outgoingMessage(l_objResponse);\r\n\r\n //write now on timeline\r\n var l_objMessage = {\r\n sender: l_objUser.userName,\r\n senderKey: l_objUser.s_key,\r\n message: l_objResponse.message,\r\n date: l_objResponse.time,\r\n s_avatar: l_objUser.s_avatar,\r\n s_typeAvatar: l_objUser.s_typeAvatar,\r\n messageKey: l_strMessageKey,\r\n b_isDelivered: false\r\n };\r\n if (l_objRoom.b_readOnly == null || l_objRoom.b_readOnly == false || (l_objRoom.b_readOnly && l_objUser.type == 1)) {\r\n messageDatasource.addToMessageList(l_objMessage, 1);\r\n messageDatasource.refreshDayText();\r\n }\r\n }\r\n });\r\n\r\n\r\n $scope.$on('UserStatusChange', function (event, data) {\r\n //update chatbox users\r\n $('body').chatBox.updateUserList(userService.getForChatbox());\r\n });\r\n\r\n if (currentRoom.roomType == 3) {\r\n $('.chatDiv').css('display', 'none');\r\n $(\".center-container\").css('bottom', '0');\r\n }\r\n\r\n $scope.$on('UserStatusChange', function (event, data) {\r\n //update chatbox users\r\n $('body').chatBox.updateUserList(userService.getForChatbox());\r\n });\r\n };\r\n\r\n $scope.$on('initial', function (event, data) {\r\n if (chatBoxVariables == null) {\r\n var l_lstEmojis = emojiService.getEmojis(),\r\n l_lstEmojisParsed = [];\r\n _createChatBox();\r\n }\r\n });\r\n\r\n $scope.$on('ChangeRoom', function (event, data) {\r\n\r\n if (data && data.roomType == 4) {\r\n return;\r\n }\r\n var l_objRoom = chatRoomService.getCurrentRoom();\r\n var l_objUser = userService.getCurrentUser();\r\n\r\n if (l_objRoom != null && l_objUser != null) {\r\n if (l_objRoom && l_objRoom.trialReadonly) {\r\n $(\"#chatbox\").prop('contenteditable', 'false');\r\n $(\"#chatbox\").css('cursor', 'not-allowed');\r\n $(\"#uploadBtn\").css('cursor', 'not-allowed');\r\n $(\"#uploadBtn\").attr('disabled', 'disabled');\r\n $(\".chatDiv\").attr('title', 'This chatroom is read-only for trial members.')\r\n } else if (l_objRoom.b_readOnly == null || l_objRoom.b_readOnly == false || (l_objRoom.b_readOnly && (l_objUser.type == 1 || l_objUser.type == 2 || l_objUser.type == 3))) {\r\n $(\"#chatbox\").prop('contenteditable', 'true');\r\n $(\"#chatbox\").css('cursor', 'text');\r\n $(\"#uploadBtn\").css('cursor', 'pointer');\r\n $(\"#uploadBtn\").removeAttr('disabled', 'disabled');\r\n $(\".chatDiv\").removeAttr('title');\r\n\r\n } else {\r\n $(\"#chatbox\").prop('contenteditable', 'false');\r\n $(\"#chatbox\").css('cursor', 'not-allowed');\r\n $(\"#uploadBtn\").css('cursor', 'not-allowed');\r\n $(\"#uploadBtn\").attr('disabled', 'disabled');\r\n $(\".chatDiv\").attr('title', 'This is a read-only chatroom. Only admins can send messages.')\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 .directive('hamburgerDrv', [function () {\r\n return {\r\n replace: true,\r\n template: '',\r\n controller: function ($scope, $element, $rootScope) { },\r\n link: function (scope, elem, attrs) {\r\n var initial = parseInt($('.navbar-fixed-top').css(\"left\").replace('px', ''));\r\n var el = document.querySelectorAll('.hamburger');\r\n if (el.length > 0) {\r\n el[0].addEventListener('click', function () {\r\n this.classList.toggle('active');\r\n\r\n if (this.classList.contains(\"active\")) {\r\n $('#navbar').css(\"display\", \"\");\r\n $('.navbar-fixed-top').css(\"left\", initial.toString() + 'px');\r\n $('.main').css(\"margin-left\", (initial + 10).toString() + 'px');\r\n $('.main2').css(\"margin-left\", (initial).toString() + 'px');\r\n $('.chatDiv').css(\"left\", (initial + 10).toString() + 'px');\r\n $('.alertDiv').css(\"left\", (initial).toString() + 'px');\r\n\r\n } else {\r\n $('#navbar').css(\"display\", \"none\");\r\n $('.navbar-fixed-top').css(\"left\", \"0\");\r\n $('.main').css(\"margin-left\", \"10px\");\r\n $('.main2').css(\"margin-left\", \"0\");\r\n $('.chatDiv').css(\"left\", \"10px\");\r\n $('.alertDiv').css(\"left\", \"0\");\r\n }\r\n }, false);\r\n }\r\n\r\n }\r\n }\r\n }])\r\n\r\n .directive('imageonload', [function () {\r\n return {\r\n restrict: 'A',\r\n scope: {\r\n imageloader: '@',\r\n imageurl: '@',\r\n isuploaded: '@',\r\n scrollcontainer: '@',\r\n youtubeid: '@',\r\n imageurlfull: '@'\r\n },\r\n link: function (scope, element, attrs) {\r\n //'https://img.youtube.com/vi/' + scope.youtubeid + '/0.jpg'\r\n element.attr(\"src\", scope.imageloader)\r\n\r\n element.bind('load', function () {\r\n var raw = element[0];\r\n if (attrs[\"autoScroll\"] == 'true') {\r\n $(scope.scrollcontainer).scrollTop($(scope.scrollcontainer)[0].scrollHeight);\r\n }\r\n });\r\n\r\n element.bind('error', function () {\r\n var n = element.attr(\"src\").indexOf(\".thumb.\");\r\n if (n >= 0) {\r\n element.attr(\"src\", scope.imageurlfull);\r\n }\r\n });\r\n\r\n scope.$on('UploadDone', function (event, data) {\r\n if (scope.imageurl.indexOf(data.s_token) > -1) {\r\n if (scope.isuploaded == 'true') {\r\n element.attr(\"src\", scope.imageurl);\r\n } else {\r\n element.attr(\"src\", imageloader);\r\n }\r\n }\r\n });\r\n if (scope.imageurl.indexOf('null.thumb.null') < 0) {\r\n if (scope.isuploaded == 'true') {\r\n element.attr(\"src\", scope.imageurl);\r\n }\r\n }\r\n if (scope.imageurl.indexOf('null.null') < 0 && scope.imageurl.indexOf('null.thumb.null') < 0) {\r\n if (scope.isuploaded == 'true') {\r\n element.attr(\"src\", scope.imageurl);\r\n }\r\n }\r\n\r\n\r\n }\r\n };\r\n }])\r\n\r\n .directive('usersGroup', ['$rootScope', '$location', 'userService', 'notifyService',\r\n function ($rootScope, $location, userService, notifyService) {\r\n return {\r\n replace: false,\r\n scope: {\r\n type: '@',\r\n grouptitle: '@',\r\n banned: '@',\r\n groupicon: '@',\r\n totalusers: \"=\",\r\n isgroupadmin: '=',\r\n filteroffline: '=',\r\n filtername: '='\r\n },\r\n templateUrl: 'users-group.html',\r\n link: function (scope, elem, attrs) {\r\n var l_intType = parseInt(scope.type),\r\n l_bIsBanned = (scope.banned == \"true\"),\r\n bLazy = null;\r\n\r\n var _loadBLazy = function () {\r\n bLazy = new Blazy({\r\n container: '#dvTools',\r\n src: 'a-blazy',\r\n success: function (ele) {\r\n },\r\n error: function (ele, msg) {\r\n }\r\n });\r\n };\r\n scope.safeApply = function (fn) {\r\n var phase = this.$root.$$phase;\r\n if (phase == '$apply' || phase == '$digest') {\r\n if (fn && (typeof (fn) === 'function')) {\r\n fn();\r\n }\r\n } else {\r\n this.$apply(fn);\r\n }\r\n };\r\n scope.ToggleOffline = function () {\r\n scope.blnShowAllToggle = !scope.blnShowAllToggle\r\n _loadBLazy();\r\n };\r\n scope.BanUser = function (user, ban) {\r\n if (ban)\r\n userService.banUser({\r\n userKey: user.s_key\r\n }).then(function (data) {\r\n });\r\n else\r\n userService.unbanUser({\r\n userKey: user.s_key\r\n }).then(function (data) {\r\n });\r\n };\r\n scope.BlockUser = function (user, block) {\r\n if (block)\r\n userService.blockUser({\r\n userKey: user.s_key\r\n }).then(function (data) {\r\n });\r\n else\r\n userService.unblockUser({\r\n userKey: user.s_key\r\n }).then(function (data) {\r\n });\r\n };\r\n\r\n var _makeClear = function (a_strKey) {\r\n if (a_strKey != null && a_strKey.length > 0)\r\n return a_strKey.substring(a_strKey.length - 8, a_strKey.length);\r\n else\r\n return a_strKey;\r\n }\r\n\r\n scope.$on('NewUser', function (event, data) {\r\n data.n_count = 0;\r\n //copy clear key\r\n data.s_clearkey = _makeClear(data.s_key);\r\n //make key full (compatibility)\r\n data.s_key = \"private-u-\" + data.s_clearkey;\r\n //separate current user from team user's\r\n data.b_isCurrent = false;\r\n //find if the text of that user should be bold all the time\r\n //data.b_bold = true;\r\n\r\n //dirty, compatibility code\r\n data.status = data.Status;\r\n data.userName = data.UserName;\r\n data.type = data.Type;\r\n //dirty compatibility code end\r\n\r\n //if user was never logon we will convert him to unavailable\r\n if (data.status == null) {\r\n data.status = 2;\r\n };\r\n\r\n data.n_count = 0;\r\n data.b_isPinned = false;\r\n data.b_isCurrent = false;\r\n userService.addUser(data);\r\n\r\n scope.safeApply(_loadBLazy);\r\n\r\n });\r\n $rootScope.$on('blk', function (event, data) {\r\n scope.$apply();\r\n });\r\n $rootScope.$on('unblk', function (event, data) {\r\n scope.$apply();\r\n });\r\n scope.$on('UserStatusChange', function (event, data) {\r\n _loadBLazy();\r\n scope.$apply();\r\n });\r\n }\r\n }\r\n }\r\n ])\r\n\r\n .directive('refreshable', [function () {\r\n return {\r\n restrict: 'A',\r\n scope: {\r\n refresh: \"=refreshable\"\r\n },\r\n link: function (scope, element, attr) {\r\n var refreshMe = function () {\r\n element.attr('src', element.attr('src'));\r\n };\r\n\r\n scope.$watch('refresh', function (newVal, oldVal) {\r\n if (scope.refresh) {\r\n scope.refresh = false;\r\n refreshMe();\r\n }\r\n });\r\n }\r\n };\r\n }])\r\n\r\n .directive('tooltip', ['$rootScope',\r\n function ($rootScope) {\r\n return {\r\n replace: false,\r\n scope: {},\r\n link: function (scope, element, attrs) {\r\n $(element).popover({\r\n container: 'body',\r\n trigger: 'manual',\r\n content: '
    ' + attrs.title + '
    ',\r\n template: '
    ',\r\n placement: \"right\",\r\n html: true\r\n }).click(function () {\r\n\r\n });\r\n $(element).hover(function () {\r\n $(element).popover('show');\r\n }, function () {\r\n $(element).popover('hide');\r\n });\r\n //scope.$apply();\r\n //$(element).on('shown.bs.tooltip', function () {\r\n // //$(this).tooltip('show');\r\n // scope.$apply();\r\n //});\r\n //$(element).hover(function () {\r\n // // on mouseenter\r\n // $(element).tooltip('show');\r\n //}, function () {\r\n // // on mouseleave\r\n // $(element).tooltip('hide');\r\n //});\r\n }\r\n };\r\n }\r\n ])\r\n\r\n .directive('headerNavTrial', ['$rootScope', '$location', '$timeout', '$interval', 'chatRoomService', 'tokenService', 'userService',\r\n function ($rootScope, $location, $timeout, $interval, chatRoomService, tokenService, userService) {\r\n return {\r\n controller: function ($scope, $element) {\r\n var l_strFormat = 'HH:mm A',\r\n l_strDateFormat = null,\r\n l_strTimezone = null;\r\n\r\n $rootScope.$on('initial', function (event, data) {\r\n l_strDateFormat = userService.getUserDateFormat();\r\n l_strTimezone = userService.getUserTimezone();\r\n });\r\n\r\n $rootScope.$on('ChangeRoomData', function (event, data) {\r\n $scope.expireText = null;\r\n\r\n //var updateTime = function updateTime() {\r\n // //var l_intDiff = l_dExpires.diff(moment.utc(), 'days');\r\n // //if (l_intDiff == 0) {\r\n // // $scope.expireText = 'Trial expires today';\r\n // //} else if (l_intDiff == 1) {\r\n // // $scope.expireText = 'Trial expires in 1 day';\r\n // //} else {\r\n // // $scope.expireText = 'Trial expires in ' + (l_intDiff + 1) + ' days';\r\n // //}\r\n\r\n\r\n //};\r\n\r\n if (data.trialExpires) {\r\n //var l_dExpires = moment(data.trialExpires);\r\n if (l_strTimezone != null) {\r\n $scope.expireText = 'Trial expires on ' + moment.utc(data.trialExpires).tz(l_strTimezone).format(l_strDateFormat + ' ' + l_strFormat);\r\n } else {\r\n $scope.expireText = 'Trial expires on ' + moment.utc(data.trialExpires).format('DD/MM hh:mm');\r\n }\r\n //stopTime = $interval(updateTime, 1000);\r\n //$element.on('$destroy', function () {\r\n // $interval.cancel(stopTime);\r\n //});\r\n\r\n\r\n }\r\n });\r\n\r\n $rootScope.$on('BeforeChangeRoom', function (event, data) {\r\n //clear before the page loads so the user doesn't confuse it\r\n $scope.expireText = null;\r\n //$interval.cancel(stopTime);\r\n });\r\n\r\n },\r\n link: function ($scope, element, attrs) {\r\n\r\n $scope.Payment = function () {\r\n\r\n var l_objChatRoom = chatRoomService.getCurrentRoom();\r\n $rootScope.$broadcast('LoadPayment', {\r\n chatroom: l_objChatRoom,\r\n config: {\r\n data: null\r\n }\r\n });\r\n }\r\n\r\n\r\n } //DOM manipulation\r\n };\r\n }\r\n ])\r\n\r\n .directive('headerCompanySidebar', ['$rootScope', 'userService',\r\n function ($rootScope, userService) {\r\n return {\r\n replace: true,\r\n scope: {},\r\n templateUrl: 'sidebar-company-header.html',\r\n link: function (scope, element) {\r\n\r\n $rootScope.$on('initial', function (event, data) {\r\n var l_objTeamProperties = userService.getTeamProperties();\r\n scope.teamName = l_objTeamProperties.s_name;\r\n scope.imageLink = l_objTeamProperties.avatar;\r\n if (l_objTeamProperties.showUserCount) {\r\n var l_intTeamUserCount = userService.getTeam().length + 1;\r\n\r\n scope.memberText = l_intTeamUserCount.toString() + \" member\";\r\n\r\n if (l_intTeamUserCount > 1)\r\n scope.memberText += \"s\";\r\n\r\n }\r\n });\r\n\r\n }\r\n }\r\n }\r\n ]);","'use strict';\r\n\r\nangular.module('chat.pin.message', ['chat.user', 'chat.notify', 'chat.room'])\r\n .service('pinDataService', ['$window', '$http', '$q', function ($window, $http, $q) {\r\n\r\n var url = {\r\n unpinMessage: 'api/message/unpin'\r\n };\r\n\r\n if ($window.localStorage) {\r\n // console.log('local storage working');\r\n } else {\r\n // console.log('local storage not working');\r\n }\r\n\r\n var _setItem = function (a_strRoomKey, a_strMessage) {\r\n if ($window.localStorage)\r\n $window.localStorage.setItem(a_strRoomKey, a_strMessage);\r\n }\r\n\r\n var _getItem = function (a_strRoomKey) {\r\n if ($window.localStorage)\r\n return $window.localStorage.getItem(a_strRoomKey);\r\n }\r\n\r\n var _unpinMessage = function (data) {\r\n var deferred = $q.defer();\r\n $http.post(url.unpinMessage, data)\r\n .success(function (a_data, status, headers, config) {\r\n deferred.resolve(a_data);\r\n })\r\n .error(function (data, status, headers, config) {\r\n notifyService.showError(\"Get Data \", 'error ' + status + ' get ' + url.unpinMessage);\r\n deferred.reject();\r\n });\r\n\r\n return deferred.promise;\r\n };\r\n\r\n\r\n return {\r\n setItem: _setItem,\r\n getItem: _getItem,\r\n unpinMessage: _unpinMessage\r\n }\r\n }])\r\n .directive('pinMessageDirective', [\r\n 'userService', 'pinDataService', 'notifyService', 'chatRoomService',\r\n function (userService, pinDataService, notifyService, chatRoomService) {\r\n return {\r\n templateUrl: 'pin-message.html',\r\n scope: { },\r\n controller: function ($scope) {\r\n var m_strRoomKey = null,\r\n m_strLastEdit = null;\r\n\r\n $scope.l_pinBoxShow = false;\r\n $scope.l_blnPinBoxVisible = false;\r\n \r\n $scope.$on('AdminPinMessage', function (event, data) {\r\n\r\n m_strRoomKey = data.RoomKey;\r\n m_strLastEdit = moment(data.Message.d_lastEdit).valueOf();\r\n\r\n var l_objRoom = chatRoomService.getCurrentRoom();\r\n var l_objStorageVal = pinDataService.getItem(data.RoomKey);\r\n var l_objUser = userService.getUserByName(data.Message.s_sender);\r\n // console.log('AdminPinMessage', data, l_objStorageVal, moment(data.Message.d_lastEdit).valueOf(), l_objRoom.s_key, data.RoomKey);\r\n if (!pinDataService.getItem(data.s_key) && l_objStorageVal != moment(data.Message.d_lastEdit).valueOf() && l_objRoom.s_key == data.RoomKey) {\r\n $scope.l_pinBoxShow = true;\r\n $scope.l_blnPinBoxVisible = true;\r\n $scope.item = {\r\n senderKey: l_objUser.s_key,\r\n s_avatar: l_objUser.s_avatar,\r\n b_isContinuing: false,\r\n sender: data.Message.s_sender,\r\n userType: l_objUser.type,\r\n date: data.Message.d_lastEdit,\r\n b_delivered: true,\r\n n_fileType: data.Message.n_fileType,\r\n s_extension: data.Message.s_extension,\r\n s_fileToken: data.Message.s_fileToken,\r\n message: data.Message.s_message,\r\n type: data.Message.n_fileType\r\n }\r\n $scope.safeApply();\r\n }\r\n });\r\n\r\n $scope.$on('ChangeRoomData', function (event, data) {\r\n var l_objStorageVal = pinDataService.getItem(data.s_key);\r\n // console.log('pinMessageDirective ChangeRoom', data, l_objStorageVal);\r\n if (data.pinned != null && l_objStorageVal != moment(data.pinned.d_lastEdit).valueOf()) {\r\n m_strRoomKey = data.s_key;\r\n m_strLastEdit = moment(data.pinned.d_lastEdit).valueOf();\r\n\r\n var l_objUser = userService.getUserByName(data.pinned.s_sender);\r\n $scope.l_pinBoxShow = true;\r\n $scope.l_blnPinBoxVisible = true;\r\n $scope.item = {\r\n senderKey: l_objUser.s_key,\r\n s_avatar: l_objUser.s_avatar,\r\n b_isContinuing: false,\r\n sender: data.pinned.s_sender,\r\n userType: l_objUser.type,\r\n date: data.pinned.d_lastEdit,\r\n b_delivered: true,\r\n n_fileType: data.pinned.n_fileType,\r\n s_extension: data.pinned.s_extension,\r\n s_fileToken: data.pinned.s_fileToken,\r\n message: data.pinned.s_message,\r\n type: data.pinned.n_fileType\r\n }\r\n $scope.safeApply();\r\n }\r\n });\r\n\r\n $scope.$on('AdminUnpinMessage', function (event, data) {\r\n var l_objRoom = chatRoomService.getCurrentRoom();\r\n // console.log('AdminUnpinMessage', l_objRoom, data);\r\n if (l_objRoom.s_clearKey === data.RoomKey)\r\n {\r\n _justClose();\r\n $scope.safeApply();\r\n }\r\n });\r\n\r\n $scope.HidePinBox = _hidePinBox;\r\n\r\n function _hidePinBox() {\r\n var l_objCurrentUser = userService.getCurrentUser(),\r\n l_objRoom = chatRoomService.getCurrentRoom();\r\n\r\n // console.log('l_objCurrentUser', l_objCurrentUser);\r\n if (l_objCurrentUser && (l_objCurrentUser.type === 1 || l_objCurrentUser.type === 2 || l_objCurrentUser.type === 3))\r\n notifyService.confirm('This will remove notice from all users. Are you sure?', function () {\r\n pinDataService.unpinMessage({\r\n roomkey: l_objRoom.s_key\r\n }).then(function () { });\r\n });\r\n else {\r\n pinDataService.setItem(m_strRoomKey, m_strLastEdit);\r\n _justClose();\r\n }\r\n\r\n }\r\n\r\n function _justClose() {\r\n $scope.l_blnPinBoxVisible = false;\r\n $scope.l_pinBoxShow = false;\r\n\r\n }\r\n\r\n $scope.safeApply = function (fn) {\r\n var phase = this.$root.$$phase;\r\n if (phase == '$apply' || phase == '$digest') {\r\n if (fn && (typeof (fn) === 'function')) {\r\n fn();\r\n }\r\n } else {\r\n this.$apply(fn);\r\n }\r\n };\r\n\r\n }\r\n }\r\n }]);\r\n","'use strict';\r\n\r\nangular.module('chat.istyping', [\r\n 'chat.room',\r\n 'chat.push',\r\n 'chat.user'\r\n])\r\n\r\n .service('typingLogic', [\r\n '$sce', '$rootScope', '$interval', '$timeout', '$http', '$q', 'pushService', 'userService', 'chatRoomService',\r\n function ($sce, $rootScope, $interval, $timeout, $http, $q, pushService, userService, chatRoomService) {\r\n\r\n var _isTyping = false,\r\n _dt = new Date(),\r\n url = {\r\n isTyping: 'api/user/istyping'\r\n },\r\n _dtLastPost = new Date(),\r\n _typing_users = [],\r\n _typing_dates = [],\r\n l_objCurrentUser = null,\r\n roomKey = null;\r\n\r\n $rootScope.$on('IncomingMessage', function (event, data) {\r\n if (data.SenderKey.startsWith('private-u-')) {\r\n _removeNonTyping(data.SenderKey.replace(\"private-u-\", \"\") + '|' + data.ReceiverKey.replace(\"private-u-\", \"\"));\r\n } else {\r\n _removeNonTyping(data.SenderKey + '|' + roomKey.replace(\"pub-\", \"\").replace(\"private-t-\", \"\"));\r\n }\r\n refreshTyping();\r\n });\r\n\r\n $rootScope.$on('ChangeRoom', function (event, data) {\r\n if (data != null) {\r\n if (data.s_clearKey != null)\r\n roomKey = data.s_clearKey;\r\n else\r\n roomKey = data.s_clearkey\r\n l_objCurrentUser = userService.getCurrentUser();\r\n }\r\n });\r\n\r\n var _postTyping = function () {\r\n _dtLastPost = new Date();\r\n var deferred = $q.defer();\r\n $http\r\n .post(url.isTyping,\r\n JSON.stringify({\r\n typing: _isTyping,\r\n room: chatRoomService.getCurrentRoom().s_key\r\n }),\r\n {\r\n headers: {\r\n 'Content-Type': 'application/json'\r\n }\r\n }\r\n )\r\n .success(function (a_data, status, headers, config) {\r\n deferred.resolve(a_data);\r\n })\r\n .error(function (data, status, headers, config) {\r\n deferred.reject();\r\n });\r\n\r\n return deferred.promise;\r\n };\r\n\r\n var _setTyping = function () {\r\n //console.log(\"setTyping\", _isTyping)\r\n _dt = new Date();\r\n if (!_isTyping) { //no typing\r\n _isTyping = true;\r\n _postTyping();\r\n $timeout(_checkTyping, 7000);\r\n }\r\n };\r\n\r\n var _checkTyping = function () {\r\n //console.log(\"setTyping\", _isTyping, _dt)\r\n var now = new Date()\r\n if (_isTyping && now.getTime() - _dt.getTime() < 1000) {\r\n _postTyping();\r\n $timeout(_checkTyping, 7000);\r\n } else {\r\n _isTyping = false;\r\n }\r\n refreshTyping();\r\n };\r\n\r\n var _findUser = function (a_strUserKey) {\r\n for (var i = 0; i < _typing_users.length; i++) {\r\n if (_typing_users[i] == a_strUserKey)\r\n return i;\r\n }\r\n return null;\r\n };\r\n\r\n var _removeNonTyping = function (a_strUserKey) {\r\n var l_intIndex = _findUser(a_strUserKey);\r\n if (l_intIndex != null) {\r\n _typing_users.splice(l_intIndex, 1);\r\n _typing_dates.splice(l_intIndex, 1);\r\n }\r\n }\r\n\r\n var _checkNonTyping = function () {\r\n var now = new Date();\r\n for (var i = 0; i < _typing_dates.length; i++) {\r\n if (now.getTime() - _typing_dates[i].getTime() > 6 * 1000) {\r\n _typing_users.splice(i, 1);\r\n _typing_dates.splice(i, 1);\r\n }\r\n }\r\n }\r\n\r\n var _getTypingText = function () {\r\n _checkNonTyping();\r\n var l_strReturn = '';\r\n var l_intCount = 0;\r\n\r\n for (var i = 0; i < _typing_users.length; i++) {\r\n var l_arrUser = _typing_users[i].split('|');\r\n var l_objUser = userService.getUserByClearKey(l_arrUser[0]);\r\n\r\n l_objCurrentUser = userService.getCurrentUser();\r\n\r\n // console.log('check user', l_arrUser, l_objCurrentUser.s_clearkey, roomKey);\r\n if (l_objUser == null) {\r\n // console.log('_getTypingText user not found', _typing_users[i], userService.getAll());\r\n } else if (l_objCurrentUser == null) {\r\n\r\n } else if (l_arrUser == null || l_arrUser.length < 2) {\r\n\r\n } else if (l_arrUser[0] != l_objCurrentUser.s_clearkey && l_arrUser[1] == roomKey) {\r\n // console.log('add user', _typing_users[i], l_objCurrentUser.s_clearkey);\r\n if (l_intCount < 5) {\r\n l_strReturn += '' + l_objUser.userName + ', ';\r\n }\r\n l_intCount += 1;\r\n } else if (l_arrUser[0] == roomKey && l_arrUser[1] == l_objCurrentUser.s_clearkey) {\r\n l_strReturn += '' + l_objUser.userName + '';\r\n l_intCount += 1;\r\n }\r\n };\r\n\r\n if (l_strReturn.length > 0) {\r\n if (l_strReturn.indexOf(', ', l_strReturn.length - 2) !== -1)\r\n l_strReturn = l_strReturn.substring(0, l_strReturn.length - 2);\r\n\r\n if (l_intCount > 5) {\r\n l_strReturn += ' and ' + (l_intCount - 5) + ' more'\r\n }\r\n if (l_intCount == 1) {\r\n l_strReturn += ' is typing';\r\n } else if (l_intCount > 1) {\r\n l_strReturn += ' are typing';\r\n }\r\n\r\n l_strReturn += ' ';\r\n // console.log('l_intCount', l_intCount, l_strReturn);\r\n }\r\n\r\n return l_strReturn;\r\n }\r\n\r\n var refreshTyping = function () {\r\n //console.log('refreshTyping', _typing_users, _typing_dates);\r\n var typingText = _getTypingText();\r\n var trustedTypingText = $sce.trustAsHtml(typingText);\r\n $rootScope.$broadcast(\"IsTypingChanged\", trustedTypingText)\r\n }\r\n\r\n $rootScope.$on('istyping', function (event, data) {\r\n //console.log('event: istyping');\r\n _checkNonTyping();\r\n if (data.typing) {\r\n var l_intIdx = _findUser(data.user + '|' + data.roomKey);\r\n var now = new Date();\r\n if (l_intIdx == null) {\r\n _typing_users.push(data.user + '|' + data.roomKey);\r\n _typing_dates.push(now);\r\n } else {\r\n _typing_dates[l_intIdx] = now;\r\n }\r\n } else {\r\n _removeNonTyping(data.user + '|' + data.roomKey);\r\n }\r\n\r\n refreshTyping();\r\n\r\n $timeout(function () {\r\n //console.log('$timeout refreshTyping');\r\n refreshTyping();\r\n }, 7 * 1000);\r\n });\r\n\r\n return {\r\n setTyping: _setTyping,\r\n getTypingText: _getTypingText,\r\n removeNonTyping: _removeNonTyping\r\n };\r\n }])\r\n\r\n .directive('typingHandler', ['typingLogic',\r\n function (typingLogic) {\r\n return {\r\n scope: {},\r\n link: function (scope, element) {\r\n scope.$on('initial', function (event, data) {\r\n $(\"#chatbox\").on(\"keypress\", typingLogic.setTyping);\r\n $(\"#chatbox\").on(\"keyup\", typingLogic.setTyping);\r\n $(\"#chatbox\").on(\"keydown\", typingLogic.setTyping);\r\n });\r\n }\r\n }\r\n }\r\n ]);","angular\r\n .module(\"chat.session\", [])\r\n .service(\"SessionService\", SessionService)\r\n\r\nSessionService.$inject = [\"$http\", \"$q\", \"$interval\", \"AppError\", \"$timeout\", \"$window\", \"$rootScope\"]\r\n\r\nfunction SessionService($http, $q, $interval, AppError, $timeout, $window, $rootScope) {\r\n var createSessionAfterSeconds = 5\r\n var intervalSeconds = 30\r\n var intervalProcess = null\r\n var failedIntervals = 0\r\n var setupObject = {}\r\n\r\n var service = {\r\n _session: null,\r\n isIdle: true,\r\n setup: setup,\r\n update: update,\r\n }\r\n return service\r\n\r\n function setup() {\r\n\r\n getProperties()\r\n .then(function (properties) {\r\n $timeout(function () {\r\n $http\r\n .post(\"api/session/create\", properties)\r\n .then(\r\n function (response) {\r\n if (!response) {\r\n //Raygun.send(new Error(\"user-analytics without response\"), data)\r\n return\r\n }\r\n service._session = response.data.session\r\n console.debug(\"Session created:\", service._session)\r\n\r\n setupInterval()\r\n setupUserIdle()\r\n },\r\n function (err) {\r\n AppError.Send(\r\n new Error(\"user-analytics failed to initialize\", {\r\n error: err,\r\n session: service._session,\r\n obj: data\r\n })\r\n )\r\n }\r\n )\r\n }, createSessionAfterSeconds * 1000)\r\n })\r\n\r\n }\r\n\r\n function getProperties() {\r\n return $q(function (resolve, reject) {\r\n setupObject = {}\r\n var genericFP = new Fingerprint2()\r\n var machineFP = new Fingerprint2({\r\n //getOS\r\n //getOSVersion\r\n //getDevice\r\n //getDeviceType\r\n //getCPU\r\n //isMobile\r\n //getColorDepth\r\n excludeUserAgent: true,\r\n excludeLanguage: true,\r\n excludeColorDepth: true,\r\n excludeScreenResolution: true,\r\n excludeTimezoneOffset: true,\r\n excludeSessionStorage: true,\r\n excludeIndexedDB: true,\r\n excludeAddBehavior: true,\r\n excludeOpenDatabase: true,\r\n excludeCpuClass: false,\r\n excludePlatform: false,\r\n excludeDoNotTrack: true,\r\n excludeCanvas: true,\r\n excludeWebGL: true,\r\n excludeAdBlock: true,\r\n excludeHasLiedLanguages: true,\r\n excludeHasLiedResolution: true,\r\n excludeHasLiedOs: true,\r\n excludeHasLiedBrowser: true,\r\n excludeJsFonts: true,\r\n excludeFlashFonts: true,\r\n excludePlugins: true,\r\n excludeIEPlugins: true,\r\n excludeTouchSupport: true,\r\n excludePixelRatio: true\r\n })\r\n var uaparser = new UAParser()\r\n\r\n genericFP.get(function (generic_Result) {\r\n machineFP.get(function (machine_Result) {\r\n setupObject = {\r\n genericID: generic_Result,\r\n machineID: machine_Result,\r\n osName: uaparser.getOS().name + uaparser.getOS().version,\r\n browserName: uaparser.getBrowser().name,\r\n browserVersion: uaparser.getBrowser().version\r\n }\r\n resolve(setupObject)\r\n })\r\n })\r\n })\r\n }\r\n\r\n function update() {\r\n\r\n if (!service._session) {\r\n return\r\n }\r\n\r\n if (failedIntervals > 4 && intervalProcess) {\r\n $interval.cancel(intervalProcess)\r\n return\r\n }\r\n\r\n $http\r\n .post(\"api/session/update\", {\r\n session: service._session,\r\n isIdle: service.isIdle,\r\n })\r\n .then(function (response) {\r\n if (!response) {\r\n failedIntervals++\r\n return\r\n }\r\n failedIntervals = 0\r\n // console.debug(\"Session updated:\", service._session)\r\n }, function (err) {\r\n failedIntervals++\r\n AppError.Send(\r\n new Error(\"user-analytics failed to update\", {\r\n error: err,\r\n session: service._session,\r\n obj: setupObject\r\n })\r\n )\r\n })\r\n }\r\n\r\n function setupInterval() {\r\n if (intervalProcess) {\r\n $interval.cancel(intervalProcess)\r\n }\r\n intervalProcess = $interval(service.update, intervalSeconds * 1000)\r\n }\r\n\r\n function setupUserIdle() {\r\n var timeoutIdle\r\n var idleTime = 5 * 60 * 1000 //5 minutes default\r\n\r\n var _check = function () {\r\n $timeout.cancel(timeoutIdle)\r\n if (service.isIdle) {\r\n //console.debug(\"User is active\")\r\n service.isIdle = false\r\n service.update()\r\n }\r\n timeoutIdle = $timeout(function () {\r\n //console.debug(\"User is idle\")\r\n service.isIdle = true\r\n service.update()\r\n }, idleTime)\r\n }\r\n\r\n $window.addEventListener(\"mousemove\", _check)\r\n $window.addEventListener(\"keypress\", _check)\r\n $window.addEventListener(\"focus\", _check)\r\n }\r\n\r\n}","'use strict';\r\n\r\nangular\r\n .module('chat', [\r\n 'ngRoute',\r\n 'ngCookies',\r\n 'ngAlertify',\r\n 'luegg.directives',\r\n 'chat.core',\r\n 'chat.emojis',\r\n 'chat.auth',\r\n 'chat.error',\r\n 'chat.browser',\r\n 'chat.push',\r\n 'chat.notify',\r\n 'chat.user',\r\n 'chat.message',\r\n 'chat.modal',\r\n 'chat.stream',\r\n 'chat.settings',\r\n 'chat.payment',\r\n 'chat.room',\r\n 'wiseguyAlerts',\r\n 'chat.alertstream',\r\n 'chat.popover',\r\n 'chat.pinned',\r\n 'chat.filterpanel',\r\n 'chat.widget.tradingview',\r\n 'chat.widget.vidbox',\r\n 'chat.invites',\r\n 'chat.introtutorial',\r\n 'chat.brokers',\r\n 'chat.templates',\r\n 'chat.layout',\r\n 'chat.alert.refresh',\r\n 'angulartics',\r\n 'angulartics.clicky',\r\n //'angulartics.google.tagmanager',\r\n \"chat.widgets-top\",\r\n 'ngScrollable',\r\n 'chat.right-panel',\r\n 'chat.analytics.google',\r\n 'chat.pin.message',\r\n 'chat.istyping',\r\n 'chat.luckyorange',\r\n 'chat.session',\r\n ])\r\n .run([\r\n \"$rootScope\",\r\n \"chatRoomService\",\r\n function configTitle($rootScope, chatRoomService) {\r\n $rootScope.$on('TotalUnreadsChanged', function (event, counter) {\r\n if (counter) {\r\n $rootScope.pageTitle = (counter === 1) ? counter + \" unread message\" : counter + \" unread messages\";\r\n return;\r\n }\r\n\r\n var currentRoom = chatRoomService.getCurrentRoom();\r\n if (currentRoom) {\r\n $rootScope.pageTitle = chatRoomService.getCurrentRoom().s_url;\r\n return;\r\n }\r\n $rootScope.pageTitle = \"...\";\r\n });\r\n $rootScope.pageTitle = \"loading...\";\r\n\r\n $(document).on(\"click\", \".mfp-img\", function () {\r\n $(\".mfp-close\").trigger(\"click\")\r\n })\r\n }\r\n ])\r\n .service('testService', ['$http', '$q',\r\n function ($http, $q) {\r\n\r\n var url = {\r\n testException: 'api/message/testexception'\r\n };\r\n\r\n var _testException = function () {\r\n var deferred = $q.defer();\r\n $http.get(url.testException)\r\n .success(function (a_data, status, headers, config) {\r\n deferred.resolve(a_data);\r\n })\r\n .error(function (data, status, headers, config) {\r\n notifyService.showError(\"Get Data \", 'error ' + status + ' get ' + url.testException);\r\n deferred.reject();\r\n });\r\n\r\n return deferred.promise;\r\n };\r\n\r\n\r\n return {\r\n testException: _testException\r\n }\r\n }\r\n ])\r\n .directive('debugButton', ['$rootScope', '$location', 'notifyService', 'NotificationsService', 'messageDatasource',\r\n function ($rootScope, $location, notifyService, NotificationsService, messageDatasource) {\r\n return {\r\n link: function (scope, element, attrs) {\r\n //var l_intDvCenterHeight =\r\n if (l_blnDebug)\r\n element.css('display', 'block');\r\n\r\n //element.bind('click', function () {\r\n // $location.url('/#Amazing');\r\n //});\r\n }\r\n };\r\n }\r\n ])\r\n .controller('mainContainer', [\r\n 'IntroTutorialService', 'NotificationsService', 'SessionService', '$interval', '$scope', '$http', '$q',\r\n 'userService', 'messageService', '$rootScope', 'chatRoomService', 'emojiService', '$location', '$window',\r\n 'pinnedCore', 'streamDataService', 'brokersService', 'customStreamDataService', 'AnalyticsActions', 'AppError',\r\n\r\n function mainContainer(\r\n IntroTutorialService, NotificationsService, SessionService, $interval, $scope, $http, $q,\r\n userService, messageService, $rootScope, chatRoomService, emojiService, $location, $window,\r\n pinnedCore, streamDataService, brokersService, customStreamDataService, AnalyticsActions, AppError) {\r\n\r\n $scope.loading = true;\r\n\r\n $scope._settings = window._settings;\r\n\r\n $scope.$watch(function () {\r\n return brokersService.brokers\r\n }, function (val) {\r\n $scope.myBrokers = val;\r\n }, true)\r\n\r\n var _init = function () {\r\n customStreamDataService.setObject(Flashphoner);\r\n\r\n $q\r\n .when()\r\n .then(function () {\r\n return emojiService.setEmojisFromJSON();\r\n })\r\n .then(function () {\r\n return userService.getUserProperties().then(function (response) {\r\n if (response.success) {\r\n\r\n // Load stream properties\r\n streamDataService.l_strVideoId = response.data.teamProperties.l_strVideoId;\r\n streamDataService.l_blnLive = response.data.teamProperties.l_blnLive;\r\n\r\n //$rootScope.$broadcast('LoadedStream', null);\r\n\r\n userService.setUserDateFormat(response.data.userProperties.userDateFormat);\r\n userService.setUserTimezone(response.data.userProperties.userTimezone);\r\n userService.setUserFullname(response.data.userProperties.userFullname);\r\n userService.setIsStripeCustomer(response.data.userProperties.isStripeCustomer);\r\n\r\n userService._widgets = response.data.widgets;\r\n\r\n userService.setUserRoomProperties(response.data.userRoomProperties);\r\n\r\n try {\r\n chatRoomService.initChatRooms(response.data.pusherClientKey, response.data.rooms);\r\n userService.initUsers(response.data.userProperties.username, response.data.teamUsers, response.data.teamProperties, {\r\n notifyDMs: response.data.userProperties.notifyDMs,\r\n notifyMentions: response.data.userProperties.notifyMentions,\r\n notifyRooms: response.data.userProperties.notifyRooms,\r\n notifyFromAdmins: response.data.userProperties.properties.b_isNotifcFromAdmins,\r\n }, response.data.userProperties.activeSub,\r\n response.data.userProperties.activeConvs,\r\n response.data.userProperties.allowFree,\r\n response.data.userProperties.muteList,\r\n response.data.userProperties.key);\r\n\r\n for (var i = 0; i < response.data.userProperties.pinned.length; i++) {\r\n var l_objUser = userService.getUserByClearKey(response.data.userProperties.pinned[i]);\r\n if (l_objUser != null)\r\n pinnedCore.addUser(l_objUser);\r\n\r\n }\r\n } catch (e) {\r\n AppError.Send(e, response.data);\r\n }\r\n\r\n try {\r\n brokersService.load(response.data.brokers)\r\n\r\n } catch (e) {\r\n AppError.Send(e, response.data);\r\n }\r\n if (window.mixpanel) {\r\n\r\n mixpanel.identify(response.data.userProperties.email);\r\n\r\n mixpanel.people.set({\r\n $name: response.data.userProperties.userFullname,\r\n $email: response.data.userProperties.email,\r\n \"User Type\": response.data.userProperties.userType,\r\n \"Username\": response.data.userProperties.username,\r\n \"Team Name\": response.data.teamProperties.s_name,\r\n });\r\n\r\n mixpanel.register({\r\n \"Username\": response.data.userProperties.username,\r\n \"Team Name\": response.data.teamProperties.s_name,\r\n });\r\n\r\n mixpanel.track(\"chat-landing\", {});\r\n }\r\n\r\n SessionService.setup();\r\n\r\n if ($window.clicky_custom) {\r\n var clickySession = {\r\n username: response.data.userProperties.username,\r\n email: response.data.userProperties.email,\r\n userType: response.data.userProperties.userType,\r\n teamName: response.data.teamProperties.s_name,\r\n client: window.isDesktopClient ? \"desktop\" : \"browser\",\r\n }\r\n\r\n if (window.isDesktopClient) {\r\n clickySession[\"version\"] = window.desktopClientVersion\r\n }\r\n\r\n $window.clicky_custom[\"session\"] = clickySession\r\n\r\n $window.cl()\r\n }\r\n\r\n if ($window.Appcues) {\r\n $window.Appcues.identify(response.data.userProperties.key, {\r\n username: response.data.userProperties.username,\r\n email: response.data.userProperties.email,\r\n userType: response.data.userProperties.userType,\r\n teamName: response.data.teamProperties.s_name,\r\n });\r\n }\r\n\r\n if ($window.intercomSettings) {\r\n $window.intercomSettings.name = response.data.userProperties.username;\r\n $window.intercomSettings.email = response.data.userProperties.email;\r\n $window.IntercomLoad()\r\n }\r\n\r\n $scope.$on('ChangeRoom', function (event, data) {\r\n if (data != null) {\r\n $.fn.chatBox.setProperty('roomName', data.s_url);\r\n if ($window.Appcues) {\r\n $window.Appcues.start();\r\n }\r\n }\r\n });\r\n\r\n if (window.isDesktopClient) {\r\n window.parent.postMessage({\r\n event: \"teamLoad\",\r\n teamName: response.data.teamProperties.s_name\r\n }, \"*\")\r\n }\r\n\r\n $scope.rightWidgets = _.chain(response.data.widgets)\r\n .filter(function (w) {\r\n return w.config.position == 'right-bar' || !w.config.position;\r\n })\r\n .sortBy(function (w) {\r\n return w.sort;\r\n })\r\n .map(function (w) {\r\n if (w.config.hasBought && w.config.hasPremiumUrl && w.config.premiumUrl) {\r\n w.url = w.config.premiumUrl;\r\n }\r\n return w;\r\n })\r\n .value();\r\n\r\n\r\n $scope.topWidgets = _.chain(response.data.widgets)\r\n .filter(function (w) {\r\n return w.config.position == 'top-bar';\r\n })\r\n .sortBy(function (w) {\r\n return w.sort;\r\n })\r\n .map(function (w) {\r\n if (w.config.hasBought && w.config.hasPremiumUrl && w.config.premiumUrl) {\r\n w.url = w.config.premiumUrl;\r\n }\r\n w.key = w.key.replace(\".\", \"-\")\r\n return w;\r\n })\r\n .value();\r\n\r\n try {\r\n if (window.barepay && response.data.userProperties.stripeId) {\r\n window.barepay.params = {\r\n access_token_id: \"4iJDlnLMt2CIdf\",\r\n customer_oid: response.data.userProperties.stripeId\r\n };\r\n }\r\n } catch (e) {\r\n AppError.Send(e, response.data);\r\n }\r\n\r\n AnalyticsActions.setUsername(response.data.userProperties.username);\r\n\r\n userService.username = response.data.userProperties.username\r\n\r\n\r\n if (window.profitwell_enabled) {\r\n console.debug(\"profitwell enabled with email:\", response.data.userProperties.email)\r\n profitwell('user_email', response.data.userProperties.email);\r\n\r\n setInterval(function () {\r\n profitwell('user_email', response.data.userProperties.email);\r\n }, 1 * 60 * 60 * 1000)\r\n }\r\n\r\n }\r\n\r\n $scope.loading = false;\r\n $rootScope.$broadcast('initial', response.data);\r\n });\r\n\r\n })\r\n\r\n };\r\n\r\n NotificationsService.setup();\r\n\r\n _init();\r\n\r\n }\r\n ])\r\n .controller('messagesController', [\r\n 'IntroTutorialService', '$window', '$scope', '$http', '$rootScope', 'chatRoomService', 'messageService',\r\n 'userService', '$timeout', '$q', 'emojiService', '$compile', 'NotificationsService', 'messageDatasource',\r\n 'daysDatasource', 'brokersService', '$sce', 'AppError', '$interval', 'typingLogic',\r\n function messagesController(\r\n IntroTutorialService, $window, $scope, $http, $rootScope, chatRoomService,\r\n messageService, userService, $timeout, $q, emojiService, $compile, NotificationsService,\r\n messageDatasource, daysDatasource, brokersService, $sce, AppError, $interval, typingLogic) {\r\n\r\n var isLoading = false,\r\n chatRoom = null;\r\n\r\n try {\r\n chatRoom = chatRoomService.getCurrentRoom();\r\n } catch (e) {\r\n\r\n }\r\n if (window.mixpanel)\r\n chatRoomService.SendMixdata(chatRoom);\r\n\r\n var editMessageCallback = function (a_msgDate, a_msgText, a_msdDateEd) {\r\n if (messageDatasource.editMessageCallback(a_msgDate, a_msgText, a_msdDateEd)) {\r\n $scope.$apply();\r\n }\r\n };\r\n var deleteMessageCallback = function (a_msgDate) {\r\n if (messageDatasource.deleteMessageByDate(a_msgDate)) {\r\n $scope.$apply();\r\n }\r\n }\r\n var _checkToLoadMore = function () { };\r\n\r\n $scope.messages_loading = true\r\n\r\n var _handleInitialLoad = function (data) {\r\n\r\n $scope.messages_loading = false;\r\n\r\n\r\n var l_objTeamProperties = userService.getTeamProperties();\r\n var l_objLocalRoom = chatRoomService.getCurrentRoom();\r\n\r\n if (l_objTeamProperties && l_objTeamProperties.s_key && l_objLocalRoom && l_objTeamProperties.s_key != '875960cc' && l_objLocalRoom.roomType == 1) {\r\n $scope.invites_enabled = true\r\n }\r\n\r\n if (l_objTeamProperties.s_key != '875960cc') {\r\n $scope.imageloader = \"//cdn.echofin.co/images/loading.gif\"\r\n } else {\r\n $scope.imageloader = \"//cdn.echofin.co/images/wsj_loading.gif\"\r\n }\r\n\r\n if (data.success && data.auth) {\r\n for (var i = 0; i < data.data.length; i++) {\r\n\r\n if (data.s_key != l_objLocalRoom.s_key) {\r\n continue\r\n }\r\n var l_objMessage = null;\r\n //var l_objUser = userService.getUserByName(data.data[i].s_sender);\r\n var l_objUser = userService.getUserByClearKey(data.data[i].s_userkey);\r\n\r\n try {\r\n if (l_objUser != null) {\r\n l_objMessage = {\r\n sender: data.data[i].s_sender,\r\n senderKey: l_objUser.s_key,\r\n message: data.data[i].s_message,\r\n date: data.data[i].d_created,\r\n time: moment.utc(data.data[i].d_created).valueOf(),\r\n s_avatar: l_objUser.s_avatar,\r\n s_typeAvatar: l_objUser.s_typeAvatar,\r\n s_path: '//cdn.echofin.co/uploads/' + l_objUser.s_key.substring(10) + '/',\r\n s_fileName: data.data[i].s_fileName,\r\n s_fileToken: data.data[i].s_fileToken,\r\n s_extension: data.data[i].s_extension,\r\n n_fileType: data.data[i].n_fileType,\r\n s_fileDescr: data.data[i].s_fileDescr,\r\n s_fileLink: data.data[i].s_fileLink,\r\n b_isUploaded: true,\r\n b_isDelivered: true\r\n };\r\n messageDatasource.addToMessageList(l_objMessage, 0);\r\n }\r\n } catch (e) {\r\n AppError.Send(e, {\r\n location: 'getRoomMessages',\r\n message: l_objMessage,\r\n sender: l_objUser,\r\n chatRoomKey: l_objLocalRoom.s_key,\r\n user: userService.getCurrentUser()\r\n });\r\n //l_objMessage\r\n }\r\n\r\n };\r\n\r\n messageDatasource.refreshDayText();\r\n\r\n $rootScope.$broadcast('LoadDisclaimer', chatRoom);\r\n\r\n if (chatRoom.s_clearKey != 'bb85d94a' && chatRoom.s_clearKey != '1f1a7376') {\r\n IntroTutorialService.setup()\r\n IntroTutorialService.runIfNotViewed()\r\n };\r\n\r\n } else {\r\n $rootScope.$broadcast('LoadPayment', {\r\n chatroom: chatRoom,\r\n config: data\r\n });\r\n }\r\n }\r\n\r\n messageDatasource.clear();\r\n daysDatasource.clear();\r\n $scope.messagelist = messageDatasource.getMessages();\r\n $scope.newAlert = false;\r\n $scope.autoScroll = true;\r\n $scope.status = {\r\n loading: false,\r\n loaded: false\r\n };\r\n $scope.loadMore = function () {\r\n\r\n var deferred = $q.defer();\r\n if (!$scope.status.loading) {\r\n $scope.status.loading = true;\r\n var l_objLocalRoom = chatRoomService.getCurrentRoom();\r\n\r\n messageService.getRoomMessages(l_objLocalRoom.s_key, messageDatasource.getLastMessageTime()).then(function (data) {\r\n if (data != null && data.data != null) {\r\n for (var i = 0; i < data.data.length; i++) {\r\n if (data.data[i] != null) {\r\n var l_objMessage = null;\r\n //var l_objUser = userService.getUserByName(data.data[i].s_sender);\r\n var l_objUser = userService.getUserByClearKey(data.data[i].s_userkey);\r\n if (l_objUser != null) {\r\n try {\r\n l_objMessage = {\r\n sender: data.data[i].s_sender,\r\n senderKey: l_objUser.s_key,\r\n message: data.data[i].s_message,\r\n date: data.data[i].d_created,\r\n time: moment.utc(data.data[i].d_created).valueOf(),\r\n s_avatar: l_objUser.s_avatar,\r\n s_typeAvatar: l_objUser.s_typeAvatar,\r\n s_path: '//cdn.echofin.co/uploads/' + l_objUser.s_key.substring(10) + '/',\r\n s_fileName: data.data[i].s_fileName,\r\n s_fileToken: data.data[i].s_fileToken,\r\n s_extension: data.data[i].s_extension,\r\n n_fileType: data.data[i].n_fileType,\r\n s_fileDescr: data.data[i].s_fileDescr,\r\n s_fileLink: data.data[i].s_fileLink,\r\n b_isUploaded: true,\r\n b_isDelivered: true\r\n };\r\n messageDatasource.addToMessageList(l_objMessage, 0);\r\n } catch (e) {\r\n AppError.Send(e, {\r\n location: 'loadMore',\r\n message: l_objMessage,\r\n sender: l_objUser,\r\n chatRoomKey: l_objLocalRoom.s_key,\r\n user: userService.getCurrentUser()\r\n });\r\n }\r\n }\r\n }\r\n };\r\n messageDatasource.refreshDayText();\r\n }\r\n $scope.status.loading = false;\r\n $scope.status.loaded = true;\r\n deferred.resolve();\r\n });\r\n } else {\r\n deferred.reject();\r\n };\r\n return deferred.promise;\r\n };\r\n $scope.gotoBottom = function () {\r\n $('#dvCenter').scrollTop($('#dvCenter')[0].scrollHeight);\r\n $scope.newAlert = false;\r\n };\r\n $scope.MatchingNext = function (a_objNext, a_objMessage) {\r\n if (a_objNext == null)\r\n return false;\r\n\r\n if (a_objNext.senderKey == a_objMessage.senderKey &&\r\n moment.utc(a_objNext.date).diff(moment.utc(a_objMessage.date), 'seconds') <= 300)\r\n return true;\r\n\r\n return false;\r\n };\r\n $scope.NewState = function (a_objCurrent, a_objPrevious) {\r\n\r\n var l_objCurrentUser = userService.getCurrentUser();\r\n if (a_objPrevious == null || a_objPrevious == 'undefined')\r\n return false;\r\n if (a_objCurrent == null || a_objCurrent == 'undefined')\r\n return false;\r\n try {\r\n if (a_objCurrent.senderKey.indexOf(l_objCurrentUser.s_key) > -1) {\r\n return false;\r\n };\r\n } catch (e) {\r\n\r\n }\r\n if (!a_objPrevious.b_isUnread && a_objCurrent.b_isUnread) {\r\n return true;\r\n }\r\n\r\n return false;\r\n };\r\n\r\n $scope.$on('CurrentUserUpdate', function (event, data) {\r\n if (data.action == 'update') {\r\n for (var i = 0; i < $scope.messagelist.length; i++) {\r\n $scope.messagelist[i].s_avatar = $scope.messagelist[i].s_avatar + '?' + (new Date()).getTime().toString();\r\n }\r\n }\r\n });\r\n $scope.$on('MoveToBottom', function (event, data) {\r\n $scope.newAlert = false;\r\n $scope.$apply();\r\n });\r\n $scope.$on('FocusChange', function (event, data) {\r\n if (data) {\r\n $('.new-message-separator').delay(2000).hide(3000)\r\n messageDatasource.markAllRead();\r\n }\r\n });\r\n $scope.$on('UserAvatarChange', function (event, data) {\r\n var l_objUser = userService.getUserByClearKey(data.user);\r\n\r\n if (l_objUser != null) {\r\n l_objUser.s_avatar = data.avatar\r\n messageDatasource.changeUserAvatar('private-u-' + data.user, data.avatar);\r\n $scope.messagelist = messageDatasource.getMessages();\r\n $scope.$apply();\r\n\r\n }\r\n });\r\n $scope.$on('FailedMessage', function (event, data) {\r\n for (var i = 0; i < $scope.messagelist.length; i++) {\r\n if (!$scope.messagelist[i].b_isDelivered && $scope.messagelist[i].messageKey == data.messageKey) {\r\n messageDatasource.deleteMessage(i);\r\n }\r\n }\r\n });\r\n $scope.$on('IncomingMessage', function (event, data) {\r\n //var l_objUser = userService.getUserByName(data.Sender);\r\n var l_objUser = userService.getUserByKey(data.SenderKey);\r\n var l_objCurrentUser = userService.getCurrentUser();\r\n var l_bIsMentioned = false;\r\n\r\n if (l_objUser == null)\r\n return;\r\n\r\n for (var i = 0; i < $scope.messagelist.length; i++) {\r\n if (!$scope.messagelist[i].b_isDelivered && $scope.messagelist[i].messageKey == data.messageKey) {\r\n messageDatasource.deleteMessage(i);\r\n }\r\n }\r\n\r\n if (userService.isMuted(l_objUser.s_clearkey, data.RoomKey.substring(4))) {\r\n return;\r\n }\r\n\r\n try {\r\n for (var i = 0; i < data.Mentions.length; i++) {\r\n if ('private-u-' + data.Mentions[i] == l_objCurrentUser.s_key)\r\n userService.addMention({\r\n date: data.Submitted,\r\n fromUser: l_objUser.s_key.substring(10),\r\n messageId: null,\r\n toUser: data.Mentions[i]\r\n });\r\n\r\n if (data.Mentions[i] == l_objCurrentUser.s_key.substring(10)) {\r\n l_bIsMentioned = true;\r\n }\r\n\r\n };\r\n\r\n if (data.Mentions.length && data.Mentions[0] == \"everyone\") {\r\n l_bIsMentioned = true;\r\n }\r\n\r\n if (data.Extension != null && data.Filename != null) {\r\n if (data.RoomKey.startsWith('private-u')) {\r\n userService.addFile({\r\n d_inserted: moment.utc(data.Submitted).format(),\r\n s_extension: data.Extension,\r\n s_fileName: data.Filename,\r\n s_fromUser: data.SenderKey.substring(10),\r\n s_roomKey: null,\r\n s_toUser: data.ReceiverKey.substring(10),\r\n s_token: data.Media\r\n })\r\n } else {\r\n userService.addFile({\r\n d_inserted: moment.utc(data.Submitted).format(),\r\n s_extension: data.Extension,\r\n s_fileName: data.Filename,\r\n s_fromUser: l_objUser.s_key.substring(10),\r\n s_roomKey: data.RoomKey,\r\n s_toUser: null,\r\n s_token: data.Media\r\n })\r\n\r\n }\r\n }\r\n\r\n if (chatRoom.s_key == data.RoomKey) {\r\n var l_objMessage = {\r\n sender: data.Sender,\r\n senderKey: l_objUser.s_key,\r\n message: data.Text,\r\n date: data.Submitted,\r\n time: moment.utc(data.Submitted).valueOf(),\r\n s_avatar: l_objUser.s_avatar,\r\n s_typeAvatar: l_objUser.s_typeAvatar,\r\n s_path: '//cdn.echofin.co/uploads/' + l_objUser.s_key.substring(10) + '/',\r\n s_fileName: data.Filename,\r\n s_fileToken: data.Media,\r\n s_extension: data.Extension,\r\n n_fileType: data.n_fileType,\r\n s_fileDescr: data.s_fileDescr,\r\n s_fileLink: data.s_fileLink,\r\n b_isUploaded: (data.n_fileType == 2),\r\n messageKey: data.messageKey,\r\n b_isDelivered: true\r\n };\r\n\r\n var clearOld = ($scope.autoScroll) ? 50 : false;\r\n\r\n messageDatasource.addToMessageList(l_objMessage, 1, clearOld);\r\n\r\n messageDatasource.refreshDayText();\r\n\r\n if (l_objUser.s_key == l_objCurrentUser.s_key) {\r\n //throw scope apply to update the ui for edit/delete\r\n window.setTimeout(function () {\r\n $scope.$apply();\r\n }, 65000);\r\n }\r\n if (data.Media != null && messageDatasource.dequeueFileUpload(data.Media)) //in case file upload have already done\r\n {\r\n messageDatasource.fileUploadDone(data.Media);\r\n }\r\n\r\n if (l_objCurrentUser.s_key != l_objUser.s_key &&\r\n !($('#dvCenter').scrollTop() + $('#dvCenter').innerHeight() >= $('#dvCenter')[0].scrollHeight)) {\r\n $scope.newAlert = true;\r\n $scope.$apply();\r\n } else {\r\n $scope.$apply();\r\n $scope.gotoBottom();\r\n }\r\n\r\n } else {\r\n $rootScope.$broadcast('NewMessageNotFocused', data);\r\n\r\n }\r\n if (l_objUser.s_key != l_objCurrentUser.s_key) {\r\n var l_strChatName = '';\r\n if (chatRoom != null)\r\n l_strChatName = ' ' + chatRoom.s_url;\r\n\r\n var l_intType = null;\r\n if (l_bIsMentioned) { //mentioned notify\r\n l_intType = 2\r\n } else if (data.RoomKey.substring(0, 10) == 'private-u-') { //direct message\r\n l_intType = 3;\r\n } else { //all rooms\r\n l_intType = 1;\r\n }\r\n\r\n var _userRoom = chatRoomService.findRoomByKey(data.RoomKey);\r\n var _roomKey = null;\r\n if (_userRoom) {\r\n l_strChatName = _userRoom.s_url;\r\n _roomKey = _userRoom.s_clearKey\r\n } else {\r\n l_strChatName = \"\"\r\n }\r\n NotificationsService.notify(l_strChatName + \" \" + l_objUser.userName + ' says:', data.Text, data.Filename, l_objUser.s_avatar, 3000, l_intType, _roomKey);\r\n }\r\n\r\n } catch (e) {\r\n AppError.Send(e, {\r\n location: 'IncomingMessage',\r\n event: event,\r\n data: data,\r\n sender: l_objUser,\r\n chatRoom: chatRoom,\r\n user: l_objCurrentUser\r\n });\r\n }\r\n });\r\n $scope.$on('UploadDone', function (event, data) {\r\n var l_blnFileUploadDone = messageDatasource.fileUploadDone(data.s_token);\r\n if (l_blnFileUploadDone) {\r\n $scope.$apply();\r\n $scope.gotoBottom();\r\n };\r\n\r\n });\r\n $scope.$on('EditMessage', function (event, data) {\r\n //var l_objUser = userService.getUserByName(data.Sender);\r\n var l_objUser = userService.getUserByKey(data.SenderKey);\r\n var l_objCurrentUser = userService.getCurrentUser();\r\n if (chatRoom.s_key == data.RoomKey) {\r\n editMessageCallback(data.Created, data.Text, data.Edited);\r\n $scope.$apply();\r\n }\r\n })\r\n $scope.$on('DeleteMessage', function (event, data) {\r\n var l_objUser = userService.getUserByName(data.Sender);\r\n var l_objCurrentUser = userService.getCurrentUser();\r\n if (chatRoom.s_key == data.RoomKey) {\r\n deleteMessageCallback(data.Deleted);\r\n messageDatasource.refreshDayText();\r\n }\r\n })\r\n $scope.$on('IsTypingChanged', function (ev, typingText) {\r\n //console.log(\"IsTypingChanged\", typingText)\r\n $scope.typingMessage = typingText;\r\n $scope.$apply();\r\n });\r\n\r\n var _hideChatDiv = function () {\r\n $('.chatDiv').css('display', 'none');\r\n $(\".center-container\").css('bottom', '0');\r\n }\r\n\r\n var _showChatDiv = function () {\r\n $('.chatDiv').css('display', 'block');\r\n $(\".center-container\").css('bottom', '90px');\r\n }\r\n\r\n $(\"#dvCenter\").scroll(function () {\r\n $scope.autoScroll = ($('#dvCenter')[0].scrollHeight - $('#dvCenter')[0].scrollTop - $('#dvCenter').height() == 0);\r\n });\r\n\r\n angular.forEach(brokersService.brokers, function (room, key) {\r\n room.isVisible = false\r\n })\r\n\r\n if (chatRoom == null) {\r\n _showChatDiv();\r\n //initial load with no room selected,\r\n //we have to wait for initial data to load so we can redirect user to the first chatroom\r\n $scope.$on('initial', function (event, data) {\r\n chatRoom = chatRoomService.getCurrentRoom();\r\n $rootScope.$broadcast('ChangeRoom', chatRoom);\r\n });\r\n //$rootScope.$broadcast('initial', null);\r\n } else if (chatRoom.roomType == 3) {\r\n _hideChatDiv();\r\n\r\n messageService\r\n .getRoomMessages(chatRoom.s_key, '')\r\n .then(function (data) {\r\n\r\n if (data.success && data.auth) {\r\n $('#roomKey').val(chatRoom.s_key);\r\n //$rootScope.$broadcast('recalc', null);\r\n if (userService.getAll() != null) {\r\n $rootScope.$broadcast('ChangeRoom', chatRoom);\r\n $(\"#dvCenter\").html(\"
    \")\r\n chatRoom.serviceURL = '/redirect/index/' + chatRoom.s_clearKey;\r\n\r\n }\r\n } else {\r\n $rootScope.$broadcast('LoadPayment', {\r\n chatroom: chatRoom,\r\n config: data\r\n });\r\n }\r\n });\r\n\r\n } else if (chatRoom.roomType == 4) {\r\n // this is a broker\r\n _hideChatDiv();\r\n\r\n var _broker = _.find(brokersService.brokers, function (o) {\r\n return o.s_key == chatRoom.s_key;\r\n });\r\n\r\n chatRoom.isVisible = true\r\n chatRoom.serviceURL = $sce.trustAsResourceUrl(_broker._source)\r\n //chatRoom.s_url = \"$\" + _broker.s_title\r\n\r\n $rootScope.$broadcast('ChangeRoom', _broker);\r\n chatRoom.isVisible = true\r\n //$rootScope.$broadcast('ChangeMessageCount', []);\r\n\r\n } else { // page change (direct or chatroom)\r\n _showChatDiv();\r\n\r\n if (chatRoom.roomType == 2) { //direct chat\r\n $rootScope.$broadcast('StartDirectChat', chatRoom);\r\n };\r\n messageService.getRoomMessages(chatRoom.s_key, '').then(_handleInitialLoad);\r\n $('#roomKey').val(chatRoom.s_key);\r\n //$rootScope.$broadcast('recalc', null);\r\n $rootScope.$broadcast('ChangeRoom', chatRoom);\r\n }\r\n\r\n }\r\n ]);\r\n\r\n(function () {\r\n \"use strict\";\r\n angular\r\n .module(\"chat\")\r\n .directive(\"errSrc\", errSrc);\r\n\r\n function errSrc() {\r\n return {\r\n link: function (scope, element, attrs) {\r\n if (!attrs.ngSrc) {\r\n attrs.$set(\"src\", attrs.errSrc);\r\n }\r\n\r\n element.bind(\"error\",\r\n function () {\r\n if (attrs.errSrc === \"REMOVE\") {\r\n element.remove();\r\n return;\r\n }\r\n if (attrs.src !== attrs.errSrc) {\r\n attrs.$set(\"src\", attrs.errSrc);\r\n }\r\n });\r\n }\r\n };\r\n }\r\n}())"]}