const darkreader = require("darkreader"); Ext.define("Rambox.view.main.MainController", { extend: "Ext.app.ViewController", alias: "controller.main", initialize: function (tabPanel) { const config = ipc.sendSync("getConfig"); if (config.darkreader) { darkreader.enable(); } else { darkreader.disable(); } tabPanel.setTabPosition(config.tabbar_location); tabPanel.setTabRotation(0); var reorderer = tabPanel.plugins.find(function (plugin) { return plugin.ptype == "tabreorderer"; }); if (reorderer !== undefined) { const names = reorderer.container.getLayout().names; reorderer.dd.dim = names.width; reorderer.dd.startAttr = names.beforeX; reorderer.dd.endAttr = names.afterX; } }, // Make focus on webview every time the user change tabs, to enable the autofocus in websites onTabChange: function (tabPanel, newTab, oldTab) { var me = this; // Set Google Analytics event ga_storage._trackPageview("/index.html", "main"); localStorage.setItem("last_active_service", newTab.id); if (newTab.id === "ramboxTab") { if (Rambox.app.getTotalNotifications() > 0) { document.title = "Rambox (" + Rambox.app.getTotalNotifications() + ")"; } else { document.title = "Rambox"; } return; } if (!newTab.record.get("enabled")) { return; } var webview = newTab.down("component").el.dom; setTimeout(function () { if (webview) { tabPanel.getActiveTab().getWebView().blur(); tabPanel.getActiveTab().getWebView().focus(); } }, 300); // Update the main window so it includes the active tab title. if (Rambox.app.getTotalNotifications() > 0) { document.title = "Rambox (" + Rambox.app.getTotalNotifications() + ") - " + newTab.record.get("name"); } else { document.title = "Rambox - " + newTab.record.get("name"); } }, updatePositions: function (tabPanel, tab) { if (tab.id === "ramboxTab" || tab.id === "tbfill") return true; console.log("Updating Tabs positions..."); var store = Ext.getStore("Services"); var align = "left"; store.suspendEvent("remove"); Ext.each(tabPanel.items.items, function (t, i) { if ( t.id !== "ramboxTab" && t.id !== "tbfill" && t.record.get("enabled") ) { var rec = store.getById(t.record.get("id")); if (align === "right") i--; rec.set("align", align); rec.set("position", i); rec.save(); } else if (t.id === "tbfill") { align = "right"; } }); store.load(); store.resumeEvent("remove"); }, showServiceTab: function (grid, record, tr, rowIndex, e) { if (e.position.colIdx === 0) { // Service Logo Ext.getCmp("tab_" + record.get("id")).show(); } }, onRenameService: function (editor, e) { var me = this; e.record.commit(); // Change the title of the Tab Ext.getCmp("tab_" + e.record.get("id")).setTitle(e.record.get("name")); }, onEnableDisableService: function (cc, rowIndex, checked, obj, hideTab) { var rec = Ext.getStore("Services").getAt(rowIndex); if (!checked) { Ext.getCmp("tab_" + rec.get("id")).destroy(); } else { Ext.cq1("app-main").insert( rec.get("align") === "left" ? rec.get("position") : rec.get("position") + 1, { xtype: "webview", id: "tab_" + rec.get("id"), title: rec.get("name"), icon: rec.get("type") !== "custom" ? "resources/icons/" + rec.get("logo") : rec.get("logo") === "" ? "resources/icons/custom.png" : rec.get("logo"), src: rec.get("url"), type: rec.get("type"), muted: rec.get("muted"), includeInGlobalUnreadCounter: rec.get("includeInGlobalUnreadCounter"), displayTabUnreadCounter: rec.get("displayTabUnreadCounter"), enabled: rec.get("enabled"), record: rec, useragent: ipc.sendSync("getConfig").user_agent, hidden: hideTab, tabConfig: { service: rec, }, } ); } }, onNewServiceSelect: function (view, record, item, index, e) { Ext.create("Rambox.view.add.Add", { record: record, }); }, removeServiceFn: function (serviceId, total, actual, callback) { var me = this; if (!serviceId) return false; // Get Record var rec = Ext.getStore("Services").getById(serviceId); if (!rec.get("enabled")) { rec.set("enabled", true); me.onEnableDisableService( null, Ext.getStore("Services").indexOf(rec), true, null, true ); // Get Tab var tab = Ext.getCmp("tab_" + serviceId); // Clear all trash data const webview = tab.getWebView(); webview.addEventListener("did-start-loading", function () { clearData(webview, tab); }); } else { // Get Tab var tab = Ext.getCmp("tab_" + serviceId); // Clear all trash data const webview = tab.getWebView(); clearData(webview, tab); } const config = ipc.sendSync("getConfig"); if (config.default_service === rec.get("id")) ipc.send( "setConfig", Ext.apply(config, { default_service: "ramboxTab" }) ); function clearData(webview, tab) { const currentWebView = require("electron").remote.webContents.fromId( webview.getWebContentsId() ); currentWebView.clearHistory(); currentWebView.session.flushStorageData(); currentWebView.session .clearCache() .then(() => { currentWebView.session .clearStorageData() .then(() => { currentWebView.session.cookies .flushStore() .then(() => { // Remove record from localStorage Ext.getStore("Services").remove(rec); // Close tab tab.close(); // Close waiting message if (total === actual) { Ext.Msg.hide(); if (Ext.isFunction(callback)) callback(); } }) .catch((err) => { console.log(err); }); }) .catch((err) => { console.log(err); }); }) .catch((err) => { console.log(err); }); } }, removeService: function (gridView, rowIndex, colIndex, col, e, rec, rowEl) { var me = this; Ext.Msg.confirm( locale["app.window[12]"], locale["app.window[13]"] + " " + rec.get("name") + "?", function (btnId) { if (btnId === "yes") { Ext.Msg.wait("Please wait until we clear all.", "Removing..."); me.removeServiceFn(rec.get("id"), 1, 1); } } ); }, removeAllServices: function (btn, callback) { var me = this; if (btn) { Ext.Msg.confirm( locale["app.window[12]"], locale["app.window[14]"], function (btnId) { if (btnId === "yes") { // Clear counter for unread messaging document.title = "Rambox"; Ext.cq1("app-main").suspendEvent("remove"); Ext.getStore("Services").load(); Ext.Msg.wait("Please wait until we clear all.", "Removing..."); const count = Ext.getStore("Services").getCount(); var i = 1; Ext.Array.each( Ext.getStore("Services").collect("id"), function (serviceId) { me.removeServiceFn(serviceId, count, i++, callback || false); } ); if (count === 0 && Ext.isFunction(callback)) callback(); Ext.cq1("app-main").resumeEvent("remove"); } } ); } else { Ext.cq1("app-main").suspendEvent("remove"); Ext.getStore("Services").load(); const count = Ext.getStore("Services").getCount(); var i = 1; Ext.Array.each( Ext.getStore("Services").collect("id"), function (serviceId) { me.removeServiceFn(serviceId, count, i++, callback || false); } ); if (count === 0 && Ext.isFunction(callback)) callback(); Ext.cq1("app-main").resumeEvent("remove"); } }, configureService: function ( gridView, rowIndex, colIndex, col, e, rec, rowEl ) { Ext.create("Rambox.view.add.Add", { record: rec, service: Ext.getStore("ServicesList").getById(rec.get("type")), edit: true, }); }, onSearchRender: function (field) { field.focus(false, 1000); }, onSearchEnter: function (field, e) { var me = this; if ( e.getKey() == e.ENTER && Ext.getStore("ServicesList").getCount() === 2 ) { // Two because we always shows Custom Service option me.onNewServiceSelect( field.up().down("dataview"), Ext.getStore("ServicesList").getAt(0) ); me.onClearClick(field); } }, doTypeFilter: function (cg, newValue, oldValue) { var me = this; Ext.getStore("ServicesList") .getFilters() .replaceAll({ fn: function (record) { return ( Ext.Array.contains( Ext.Object.getKeys(cg.getValue()), record.get("type") ) || record.get("type") === "custom" ); }, }); }, onSearchServiceChange: function (field, newValue, oldValue) { var me = this; var cg = field.up().down("checkboxgroup"); if (!Ext.isEmpty(newValue) && newValue.length > 0) { field.getTrigger("clear").show(); Ext.getStore("ServicesList") .getFilters() .replaceAll({ fn: function (record) { if (record.get("type") === "custom") return true; if ( !Ext.Array.contains( Ext.Object.getKeys(cg.getValue()), record.get("type") ) ) return false; return record .get("name") .toLowerCase() .indexOf(newValue.toLowerCase()) > -1 ? true : false; }, }); } else { field.getTrigger("clear").hide(); Ext.getStore("ServicesList").getFilters().removeAll(); me.doTypeFilter(cg); } field.updateLayout(); }, onClearClick: function (field, trigger, e) { var me = this; var cg = field.up().down("checkboxgroup"); field.reset(); field.getTrigger("clear").hide(); field.updateLayout(); Ext.getStore("ServicesList").getFilters().removeAll(); me.doTypeFilter(cg); }, dontDisturb: function (btn, e, called) { console.info("Dont Disturb:", btn.pressed ? "Enabled" : "Disabled"); // Google Analytics Event if (!called) ga_storage._trackEvent( "Usability", "dontDisturb", btn.pressed ? "on" : "off" ); Ext.Array.each( Ext.getStore("Services").collect("id"), function (serviceId) { // Get Tab var tab = Ext.getCmp("tab_" + serviceId); if (!tab) return; // Skip disabled services // Mute sounds tab.setAudioMuted(btn.pressed ? true : tab.record.get("muted"), true); // Prevent Notifications tab.setNotifications( btn.pressed ? false : tab.record.get("notifications"), true ); } ); localStorage.setItem("dontDisturb", btn.pressed); ipc.send("setDontDisturb", btn.pressed); btn.setText( locale["app.main[16]"] + ": " + (btn.pressed ? locale["app.window[20]"] : locale["app.window[21]"]) ); // var btn_icon = document.getElementById('disturbBtn-btnIconEl'); // btn_icon.innerHTML = btn.pressed ? "" : ""; btn.pressed ? btn.setGlyph("xf1f7@FontAwesome") : btn.setGlyph("xf0f3@FontAwesome"); Ext.getCmp("mainTabBar").getEl().toggleCls("dontdisturb"); // If this method is called from Lock method, prevent showing toast if (!e) return; Ext.toast({ html: btn.pressed ? "ENABLED" : "DISABLED", title: "Don't Disturb", width: 200, align: "t", closable: false, }); }, lockRambox: function (btn) { var me = this; if (ipc.sendSync("getConfig").master_password) { Ext.Msg.confirm( locale["app.main[19]"], "Do you want to use the Master Password as your temporal password?", function (btnId) { if (btnId === "yes") { setLock(ipc.sendSync("getConfig").master_password); } else { showTempPass(); } } ); } else { showTempPass(); } function showTempPass() { var msgbox = Ext.Msg.prompt( locale["app.main[19]"], locale["app.window[22]"], function (btnId, text) { if (btnId === "ok") { var msgbox2 = Ext.Msg.prompt( locale["app.main[19]"], locale["app.window[23]"], function (btnId, text2) { if (btnId === "ok") { if (text !== text2) { Ext.Msg.show({ title: locale["app.window[24]"], message: locale["app.window[25]"], icon: Ext.Msg.WARNING, buttons: Ext.Msg.OK, fn: me.lockRambox, }); return false; } setLock(Rambox.util.MD5.encypt(text)); } } ); msgbox2.textField.inputEl.dom.type = "password"; } } ); msgbox.textField.inputEl.dom.type = "password"; } function setLock(text) { var ramboxTab = Ext.cq1("#ramboxTab"); // Related to issue #2065. Focusing in an sub frame is a workaround if (ramboxTab.getWebView) { ramboxTab.down("component").el.dom.executeJavaScript(` var iframeFix = document.createElement('iframe'); document.body.appendChild(iframeFix); iframeFix.focus(); document.body.removeChild(iframeFix); `); } console.info("Lock Rambox:", "Enabled"); // Save encrypted password in localStorage to show locked when app is reopen localStorage.setItem("locked", text); // Google Analytics Event ga_storage._trackEvent("Usability", "locked"); me.lookupReference("disturbBtn").setPressed(true); me.dontDisturb(me.lookupReference("disturbBtn"), false, true); me.showLockWindow(); } }, showLockWindow: function () { var me = this; var validateFn = function () { if ( localStorage.getItem("locked") === Rambox.util.MD5.encypt(winLock.down("textfield").getValue()) ) { console.info("Lock Rambox:", "Disabled"); localStorage.removeItem("locked"); winLock.close(); me.lookupReference("disturbBtn").setPressed(false); me.dontDisturb(me.lookupReference("disturbBtn"), false); } else { winLock.down("textfield").reset(); winLock.down("textfield").markInvalid("Unlock password is invalid"); } }; var winLock = Ext.create("Ext.window.Window", { maximized: true, closable: false, resizable: false, minimizable: false, maximizable: false, draggable: false, onEsc: Ext.emptyFn, layout: "center", bodyStyle: "background-color:#2e658e;", items: [ { xtype: "container", layout: "vbox", items: [ { xtype: "image", src: "resources/Icon.png", width: 256, height: 256, }, { xtype: "component", autoEl: { tag: "h1", html: locale["app.window[26]"], style: "text-align:center;width:256px;", }, }, { xtype: "textfield", inputType: "password", width: 256, listeners: { specialkey: function (field, e) { if (e.getKey() == e.ENTER) { validateFn(); } }, }, }, { xtype: "button", text: locale["app.window[27]"], glyph: "xf13e@FontAwesome", width: 256, scale: "large", handler: validateFn, }, ], }, ], listeners: { render: function (win) { win.getEl().on("click", function () { win.down("textfield").focus(100); }); }, }, }).show(); winLock.down("textfield").focus(1000); }, openPreferences: function (btn) { var me = this; Ext.create("Rambox.view.preferences.Preferences").show(); }, login: function (btn) { var me = this; Rambox.ux.Auth0.login(); }, logout: function (btn) { var me = this; var logoutFn = function (callback) { Ext.Msg.wait(locale["app.window[37]"], locale["app.main[21]"]); // Google Analytics Event ga_storage._trackEvent("Users", "loggedOut"); // Logout from Auth0 Rambox.ux.Auth0.logout(); Ext.cq1("app-main").getViewModel().set("username", ""); Ext.cq1("app-main").getViewModel().set("avatar", ""); if (Ext.isFunction(callback)) { callback(false, function () { Ext.Msg.hide(); }); } else { Ext.Msg.hide(); } }; if (btn) { Ext.Msg.confirm( locale["app.main[21]"], locale["app.window[38]"], function (btnId) { if (btnId === "yes") { logoutFn(me.removeAllServices.bind(me)); } } ); } else { logoutFn(); } }, showDonate: function (btn) { Signalayer.API.show("tChaoq3PwSG9wswhn"); }, });