From 92a4ee074514d37862782c8e2b72ff2fba56ec7f Mon Sep 17 00:00:00 2001
From: "prettifier[bot]" <45367598+prettifier[bot]@users.noreply.github.com>
Date: Sun, 14 Nov 2021 04:28:34 +0000
Subject: [PATCH] Format abea666
---
app/Application.js | 730 ++++++-----
app/store/ServicesList.js | 75 +-
app/ux/Auth0.js | 640 +++++-----
app/ux/WebView.js | 1777 +++++++++++++++------------
app/view/main/MainController.js | 1209 ++++++++++--------
app/view/preferences/Preferences.js | 778 ++++++------
electron/main.js | 64 +-
package.json | 478 +++----
resources/js/darkreader.js | 22 +-
resources/js/rambox-service-api.js | 9 +-
resources/languages/en.js | 253 +++-
11 files changed, 3388 insertions(+), 2647 deletions(-)
diff --git a/app/Application.js b/app/Application.js
index dbe77934..fddd9859 100644
--- a/app/Application.js
+++ b/app/Application.js
@@ -1,334 +1,444 @@
-Ext.define('Rambox.Application', {
- extend: 'Ext.app.Application'
+Ext.define("Rambox.Application", {
+ extend: "Ext.app.Application",
- ,name: 'Rambox'
+ name: "Rambox",
- ,requires: [
- 'Rambox.ux.Auth0'
- ,'Rambox.util.MD5'
- ,'Ext.window.Toast'
- ,'Ext.util.Cookies'
- ]
+ requires: [
+ "Rambox.ux.Auth0",
+ "Rambox.util.MD5",
+ "Ext.window.Toast",
+ "Ext.util.Cookies",
+ ],
- ,stores: [
- 'ServicesList'
- ,'Services'
- ]
+ stores: ["ServicesList", "Services"],
- ,profiles: [
- 'Offline'
- ,'Online'
- ]
+ profiles: ["Offline", "Online"],
- ,config: {
- totalServicesLoaded: 0
- ,totalNotifications: 0
- ,googleURLs: []
- }
+ config: {
+ totalServicesLoaded: 0,
+ totalNotifications: 0,
+ googleURLs: [],
+ },
- ,launch: function () {
+ launch: function () {
+ const isOnline = require("is-online");
+ const Mousetrap = require("mousetrap");
+ (async () => {
+ await isOnline().then((res) => {
+ var hideNoConnection = ipc.sendSync("getConfig").hideNoConnectionDialog;
+ if (!res && !hideNoConnection) {
+ Ext.get("spinner") ? Ext.get("spinner").destroy() : null;
+ Ext.get("background") ? Ext.get("background").destroy() : null;
+ Ext.Msg.show({
+ title: "No Internet Connection",
+ msg:
+ "Please, check your internet connection. If you use a Proxy, please go to Preferences to configure it. Rambox will try to re-connect in 10 seconds",
+ width: 300,
+ closable: false,
+ buttons: Ext.Msg.YESNO,
+ buttonText: {
+ yes: "Ok",
+ no: "Never show this again",
+ },
+ multiline: false,
+ fn: function (buttonValue, inputText, showConfig) {
+ if (buttonValue === "no") {
+ ipc.send("sConfig", { hideNoConnectionDialog: true });
+ hideNoConnection = true;
+ }
+ },
+ icon: Ext.Msg.QUESTION,
+ });
+ setTimeout(function () {
+ if (!hideNoConnection) ipc.send("reloadApp");
+ }, 10000);
+ }
+ });
+ })();
- const isOnline = require('is-online');
- const Mousetrap = require('mousetrap');
- (async () => {
- await isOnline().then(res => {
- var hideNoConnection = ipc.sendSync('getConfig').hideNoConnectionDialog
- if ( !res && !hideNoConnection ) {
- Ext.get('spinner') ? Ext.get('spinner').destroy() : null;
- Ext.get('background') ? Ext.get('background').destroy() : null;
- Ext.Msg.show({
- title: 'No Internet Connection'
- ,msg: 'Please, check your internet connection. If you use a Proxy, please go to Preferences to configure it. Rambox will try to re-connect in 10 seconds'
- ,width: 300
- ,closable: false
- ,buttons: Ext.Msg.YESNO
- ,buttonText: {
- yes: 'Ok'
- ,no: 'Never show this again'
- }
- ,multiline: false
- ,fn: function(buttonValue, inputText, showConfig) {
- if ( buttonValue === 'no' ) {
- ipc.send('sConfig', { hideNoConnectionDialog: true });
- hideNoConnection = true;
- }
- }
- ,icon: Ext.Msg.QUESTION
- });
- setTimeout(function() {
- if ( !hideNoConnection ) ipc.send('reloadApp')
- }, 10000)
- }
- })
- })();
+ if (
+ !localStorage.getItem("hideMacPermissions") &&
+ process.platform === "darwin" &&
+ (require("electron").remote.systemPreferences.getMediaAccessStatus(
+ "microphone"
+ ) !== "granted" ||
+ require("electron").remote.systemPreferences.getMediaAccessStatus(
+ "camera"
+ ) !== "granted")
+ ) {
+ console.info("Checking mac permissions...");
+ Ext.cq1("app-main").addDocked({
+ xtype: "toolbar",
+ dock: "top",
+ style: { background: "#30BBF3" },
+ items: [
+ "->",
+ {
+ xtype: "label",
+ html:
+ "Rambox CE needs permissions to use Microphone and Camera for the apps.",
+ },
+ {
+ xtype: "button",
+ text: "Grant permissions",
+ ui: "decline",
+ handler: async function (btn) {
+ await require("electron").remote.systemPreferences.askForMediaAccess(
+ "microphone"
+ );
+ await require("electron").remote.systemPreferences.askForMediaAccess(
+ "camera"
+ );
+ Ext.cq1("app-main").removeDocked(btn.up("toolbar"), true);
+ },
+ },
+ {
+ xtype: "button",
+ text: "Never ask again",
+ ui: "decline",
+ handler: function (btn) {
+ Ext.cq1("app-main").removeDocked(btn.up("toolbar"), true);
+ localStorage.setItem("hideMacPermissions", true);
+ },
+ },
+ "->",
+ {
+ glyph: "xf00d@FontAwesome",
+ baseCls: "",
+ style: "cursor:pointer;",
+ handler: function (btn) {
+ Ext.cq1("app-main").removeDocked(btn.up("toolbar"), true);
+ },
+ },
+ ],
+ });
+ }
- if ( !localStorage.getItem('hideMacPermissions') && process.platform === 'darwin' && (require('electron').remote.systemPreferences.getMediaAccessStatus('microphone') !== 'granted' || require('electron').remote.systemPreferences.getMediaAccessStatus('camera') !== 'granted') ) {
- console.info('Checking mac permissions...');
- Ext.cq1('app-main').addDocked({
- xtype: 'toolbar'
- ,dock: 'top'
- ,style: {background: '#30BBF3'}
- ,items: [
- '->'
- ,{
- xtype: 'label'
- ,html: 'Rambox CE needs permissions to use Microphone and Camera for the apps.'
- }
- ,{
- xtype: 'button'
- ,text: 'Grant permissions'
- ,ui: 'decline'
- ,handler: async function(btn) {
- await require('electron').remote.systemPreferences.askForMediaAccess('microphone');
- await require('electron').remote.systemPreferences.askForMediaAccess('camera');
- Ext.cq1('app-main').removeDocked(btn.up('toolbar'), true);
- }
- }
- ,{
- xtype: 'button'
- ,text: 'Never ask again'
- ,ui: 'decline'
- ,handler: function(btn) {
- Ext.cq1('app-main').removeDocked(btn.up('toolbar'), true);
- localStorage.setItem('hideMacPermissions', true);
- }
- }
- ,'->'
- ,{
- glyph: 'xf00d@FontAwesome'
- ,baseCls: ''
- ,style: 'cursor:pointer;'
- ,handler: function(btn) { Ext.cq1('app-main').removeDocked(btn.up('toolbar'), true); }
- }
- ]
- });
- }
+ Ext.getStore("ServicesList").load(function (records, operations, success) {
+ if (!success) {
+ Ext.cq1("app-main").addDocked({
+ xtype: "toolbar",
+ dock: "top",
+ ui: "servicesnotloaded",
+ style: { background: "#efef6d" },
+ items: [
+ "->",
+ {
+ xtype: "label",
+ html:
+ "Services couldn't be loaded, some Rambox features will not be available.",
+ },
+ {
+ xtype: "button",
+ text: "Reload",
+ handler: function () {
+ ipc.send("reloadApp");
+ },
+ },
+ "->",
+ {
+ glyph: "xf00d@FontAwesome",
+ baseCls: "",
+ style: "cursor:pointer;",
+ handler: function (btn) {
+ Ext.cq1("app-main").removeDocked(btn.up("toolbar"), true);
+ },
+ },
+ ],
+ });
+ }
+ // Prevent track if the user have disabled this option (default: false)
+ if (!ipc.sendSync("sendStatistics")) {
+ ga_storage = {
+ _enableSSL: Ext.emptyFn,
+ _disableSSL: Ext.emptyFn,
+ _setAccount: Ext.emptyFn,
+ _setDomain: Ext.emptyFn,
+ _setLocale: Ext.emptyFn,
+ _setCustomVar: Ext.emptyFn,
+ _deleteCustomVar: Ext.emptyFn,
+ _trackPageview: Ext.emptyFn,
+ _trackEvent: Ext.emptyFn,
+ };
+ }
+ // Set Google Analytics events
+ ga_storage._setAccount("UA-80680424-1");
+ ga_storage._trackPageview("/index.html", "main");
+ ga_storage._trackEvent(
+ "Versions",
+ require("electron").remote.app.getVersion()
+ );
- Ext.getStore('ServicesList').load(function (records, operations, success) {
+ // Load language for Ext JS library
+ Ext.Loader.loadScript({
+ url: Ext.util.Format.format(
+ "ext/packages/ext-locale/build/ext-locale-{0}.js",
+ localStorage.getItem("locale-auth0") || "en"
+ ),
+ });
- if (!success) {
- Ext.cq1('app-main').addDocked({
- xtype: 'toolbar'
- ,dock: 'top'
- ,ui: 'servicesnotloaded'
- ,style: { background: '#efef6d' }
- ,items: [
- '->'
- ,{
- xtype: 'label'
- ,html: 'Services couldn\'t be loaded, some Rambox features will not be available.'
- }
- ,{
- xtype: 'button'
- ,text: 'Reload'
- ,handler: function() { ipc.send('reloadApp'); }
- }
- ,'->'
- ,{
- glyph: 'xf00d@FontAwesome'
- ,baseCls: ''
- ,style: 'cursor:pointer;'
- ,handler: function(btn) { Ext.cq1('app-main').removeDocked(btn.up('toolbar'), true); }
- }
- ]
- });
- }
- // Prevent track if the user have disabled this option (default: false)
- if ( !ipc.sendSync('sendStatistics') ) {
- ga_storage = {
- _enableSSL: Ext.emptyFn
- ,_disableSSL: Ext.emptyFn
- ,_setAccount: Ext.emptyFn
- ,_setDomain: Ext.emptyFn
- ,_setLocale: Ext.emptyFn
- ,_setCustomVar: Ext.emptyFn
- ,_deleteCustomVar: Ext.emptyFn
- ,_trackPageview: Ext.emptyFn
- ,_trackEvent: Ext.emptyFn
- }
- }
+ // Initialize Auth0
+ if (auth0Cfg.clientID !== "" && auth0Cfg.domain !== "")
+ Rambox.ux.Auth0.init();
- // Set Google Analytics events
- ga_storage._setAccount('UA-80680424-1');
- ga_storage._trackPageview('/index.html', 'main');
- ga_storage._trackEvent('Versions', require('electron').remote.app.getVersion());
+ // Set cookies to help Tooltip.io messages segmentation
+ Ext.util.Cookies.set(
+ "version",
+ require("electron").remote.app.getVersion()
+ );
+ if (Ext.util.Cookies.get("auth0") === null)
+ Ext.util.Cookies.set("auth0", false);
- // Load language for Ext JS library
- Ext.Loader.loadScript({url: Ext.util.Format.format("ext/packages/ext-locale/build/ext-locale-{0}.js", localStorage.getItem('locale-auth0') || 'en')});
+ // Check for updates
+ if (
+ require("electron").remote.process.argv.indexOf("--without-update") ===
+ -1
+ )
+ Rambox.app.checkUpdate(true);
- // Initialize Auth0
- if ( auth0Cfg.clientID !== '' && auth0Cfg.domain !== '' ) Rambox.ux.Auth0.init();
+ // Get Google URLs
+ Ext.Ajax.request({
+ url:
+ "https://raw.githubusercontent.com/ramboxapp/community-edition/gh-pages/api/google.json",
+ method: "GET",
+ success: function (response) {
+ Rambox.app.config.googleURLs = Ext.decode(response.responseText);
+ },
+ });
- // Set cookies to help Tooltip.io messages segmentation
- Ext.util.Cookies.set('version', require('electron').remote.app.getVersion());
- if ( Ext.util.Cookies.get('auth0') === null ) Ext.util.Cookies.set('auth0', false);
+ // Shortcuts
+ const platform = require("electron").remote.process.platform;
+ // Prevents default behaviour of Mousetrap, that prevents shortcuts in textareas
+ Mousetrap.prototype.stopCallback = function (e, element, combo) {
+ return false;
+ };
+ // Add shortcuts to switch services using CTRL + Number
+ Mousetrap.bind(
+ platform === "darwin"
+ ? [
+ "command+1",
+ "command+2",
+ "command+3",
+ "command+4",
+ "command+5",
+ "command+6",
+ "command+7",
+ "command+8",
+ "command+9",
+ ]
+ : [
+ "ctrl+1",
+ "ctrl+2",
+ "ctrl+3",
+ "ctrl+4",
+ "ctrl+5",
+ "ctrl+6",
+ "ctrl+7",
+ "ctrl+8",
+ "ctrl+9",
+ ],
+ function (e, combo) {
+ // GROUPS
+ var tabPanel = Ext.cq1("app-main");
+ var arg = parseInt(e.key);
+ if (arg >= tabPanel.items.indexOf(Ext.getCmp("tbfill"))) arg++;
+ tabPanel.setActiveTab(arg);
+ }
+ );
+ // Add shortcut to main tab (ctrl+,)
+ Mousetrap.bind(
+ platform === "darwin" ? "command+," : "ctrl+,",
+ (e, combo) => {
+ Ext.cq1("app-main").setActiveTab(0);
+ }
+ );
+ // Add shortcuts to navigate through services
+ Mousetrap.bind(["ctrl+tab", "ctrl+pagedown"], (e, combo) => {
+ var tabPanel = Ext.cq1("app-main");
+ var activeIndex = tabPanel.items.indexOf(tabPanel.getActiveTab());
+ var i = activeIndex + 1;
+ // "cycle" (go to the start) when the end is reached or the end is the spacer "tbfill"
+ if (
+ i === tabPanel.items.items.length ||
+ (i === tabPanel.items.items.length - 1 &&
+ tabPanel.items.items[i].id === "tbfill")
+ )
+ i = 0;
+ // skip spacer
+ while (tabPanel.items.items[i].id === "tbfill") i++;
+ tabPanel.setActiveTab(i);
+ });
+ Mousetrap.bind(["ctrl+shift+tab", "ctrl+pageup"], (e, combo) => {
+ var tabPanel = Ext.cq1("app-main");
+ var activeIndex = tabPanel.items.indexOf(tabPanel.getActiveTab());
+ var i = activeIndex - 1;
+ if (i < 0) i = tabPanel.items.items.length - 1;
+ while (tabPanel.items.items[i].id === "tbfill" || i < 0) i--;
+ tabPanel.setActiveTab(i);
+ });
+ // Add shortcut to search inside a service
+ Mousetrap.bind(
+ process.platform === "darwin" ? ["command+alt+f"] : ["shift+alt+f"],
+ (e, combo) => {
+ var currentTab = Ext.cq1("app-main").getActiveTab();
+ if (currentTab.getWebView) currentTab.showSearchBox(true);
+ }
+ );
+ // Add shortcut to Do Not Disturb
+ Mousetrap.bind(
+ platform === "darwin" ? ["command+alt+d"] : ["shift+alt+d"],
+ function (e, combo) {
+ var btn = Ext.getCmp("disturbBtn");
+ btn.toggle();
+ Ext.cq1("app-main").getController().dontDisturb(btn, true);
+ }
+ );
+ // Add shortcut to Lock Rambox
+ Mousetrap.bind(
+ platform === "darwin" ? ["command+alt+l"] : ["shift+alt+l"],
+ (e, combo) => {
+ var btn = Ext.getCmp("lockRamboxBtn");
+ Ext.cq1("app-main").getController().lockRambox(btn);
+ }
+ );
- // Check for updates
- if ( require('electron').remote.process.argv.indexOf('--without-update') === -1 ) Rambox.app.checkUpdate(true);
+ // Mouse Wheel zooming
+ document.addEventListener("mousewheel", function (e) {
+ if (e.ctrlKey) {
+ var delta = Math.max(-1, Math.min(1, e.wheelDelta || -e.detail));
- // Get Google URLs
- Ext.Ajax.request({
- url: 'https://raw.githubusercontent.com/ramboxapp/community-edition/gh-pages/api/google.json'
- ,method: 'GET'
- ,success: function(response) {
- Rambox.app.config.googleURLs = Ext.decode(response.responseText);
- }
- });
+ var tabPanel = Ext.cq1("app-main");
+ if (tabPanel.items.indexOf(tabPanel.getActiveTab()) === 0)
+ return false;
- // Shortcuts
- const platform = require('electron').remote.process.platform;
- // Prevents default behaviour of Mousetrap, that prevents shortcuts in textareas
- Mousetrap.prototype.stopCallback = function(e, element, combo) {
- return false;
- };
- // Add shortcuts to switch services using CTRL + Number
- Mousetrap.bind(platform === 'darwin' ? ["command+1","command+2","command+3","command+4","command+5","command+6","command+7","command+8","command+9"] : ["ctrl+1","ctrl+2","ctrl+3","ctrl+4","ctrl+5","ctrl+6","ctrl+7","ctrl+8","ctrl+9"], function(e, combo) { // GROUPS
- var tabPanel = Ext.cq1('app-main');
- var arg = parseInt(e.key);
- if ( arg >= tabPanel.items.indexOf(Ext.getCmp('tbfill')) ) arg++;
- tabPanel.setActiveTab(arg);
- });
- // Add shortcut to main tab (ctrl+,)
- Mousetrap.bind(platform === 'darwin' ? 'command+,' : 'ctrl+,', (e, combo) => {
- Ext.cq1('app-main').setActiveTab(0);
- });
- // Add shortcuts to navigate through services
- Mousetrap.bind(['ctrl+tab', 'ctrl+pagedown'], (e, combo) => {
- var tabPanel = Ext.cq1('app-main');
- var activeIndex = tabPanel.items.indexOf(tabPanel.getActiveTab());
- var i = activeIndex + 1;
- // "cycle" (go to the start) when the end is reached or the end is the spacer "tbfill"
- if (i === tabPanel.items.items.length || i === tabPanel.items.items.length - 1 && tabPanel.items.items[i].id === 'tbfill') i = 0;
- // skip spacer
- while (tabPanel.items.items[i].id === 'tbfill') i++;
- tabPanel.setActiveTab(i);
- });
- Mousetrap.bind(['ctrl+shift+tab', 'ctrl+pageup'], (e, combo) => {
- var tabPanel = Ext.cq1('app-main');
- var activeIndex = tabPanel.items.indexOf(tabPanel.getActiveTab());
- var i = activeIndex - 1;
- if ( i < 0 ) i = tabPanel.items.items.length - 1;
- while ( tabPanel.items.items[i].id === 'tbfill' || i < 0 ) i--;
- tabPanel.setActiveTab(i);
- });
- // Add shortcut to search inside a service
- Mousetrap.bind(process.platform === 'darwin' ? ['command+alt+f'] : ['shift+alt+f'], (e, combo) => {
- var currentTab = Ext.cq1('app-main').getActiveTab();
- if ( currentTab.getWebView ) currentTab.showSearchBox(true);
- });
- // Add shortcut to Do Not Disturb
- Mousetrap.bind(platform === 'darwin' ? ["command+alt+d"] : ["shift+alt+d"], function(e, combo) {
- var btn = Ext.getCmp('disturbBtn');
- btn.toggle();
- Ext.cq1('app-main').getController().dontDisturb(btn, true);
- });
- // Add shortcut to Lock Rambox
- Mousetrap.bind(platform === 'darwin' ? ['command+alt+l'] : ['shift+alt+l'], (e, combo) => {
- var btn = Ext.getCmp('lockRamboxBtn');
- Ext.cq1('app-main').getController().lockRambox(btn);
- });
+ if (delta === 1) {
+ // Zoom In
+ tabPanel.getActiveTab().zoomIn();
+ } else {
+ // Zoom Out
+ tabPanel.getActiveTab().zoomOut();
+ }
+ }
+ });
- // Mouse Wheel zooming
- document.addEventListener('mousewheel', function(e) {
- if( e.ctrlKey ) {
- var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
+ // Define default value
+ if (localStorage.getItem("dontDisturb") === null)
+ localStorage.setItem("dontDisturb", false);
+ ipc.send("setDontDisturb", localStorage.getItem("dontDisturb")); // We store it in config
- var tabPanel = Ext.cq1('app-main');
- if ( tabPanel.items.indexOf(tabPanel.getActiveTab()) === 0 ) return false;
+ if (localStorage.getItem("locked")) {
+ console.info("Lock Rambox:", "Enabled");
+ Ext.cq1("app-main").getController().showLockWindow();
+ }
+ Ext.getStore("Services").load();
+ });
+ },
- if ( delta === 1 ) { // Zoom In
- tabPanel.getActiveTab().zoomIn();
- } else { // Zoom Out
- tabPanel.getActiveTab().zoomOut();
- }
- }
- });
+ updateTotalNotifications: function (newValue, oldValue) {
+ newValue = parseInt(newValue);
+ if (newValue > 0) {
+ if (Ext.cq1("app-main").getActiveTab().record) {
+ document.title =
+ "Rambox (" +
+ Rambox.util.Format.formatNumber(newValue) +
+ ") - " +
+ Ext.cq1("app-main").getActiveTab().record.get("name");
+ } else {
+ document.title =
+ "Rambox (" + Rambox.util.Format.formatNumber(newValue) + ")";
+ }
+ } else {
+ if (Ext.cq1("app-main") && Ext.cq1("app-main").getActiveTab().record) {
+ document.title =
+ "Rambox - " + Ext.cq1("app-main").getActiveTab().record.get("name");
+ } else {
+ document.title = "Rambox";
+ }
+ }
+ },
- // Define default value
- if ( localStorage.getItem('dontDisturb') === null ) localStorage.setItem('dontDisturb', false);
- ipc.send('setDontDisturb', localStorage.getItem('dontDisturb')); // We store it in config
+ checkUpdate: function (silence) {
+ console.info("Checking for updates...");
+ Ext.Ajax.request({
+ url:
+ "https://api.github.com/repos/ramboxapp/community-edition/releases/latest",
+ method: "GET",
+ success: function (response) {
+ var json = Ext.decode(response.responseText);
+ var appVersion = new Ext.Version(
+ require("electron").remote.app.getVersion()
+ );
+ if (
+ appVersion.isLessThan(json.name) &&
+ !json.draft &&
+ !json.prerelease
+ ) {
+ console.info("New version is available", json.version);
+ Ext.cq1("app-main").addDocked({
+ xtype: "toolbar",
+ dock: "top",
+ ui: "newversion",
+ items: [
+ "->",
+ {
+ xtype: "label",
+ html:
+ "" +
+ locale["app.update[0]"] +
+ " (" +
+ json.version +
+ ")" +
+ (process.platform === "win32"
+ ? " is downloading in the background and you will be notified when it is ready to be installed."
+ : ""),
+ },
+ {
+ xtype: "button",
+ text: locale["app.update[1]"],
+ href:
+ process.platform === "darwin"
+ ? "https://getrambox.herokuapp.com/download/" +
+ process.platform +
+ "_" +
+ process.arch
+ : "https://github.com/ramboxapp/community-edition/releases/latest",
+ hidden: process.platform === "win32",
+ },
+ {
+ xtype: "button",
+ text: locale["app.update[2]"],
+ ui: "decline",
+ tooltip:
+ "Click here to see more information about the new version.",
+ href:
+ "https://github.com/ramboxapp/community-edition/releases/tag/" +
+ json.version,
+ },
+ "->",
+ {
+ glyph: "xf00d@FontAwesome",
+ baseCls: "",
+ style: "cursor:pointer;",
+ handler: function (btn) {
+ Ext.cq1("app-main").removeDocked(btn.up("toolbar"), true);
+ },
+ },
+ ],
+ });
+ ipc.send("autoUpdater:check-for-updates");
+ return;
+ } else if (!silence) {
+ Ext.Msg.show({
+ title: locale["app.update[3]"],
+ message: locale["app.update[4]"],
+ icon: Ext.Msg.INFO,
+ buttons: Ext.Msg.OK,
+ });
+ }
- if ( localStorage.getItem('locked') ) {
- console.info('Lock Rambox:', 'Enabled');
- Ext.cq1('app-main').getController().showLockWindow();
- }
- Ext.getStore('Services').load();
- });
- }
-
- ,updateTotalNotifications: function( newValue, oldValue ) {
- newValue = parseInt(newValue);
- if ( newValue > 0 ) {
- if ( Ext.cq1('app-main').getActiveTab().record ) {
- document.title = 'Rambox (' + Rambox.util.Format.formatNumber(newValue) + ') - '+Ext.cq1('app-main').getActiveTab().record.get('name');
- } else {
- document.title = 'Rambox (' + Rambox.util.Format.formatNumber(newValue) + ')';
- }
- } else {
- if ( Ext.cq1('app-main') && Ext.cq1('app-main').getActiveTab().record ) {
- document.title = 'Rambox - '+Ext.cq1('app-main').getActiveTab().record.get('name');
- } else {
- document.title = 'Rambox';
- }
- }
- }
-
- ,checkUpdate: function(silence) {
- console.info('Checking for updates...');
- Ext.Ajax.request({
- url: 'https://api.github.com/repos/ramboxapp/community-edition/releases/latest'
- ,method: 'GET'
- ,success: function(response) {
- var json = Ext.decode(response.responseText);
- var appVersion = new Ext.Version(require('electron').remote.app.getVersion());
- if ( appVersion.isLessThan(json.name) && !json.draft && !json.prerelease ) {
- console.info('New version is available', json.version);
- Ext.cq1('app-main').addDocked({
- xtype: 'toolbar'
- ,dock: 'top'
- ,ui: 'newversion'
- ,items: [
- '->'
- ,{
- xtype: 'label'
- ,html: ''+locale['app.update[0]']+' ('+json.version+')' + ( process.platform === 'win32' ? ' is downloading in the background and you will be notified when it is ready to be installed.' : '' )
- }
- ,{
- xtype: 'button'
- ,text: locale['app.update[1]']
- ,href: process.platform === 'darwin' ? 'https://getrambox.herokuapp.com/download/'+process.platform+'_'+process.arch : 'https://github.com/ramboxapp/community-edition/releases/latest'
- ,hidden: process.platform === 'win32'
- }
- ,{
- xtype: 'button'
- ,text: locale['app.update[2]']
- ,ui: 'decline'
- ,tooltip: 'Click here to see more information about the new version.'
- ,href: 'https://github.com/ramboxapp/community-edition/releases/tag/'+json.version
- }
- ,'->'
- ,{
- glyph: 'xf00d@FontAwesome'
- ,baseCls: ''
- ,style: 'cursor:pointer;'
- ,handler: function(btn) { Ext.cq1('app-main').removeDocked(btn.up('toolbar'), true); }
- }
- ]
- });
- ipc.send('autoUpdater:check-for-updates');
- return;
- } else if ( !silence ) {
- Ext.Msg.show({
- title: locale['app.update[3]']
- ,message: locale['app.update[4]']
- ,icon: Ext.Msg.INFO
- ,buttons: Ext.Msg.OK
- });
- }
-
- console.info('Your version is the latest. No need to update.');
- }
- });
- }
+ console.info("Your version is the latest. No need to update.");
+ },
+ });
+ },
});
diff --git a/app/store/ServicesList.js b/app/store/ServicesList.js
index a2172525..07ea29a7 100644
--- a/app/store/ServicesList.js
+++ b/app/store/ServicesList.js
@@ -1,42 +1,43 @@
-Ext.define('Rambox.store.ServicesList', {
- extend: 'Ext.data.Store'
- ,alias: 'store.serviceslist'
+Ext.define("Rambox.store.ServicesList", {
+ extend: "Ext.data.Store",
+ alias: "store.serviceslist",
- ,requires: [
- 'Ext.data.proxy.LocalStorage'
- ]
+ requires: ["Ext.data.proxy.LocalStorage"],
- ,model: 'Rambox.model.ServiceList'
+ model: "Rambox.model.ServiceList",
- ,proxy: {
- type: 'ajax',
- url: 'https://raw.githubusercontent.com/ramboxapp/community-edition/gh-pages/api/services.json',
- reader: {
- type: 'json',
- rootProperty: 'responseText'
- }
- }
- ,listeners: {
- load: function () {
- Ext.get('spinner') ? Ext.get('spinner').destroy() : null;
- Ext.get('background') ? Ext.get('background').destroy() : null;
- this.add({
- id: 'custom'
- ,logo: 'custom.png'
- ,name: '_Custom Service'
- ,description: locale['services[38]']
- ,url: '___'
- ,type: 'custom'
- ,allow_popups: true
- })
- }
- }
- ,sorters: [{
- property: 'name'
- ,direction: 'ASC'
- }]
+ proxy: {
+ type: "ajax",
+ url:
+ "https://raw.githubusercontent.com/ramboxapp/community-edition/gh-pages/api/services.json",
+ reader: {
+ type: "json",
+ rootProperty: "responseText",
+ },
+ },
+ listeners: {
+ load: function () {
+ Ext.get("spinner") ? Ext.get("spinner").destroy() : null;
+ Ext.get("background") ? Ext.get("background").destroy() : null;
+ this.add({
+ id: "custom",
+ logo: "custom.png",
+ name: "_Custom Service",
+ description: locale["services[38]"],
+ url: "___",
+ type: "custom",
+ allow_popups: true,
+ });
+ },
+ },
+ sorters: [
+ {
+ property: "name",
+ direction: "ASC",
+ },
+ ],
- ,autoLoad: true
- ,autoSync: true
- ,pageSize: 100000
+ autoLoad: true,
+ autoSync: true,
+ pageSize: 100000,
});
diff --git a/app/ux/Auth0.js b/app/ux/Auth0.js
index 8f3b6afe..6cb41969 100644
--- a/app/ux/Auth0.js
+++ b/app/ux/Auth0.js
@@ -1,298 +1,344 @@
-Ext.define('Rambox.ux.Auth0', {
- singleton: true
-
- // private
- ,lock: null
- ,auth0: null
- ,authService: null
- ,backupCurrent: false
-
- ,init: function() {
- var me = this;
-
- var Auth0 = require('auth0-js');
- var _AuthService = require('./resources/js/AuthService');
-
- me.authService = new _AuthService.default({
- clientId: auth0Cfg.clientID,
- authorizeEndpoint: 'https://'+auth0Cfg.domain+'/authorize',
- audience: 'https://'+auth0Cfg.domain+'/userinfo',
- scope: 'openid profile offline_access',
- redirectUri: 'https://'+auth0Cfg.domain+'/mobile',
- tokenEndpoint: 'https://'+auth0Cfg.domain+'/oauth/token'
- });
-
- me.auth0 = new Auth0.WebAuth({ clientID: auth0Cfg.clientID, domain : auth0Cfg.domain });
-
- //me.defineEvents();
- }
-
- ,onLogin: function(token, authWindow) {
- var me = this;
-
- authWindow.close();
-
- me.auth0.client.userInfo(token.access_token, function(err, profile) {
- if ( err ) {
- if ( err.error === 401 || err.error === 'Unauthorized' ) return me.renewToken(me.checkConfiguration);
- Ext.Msg.hide();
- return Ext.Msg.show({
- title: 'Error'
- ,message: 'There was an error getting the profile: ' + err.error_description
- ,icon: Ext.Msg.ERROR
- ,buttons: Ext.Msg.OK
- });
- }
-
- profile.user_metadata = profile['https://rambox.pro/user_metadata'];
- delete profile['https://rambox.pro/user_metadata'];
-
- // Display a spinner while waiting
- Ext.Msg.wait(locale['app.window[29]'], locale['app.window[28]']);
-
- // Google Analytics Event
- ga_storage._trackEvent('Users', 'loggedIn');
-
- // Set cookies to help Tooltip.io messages segmentation
- Ext.util.Cookies.set('auth0', true);
-
- // User is logged in
- // Save the profile and JWT.
- localStorage.setItem('profile', JSON.stringify(profile));
- localStorage.setItem('access_token', token.access_token);
- localStorage.setItem('id_token', token.id_token);
- localStorage.setItem('refresh_token', token.refresh_token);
-
- if ( !Ext.isEmpty(profile.user_metadata) && !Ext.isEmpty(profile.user_metadata.services) && !me.backupCurrent ) {
- Ext.each(profile.user_metadata.services, function(s) {
- var service = Ext.create('Rambox.model.Service', s);
- service.save();
- Ext.getStore('Services').add(service);
- });
-
- require('electron').remote.app.relaunch();
- require('electron').remote.app.exit();
- }
-
- Ext.Msg.hide();
- Ext.cq1('app-main').getViewModel().set('username', profile.name);
- Ext.cq1('app-main').getViewModel().set('avatar', profile.picture);
- });
- }
-
- ,backupConfiguration: function(callback) {
- var me = this;
-
- Ext.Msg.wait('Saving backup...', 'Please wait...');
-
- // Getting all services
- var lastupdate = (new Date()).toJSON();
- var services = [];
- Ext.getStore('Services').each(function(service) {
- var s = Ext.clone(service);
- delete s.data.id;
- delete s.data.zoomLevel;
- services.push(s.data);
- });
-
- Ext.Ajax.request({
- url: 'https://rambox.auth0.com/api/v2/users/'+Ext.decode(localStorage.getItem('profile')).sub
- ,method: 'PATCH'
- ,headers: { authorization: "Bearer " + localStorage.getItem('id_token') }
- ,jsonData: { user_metadata: { services: services, services_lastupdate: lastupdate } }
- ,success: function(response) {
- Ext.Msg.hide();
- // Save the last update in localStorage
- var profile = Ext.decode(localStorage.getItem('profile'));
- if ( !profile.user_metadata ) profile.user_metadata = {};
- profile.user_metadata.services_lastupdate = lastupdate;
- localStorage.setItem('profile', Ext.encode(profile));
- Ext.cq1('app-main').getViewModel().set('last_sync', new Date(lastupdate).toUTCString());
-
- Ext.toast({
- html: ' Your configuration were successfully backed up.'
- ,title: 'Synchronize Configuration'
- ,width: 300
- ,align: 't'
- ,closable: false
- });
-
- if ( Ext.isFunction(callback) ) callback.bind(me)();
- }
- ,failure: function(response) {
- if ( response.status === 401 ) return me.renewToken(me.backupConfiguration);
-
- Ext.Msg.hide();
- Ext.toast({
- html: ' Error occurred when trying to backup your configuration.'
- ,title: 'Synchronize Configuration'
- ,width: 300
- ,align: 't'
- ,closable: false
- });
-
- if ( Ext.isFunction(callback) ) callback.bind(me)();
-
- console.error(response);
- }
- });
- }
-
- ,restoreConfiguration: function() {
- var me = this;
-
- me.auth0.client.userInfo(localStorage.getItem('access_token'), function(err, profile) {
- if ( err ) {
- if ( err.code === 401 ) return me.renewToken(me.restoreConfiguration);
- return Ext.Msg.show({
- title: 'Error'
- ,message: 'There was an error getting the profile: ' + err.description
- ,icon: Ext.Msg.ERROR
- ,buttons: Ext.Msg.OK
- });
- }
-
- profile.user_metadata = profile['https://rambox.pro/user_metadata'];
- delete profile['https://rambox.pro/user_metadata'];
-
- // First we remove all current services
- Ext.cq1('app-main').getController().removeAllServices(false, function() {
- if ( !profile.user_metadata || !profile.user_metadata.services ) return;
- Ext.each(profile.user_metadata.services, function(s) {
- var service = Ext.create('Rambox.model.Service', s);
- service.save();
- Ext.getStore('Services').add(service);
- });
-
- require('electron').remote.getCurrentWindow().reload();
- });
- });
- }
-
- ,checkConfiguration: function() {
- var me = this;
-
- me.auth0.client.userInfo(localStorage.getItem('access_token'), function(err, profile) {
- if ( err ) {
- if ( err.code === 401 ) return me.renewToken(me.checkConfiguration);
- return Ext.Msg.show({
- title: 'Error'
- ,message: 'There was an error getting the profile: ' + err.description
- ,icon: Ext.Msg.ERROR
- ,buttons: Ext.Msg.OK
- });
- }
-
- profile.user_metadata = profile['https://rambox.pro/user_metadata'];
- delete profile['https://rambox.pro/user_metadata'];
-
- if ( !profile.user_metadata ) {
- Ext.toast({
- html: 'You don\'t have any backup yet.'
- ,title: 'Synchronize Configuration'
- ,width: 300
- ,align: 't'
- ,closable: false
- });
- return;
- }
-
- if ( Math.floor(new Date(profile.user_metadata.services_lastupdate) / 1000) > Math.floor(new Date(Ext.decode(localStorage.getItem('profile')).user_metadata.services_lastupdate) / 1000) ) {
- Ext.toast({
- html: 'Your settings are out of date.'
- ,title: 'Synchronize Configuration'
- ,width: 300
- ,align: 't'
- ,closable: false
- });
- } else {
- Ext.toast({
- html: ' Latest backup is already applied.'
- ,title: 'Synchronize Configuration'
- ,width: 300
- ,align: 't'
- ,closable: false
- });
- }
- });
- }
-
- ,renewToken: function(callback) {
- var me = this;
-
- Ext.Ajax.request({
- url: 'https://rambox.auth0.com/oauth/token'
- ,method: 'POST'
- ,jsonData: {
- grant_type: 'refresh_token'
- ,client_id: auth0Cfg.clientID
- ,client_secret: auth0Cfg.clientSecret
- ,refresh_token: localStorage.getItem('refresh_token')
- ,api_type: 'app'
- }
- ,success: function(response) {
- var json = Ext.decode(response.responseText);
- localStorage.setItem('access_token', json.access_token);
- localStorage.setItem('id_token', json.id_token);
-
- if ( Ext.isFunction(callback) ) callback.bind(me)();
- }
- ,failure: function(response) {
- console.error(response);
- }
- });
- }
-
- ,login: function() {
- var me = this;
-
- var electron = require('electron').remote;
- var authWindow = new electron.BrowserWindow({
- title: 'Rambox - Login'
- ,width: 400
- ,height: 600
- ,maximizable: false
- ,minimizable: false
- ,resizable: true
- ,closable: true
- ,center: true
- ,autoHideMenuBar: true
- ,skipTaskbar: true
- ,fullscreenable: false
- ,parent: require('electron').remote.getCurrentWindow()
- ,webPreferences: {
- partition: 'persist:rambox'
- }
- });
-
- authWindow.on('closed', function() {
- authWindow = null;
- });
-
- authWindow.loadURL(me.authService.requestAuthCode());
-
- authWindow.webContents.on('did-start-loading', function(e) {
- authWindow.webContents.session.webRequest.onBeforeSendHeaders((details, callback) => {
- Rambox.app.config.googleURLs.forEach((loginURL) => {
- if ( details.url.indexOf(loginURL) > -1 ) details.requestHeaders['User-Agent'] = 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:70.0) Gecko/20100101 Firefox/70.0' })
- callback({ cancel: false, requestHeaders: details.requestHeaders });
- });
- });
-
- authWindow.webContents.on('did-navigate', function(e, url) {
- me.authService.requestAccessCode(url, me.onLogin.bind(me), authWindow);
- });
- }
-
- ,logout: function() {
- var me = this;
-
- localStorage.removeItem('profile');
- localStorage.removeItem('id_token');
- localStorage.removeItem('refresh_token');
- localStorage.removeItem('access_token');
-
- // Set cookies to help Tooltip.io messages segmentation
- Ext.util.Cookies.set('auth0', false);
- }
+Ext.define("Rambox.ux.Auth0", {
+ singleton: true,
+
+ // private
+ lock: null,
+ auth0: null,
+ authService: null,
+ backupCurrent: false,
+
+ init: function () {
+ var me = this;
+
+ var Auth0 = require("auth0-js");
+ var _AuthService = require("./resources/js/AuthService");
+
+ me.authService = new _AuthService.default({
+ clientId: auth0Cfg.clientID,
+ authorizeEndpoint: "https://" + auth0Cfg.domain + "/authorize",
+ audience: "https://" + auth0Cfg.domain + "/userinfo",
+ scope: "openid profile offline_access",
+ redirectUri: "https://" + auth0Cfg.domain + "/mobile",
+ tokenEndpoint: "https://" + auth0Cfg.domain + "/oauth/token",
+ });
+
+ me.auth0 = new Auth0.WebAuth({
+ clientID: auth0Cfg.clientID,
+ domain: auth0Cfg.domain,
+ });
+
+ //me.defineEvents();
+ },
+
+ onLogin: function (token, authWindow) {
+ var me = this;
+
+ authWindow.close();
+
+ me.auth0.client.userInfo(token.access_token, function (err, profile) {
+ if (err) {
+ if (err.error === 401 || err.error === "Unauthorized")
+ return me.renewToken(me.checkConfiguration);
+ Ext.Msg.hide();
+ return Ext.Msg.show({
+ title: "Error",
+ message:
+ "There was an error getting the profile: " + err.error_description,
+ icon: Ext.Msg.ERROR,
+ buttons: Ext.Msg.OK,
+ });
+ }
+
+ profile.user_metadata = profile["https://rambox.pro/user_metadata"];
+ delete profile["https://rambox.pro/user_metadata"];
+
+ // Display a spinner while waiting
+ Ext.Msg.wait(locale["app.window[29]"], locale["app.window[28]"]);
+
+ // Google Analytics Event
+ ga_storage._trackEvent("Users", "loggedIn");
+
+ // Set cookies to help Tooltip.io messages segmentation
+ Ext.util.Cookies.set("auth0", true);
+
+ // User is logged in
+ // Save the profile and JWT.
+ localStorage.setItem("profile", JSON.stringify(profile));
+ localStorage.setItem("access_token", token.access_token);
+ localStorage.setItem("id_token", token.id_token);
+ localStorage.setItem("refresh_token", token.refresh_token);
+
+ if (
+ !Ext.isEmpty(profile.user_metadata) &&
+ !Ext.isEmpty(profile.user_metadata.services) &&
+ !me.backupCurrent
+ ) {
+ Ext.each(profile.user_metadata.services, function (s) {
+ var service = Ext.create("Rambox.model.Service", s);
+ service.save();
+ Ext.getStore("Services").add(service);
+ });
+
+ require("electron").remote.app.relaunch();
+ require("electron").remote.app.exit();
+ }
+
+ Ext.Msg.hide();
+ Ext.cq1("app-main").getViewModel().set("username", profile.name);
+ Ext.cq1("app-main").getViewModel().set("avatar", profile.picture);
+ });
+ },
+
+ backupConfiguration: function (callback) {
+ var me = this;
+
+ Ext.Msg.wait("Saving backup...", "Please wait...");
+
+ // Getting all services
+ var lastupdate = new Date().toJSON();
+ var services = [];
+ Ext.getStore("Services").each(function (service) {
+ var s = Ext.clone(service);
+ delete s.data.id;
+ delete s.data.zoomLevel;
+ services.push(s.data);
+ });
+
+ Ext.Ajax.request({
+ url:
+ "https://rambox.auth0.com/api/v2/users/" +
+ Ext.decode(localStorage.getItem("profile")).sub,
+ method: "PATCH",
+ headers: { authorization: "Bearer " + localStorage.getItem("id_token") },
+ jsonData: {
+ user_metadata: { services: services, services_lastupdate: lastupdate },
+ },
+ success: function (response) {
+ Ext.Msg.hide();
+ // Save the last update in localStorage
+ var profile = Ext.decode(localStorage.getItem("profile"));
+ if (!profile.user_metadata) profile.user_metadata = {};
+ profile.user_metadata.services_lastupdate = lastupdate;
+ localStorage.setItem("profile", Ext.encode(profile));
+ Ext.cq1("app-main")
+ .getViewModel()
+ .set("last_sync", new Date(lastupdate).toUTCString());
+
+ Ext.toast({
+ html:
+ ' Your configuration were successfully backed up.',
+ title: "Synchronize Configuration",
+ width: 300,
+ align: "t",
+ closable: false,
+ });
+
+ if (Ext.isFunction(callback)) callback.bind(me)();
+ },
+ failure: function (response) {
+ if (response.status === 401)
+ return me.renewToken(me.backupConfiguration);
+
+ Ext.Msg.hide();
+ Ext.toast({
+ html:
+ ' Error occurred when trying to backup your configuration.',
+ title: "Synchronize Configuration",
+ width: 300,
+ align: "t",
+ closable: false,
+ });
+
+ if (Ext.isFunction(callback)) callback.bind(me)();
+
+ console.error(response);
+ },
+ });
+ },
+
+ restoreConfiguration: function () {
+ var me = this;
+
+ me.auth0.client.userInfo(
+ localStorage.getItem("access_token"),
+ function (err, profile) {
+ if (err) {
+ if (err.code === 401) return me.renewToken(me.restoreConfiguration);
+ return Ext.Msg.show({
+ title: "Error",
+ message:
+ "There was an error getting the profile: " + err.description,
+ icon: Ext.Msg.ERROR,
+ buttons: Ext.Msg.OK,
+ });
+ }
+
+ profile.user_metadata = profile["https://rambox.pro/user_metadata"];
+ delete profile["https://rambox.pro/user_metadata"];
+
+ // First we remove all current services
+ Ext.cq1("app-main")
+ .getController()
+ .removeAllServices(false, function () {
+ if (!profile.user_metadata || !profile.user_metadata.services)
+ return;
+ Ext.each(profile.user_metadata.services, function (s) {
+ var service = Ext.create("Rambox.model.Service", s);
+ service.save();
+ Ext.getStore("Services").add(service);
+ });
+
+ require("electron").remote.getCurrentWindow().reload();
+ });
+ }
+ );
+ },
+
+ checkConfiguration: function () {
+ var me = this;
+
+ me.auth0.client.userInfo(
+ localStorage.getItem("access_token"),
+ function (err, profile) {
+ if (err) {
+ if (err.code === 401) return me.renewToken(me.checkConfiguration);
+ return Ext.Msg.show({
+ title: "Error",
+ message:
+ "There was an error getting the profile: " + err.description,
+ icon: Ext.Msg.ERROR,
+ buttons: Ext.Msg.OK,
+ });
+ }
+
+ profile.user_metadata = profile["https://rambox.pro/user_metadata"];
+ delete profile["https://rambox.pro/user_metadata"];
+
+ if (!profile.user_metadata) {
+ Ext.toast({
+ html: "You don't have any backup yet.",
+ title: "Synchronize Configuration",
+ width: 300,
+ align: "t",
+ closable: false,
+ });
+ return;
+ }
+
+ if (
+ Math.floor(
+ new Date(profile.user_metadata.services_lastupdate) / 1000
+ ) >
+ Math.floor(
+ new Date(
+ Ext.decode(
+ localStorage.getItem("profile")
+ ).user_metadata.services_lastupdate
+ ) / 1000
+ )
+ ) {
+ Ext.toast({
+ html: "Your settings are out of date.",
+ title: "Synchronize Configuration",
+ width: 300,
+ align: "t",
+ closable: false,
+ });
+ } else {
+ Ext.toast({
+ html:
+ ' Latest backup is already applied.',
+ title: "Synchronize Configuration",
+ width: 300,
+ align: "t",
+ closable: false,
+ });
+ }
+ }
+ );
+ },
+
+ renewToken: function (callback) {
+ var me = this;
+
+ Ext.Ajax.request({
+ url: "https://rambox.auth0.com/oauth/token",
+ method: "POST",
+ jsonData: {
+ grant_type: "refresh_token",
+ client_id: auth0Cfg.clientID,
+ client_secret: auth0Cfg.clientSecret,
+ refresh_token: localStorage.getItem("refresh_token"),
+ api_type: "app",
+ },
+ success: function (response) {
+ var json = Ext.decode(response.responseText);
+ localStorage.setItem("access_token", json.access_token);
+ localStorage.setItem("id_token", json.id_token);
+
+ if (Ext.isFunction(callback)) callback.bind(me)();
+ },
+ failure: function (response) {
+ console.error(response);
+ },
+ });
+ },
+
+ login: function () {
+ var me = this;
+
+ var electron = require("electron").remote;
+ var authWindow = new electron.BrowserWindow({
+ title: "Rambox - Login",
+ width: 400,
+ height: 600,
+ maximizable: false,
+ minimizable: false,
+ resizable: true,
+ closable: true,
+ center: true,
+ autoHideMenuBar: true,
+ skipTaskbar: true,
+ fullscreenable: false,
+ parent: require("electron").remote.getCurrentWindow(),
+ webPreferences: {
+ partition: "persist:rambox",
+ },
+ });
+
+ authWindow.on("closed", function () {
+ authWindow = null;
+ });
+
+ authWindow.loadURL(me.authService.requestAuthCode());
+
+ authWindow.webContents.on("did-start-loading", function (e) {
+ authWindow.webContents.session.webRequest.onBeforeSendHeaders(
+ (details, callback) => {
+ Rambox.app.config.googleURLs.forEach((loginURL) => {
+ if (details.url.indexOf(loginURL) > -1)
+ details.requestHeaders["User-Agent"] =
+ "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:70.0) Gecko/20100101 Firefox/70.0";
+ });
+ callback({ cancel: false, requestHeaders: details.requestHeaders });
+ }
+ );
+ });
+
+ authWindow.webContents.on("did-navigate", function (e, url) {
+ me.authService.requestAccessCode(url, me.onLogin.bind(me), authWindow);
+ });
+ },
+
+ logout: function () {
+ var me = this;
+
+ localStorage.removeItem("profile");
+ localStorage.removeItem("id_token");
+ localStorage.removeItem("refresh_token");
+ localStorage.removeItem("access_token");
+
+ // Set cookies to help Tooltip.io messages segmentation
+ Ext.util.Cookies.set("auth0", false);
+ },
});
diff --git a/app/ux/WebView.js b/app/ux/WebView.js
index db92fbe9..44110495 100644
--- a/app/ux/WebView.js
+++ b/app/ux/WebView.js
@@ -2,807 +2,978 @@
* Default config for all webviews created
*/
-Ext.define('Rambox.ux.WebView',{
- extend: 'Ext.panel.Panel'
- ,xtype: 'webview'
-
- ,requires: [
- 'Rambox.util.Format'
- ,'Rambox.util.Notifier'
- ,'Rambox.util.UnreadCounter'
- ,'Rambox.util.IconLoader'
- ]
-
- // private
- ,zoomLevel: 0
- ,currentUnreadCount: 0
-
- // CONFIG
- ,hideMode: 'offsets'
- ,initComponent: function(config) {
- var me = this;
-
- function getLocation(href) {
- var match = href.match(/^(https?\:)\/\/(([^:\/?#]*)(?:\:([0-9]+))?)(\/[^?#]*)(\?[^#]*|)(#.*|)$/);
- return match && {
- protocol: match[1],
- host: match[2],
- hostname: match[3],
- port: match[4],
- pathname: match[5],
- search: match[6],
- hash: match[7]
- }
- }
-
- const prefConfig = ipc.sendSync('getConfig');
- Ext.apply(me, {
- items: me.webViewConstructor()
- ,title: prefConfig.hide_tabbar_labels ? '' : (me.record.get('tabname') ? me.record.get('name') : '')
- ,icon: me.record.get('type') === 'custom' ? (me.record.get('logo') === '' ? 'resources/icons/custom.png' : me.record.get('logo')) : 'https://firebasestorage.googleapis.com/v0/b/rambox-d1326.appspot.com/o/services%2F'+me.record.get('logo')+'?alt=media'
- ,src: me.record.get('url')
- ,type: me.record.get('type')
- ,align: me.record.get('align')
- ,notifications: me.record.get('notifications')
- ,muted: me.record.get('muted')
- ,tabConfig: {
- listeners: {
- afterrender : function( btn ) {
- btn.el.on('contextmenu', function(e) {
- btn.showMenu('contextmenu');
- e.stopEvent();
- });
- }
- ,scope: me
- }
- ,clickEvent: ''
- ,style: !me.record.get('enabled') ? '-webkit-filter: grayscale(1)' : ''
- ,menu: {
- plain: true
- ,items: [
- {
- xtype: 'toolbar'
- ,items: [
- {
- xtype: 'segmentedbutton'
- ,allowToggle: false
- ,flex: 1
- ,items: [
- {
- text: 'Back'
- ,glyph: 'xf053@FontAwesome'
- ,flex: 1
- ,scope: me
- ,handler: me.goBack
- }
- ,{
- text: 'Forward'
- ,glyph: 'xf054@FontAwesome'
- ,iconAlign: 'right'
- ,flex: 1
- ,scope: me
- ,handler: me.goForward
- }
- ]
- }
- ]
- }
- ,'-'
- ,{
- text: 'Zoom In'
- ,glyph: 'xf00e@FontAwesome'
- ,scope: me
- ,handler: me.zoomIn
- }
- ,{
- text: 'Zoom Out'
- ,glyph: 'xf010@FontAwesome'
- ,scope: me
- ,handler: me.zoomOut
- }
- ,{
- text: 'Reset Zoom'
- ,glyph: 'xf002@FontAwesome'
- ,scope: me
- ,handler: me.resetZoom
- }
- ,'-'
- ,{
- text: locale['app.webview[0]']
- ,glyph: 'xf021@FontAwesome'
- ,scope: me
- ,handler: me.reloadService
- }
- ,'-'
- ,{
- text: locale['app.webview[3]']
- ,glyph: 'xf121@FontAwesome'
- ,scope: me
- ,handler: me.toggleDevTools
- }
- ]
- }
- }
- ,tbar: {
- itemId: 'searchBar'
- ,hidden: true
- ,items: ['->', {
- xtype: 'textfield'
- ,emptyText: 'Search...'
- ,listeners: {
- scope: me
- ,change: me.doSearchText
- ,specialkey: function(field, e) {
- if ( e.getKey() === e.ENTER ) return me.doSearchText(field, field.getValue(), null, null, true)
- if ( e.getKey() === e.ESC ) return me.showSearchBox(false)
- }
- }
- }, {
- xtype: 'displayfield'
- }, {
- xtype: 'segmentedbutton'
- ,allowMultiple: false
- ,allowToggle: false
- ,items: [{
- glyph: 'xf053@FontAwesome'
- ,handler: function() {
- var field = this.up('toolbar').down('textfield');
- me.doSearchText(field, field.getValue(), null, null, false)
- }
- }, {
- glyph: 'xf054@FontAwesome'
- ,handler: function() {
- var field = this.up('toolbar').down('textfield');
- me.doSearchText(field, field.getValue(), null, null, true)
- }
- }]
- }, {
- xtype: 'button'
- ,glyph: 'xf00d@FontAwesome'
- ,handler: function() { me.showSearchBox(false) }
- }]
- }
- ,listeners: {
- afterrender: me.onAfterRender
- ,beforedestroy: me.onBeforeDestroy
- }
- });
-
- if ( me.record.get('statusbar') ) {
- Ext.apply(me, {
- bbar: me.statusBarConstructor(false)
- });
- } else {
- me.items.push(me.statusBarConstructor(true));
- }
-
- me.callParent(config);
- }
-
- ,onBeforeDestroy: function() {
- var me = this;
-
- me.setUnreadCount(0);
- }
-
- ,webViewConstructor: function( enabled ) {
- var me = this;
-
- var cfg;
- enabled = enabled || me.record.get('enabled');
-
- if ( !enabled ) {
- cfg = {
- xtype: 'container'
- ,html: '
Service Disabled
'
- ,style: 'text-align:center;'
- ,padding: 100
- };
- } else {
- cfg = [{
- xtype: 'component'
- ,cls: 'webview'
- ,hideMode: 'offsets'
- ,autoRender: true
- ,autoShow: true
- ,autoEl: {
- tag: 'webview'
- ,src: me.record.get('url')
- ,style: 'width:100%;height:100%;visibility:visible;'
- ,partition: 'persist:' + me.record.get('type') + '_' + me.id.replace('tab_', '') + (localStorage.getItem('id_token') ? '_' + Ext.decode(localStorage.getItem('profile')).sub : '')
- ,plugins: 'true'
- ,allowtransparency: 'on'
- ,autosize: 'on'
- ,webpreferences: 'nativeWindowOpen=yes, spellcheck=no, contextIsolation=no'
- ,allowpopups: 'on'
- // ,disablewebsecurity: 'on' // Disabled because some services (Like Google Drive) dont work with this enabled
- ,useragent: me.getUserAgent()
- ,preload: './resources/js/rambox-service-api.js'
- }
- }];
- }
-
- return cfg;
- }
- ,getUserAgent: function() {
- var ua = ipc.sendSync('getConfig').user_agent ? ipc.sendSync('getConfig').user_agent : Ext.getStore('ServicesList').getById(this.record.get('type')) ? Ext.getStore('ServicesList').getById(this.record.get('type')).get('userAgent') : ''
- return ua.length === 0 ? window.clientInformation.userAgent.replace(/Rambox\/([0-9]\.?)+\s/ig,'').replace(/Electron\/([0-9]\.?)+\s/ig,'') : ua;
- }
-
- ,statusBarConstructor: function(floating) {
- var me = this;
-
- return {
- xtype: 'statusbar'
- ,id: me.id+'statusbar'
- ,hidden: !me.record.get('statusbar')
- ,keep: me.record.get('statusbar')
- ,y: floating ? '-18px' : 'auto'
- ,height: 19
- ,dock: 'bottom'
- ,defaultText: ' Ready'
- ,busyIconCls : ''
- ,busyText: ' '+locale['app.webview[4]']
- ,items: [
- {
- xtype: 'tbtext'
- ,itemId: 'url'
- }
- ,{
- xtype: 'button'
- ,glyph: 'xf00d@FontAwesome'
- ,scale: 'small'
- ,ui: 'decline'
- ,padding: 0
- ,scope: me
- ,hidden: floating
- ,handler: me.closeStatusBar
- ,tooltip: {
- text: 'Close statusbar until next time'
- ,mouseOffset: [0,-60]
- }
- }
- ]
- };
- }
-
- ,onAfterRender: function() {
- var me = this;
-
- if ( !me.record.get('enabled') ) return;
-
- var webview = me.getWebView();
- me.errorCodeLog = []
-
- // Google Analytics Event
- ga_storage._trackEvent('Services', 'load', me.type, 1, true);
-
- // Notifications in Webview
- me.setNotifications(localStorage.getItem('locked') || JSON.parse(localStorage.getItem('dontDisturb')) ? false : me.record.get('notifications'));
-
- // Show and hide spinner when is loading
- webview.addEventListener("did-start-loading", function() {
- console.info('Start loading...', me.src);
-
- require('electron').remote.webContents.fromId(webview.getWebContentsId()).session.webRequest.onBeforeSendHeaders((details, callback) => {
- Rambox.app.config.googleURLs.forEach((loginURL) => { if ( details.url.indexOf(loginURL) > -1 ) details.requestHeaders['User-Agent'] = 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:70.0) Gecko/20100101 Firefox/70.0'});
- callback({ cancel: false, requestHeaders: details.requestHeaders });
- });
-
- if ( !me.down('statusbar').closed || !me.down('statusbar').keep ) me.down('statusbar').show();
- me.down('statusbar').showBusy();
- });
- webview.addEventListener("did-stop-loading", function() {
- me.down('statusbar').clearStatus({useDefaults: true});
- if ( !me.down('statusbar').keep ) me.down('statusbar').hide();
- });
-
- webview.addEventListener("did-finish-load", function(e) {
- Rambox.app.setTotalServicesLoaded( Rambox.app.getTotalServicesLoaded() + 1 );
-
- // Apply saved zoom level
- webview.setZoomLevel(me.record.get('zoomLevel'));
-
- // Fix cursor sometimes dissapear
- let currentTab = Ext.cq1('app-main').getActiveTab();
- if ( currentTab.id === me.id ) {
- webview.blur();
- webview.focus();
- }
- // Set special icon for some service (like Slack)
- Rambox.util.IconLoader.loadServiceIconUrl(me, webview);
- });
-
- // On search text
- webview.addEventListener('found-in-page', function(e) {
- me.onSearchText(e.result)
- });
-
- // On search text
- webview.addEventListener('did-fail-load', function(e) {
- console.info('The service fail at loading', me.src, e);
-
- if ( me.record.get('disableAutoReloadOnFail') || !e.isMainFrame ) return
- me.errorCodeLog.push(e.errorCode)
-
- var attempt = me.errorCodeLog.filter(function(code) { return code === e.errorCode });
-
- // Error codes: https://cs.chromium.org/chromium/src/net/base/net_error_list.h
- var msg = []
- msg[-2] = 'NET error: failed.'
- msg[-3] = 'An operation was aborted (due to user action)'
- msg[-7] = 'Connection timeout.'
- msg[-21] = 'Network change.'
- msg[-100] = 'The connection was reset. Check your internet connection.'
- msg[-101] = 'The connection was reset. Check your internet connection.'
- msg[-105] = 'Name not resolved. Check your internet connection.'
- msg[-106] = 'There is no active internet connection.'
- msg[-118] = 'Connection timed out. Check your internet connection.'
- msg[-130] = 'Proxy connection failed. Please, check the proxy configuration.'
- msg[-300] = 'The URL is invalid.'
- msg[-324] = 'Empty response. Check your internet connection.'
-
- switch ( e.errorCode ) {
- case 0:
- break
- case -3: // An operation was aborted (due to user action) I think that gmail an other pages that use iframes stop some of them making this error fired
- if ( attempt.length <= 4 ) return
- setTimeout(() => me.reloadService(me), 200);
- me.errorCodeLog = []
- break;
- case -2:
- case -7:
- case -21:
- case -118:
- case -324:
- case -100:
- case -101:
- case -105:
- attempt.length > 4 ? me.onFailLoad(msg[e.errorCode]) : setTimeout(() => me.reloadService(me), 2000);
- break;
- case -106:
- me.onFailLoad(msg[e.errorCode])
- break;
- case -130:
- // Could not create a connection to the proxy server. An error occurred
- // either in resolving its name, or in connecting a socket to it.
- // Note that this does NOT include failures during the actual "CONNECT" method
- // of an HTTP proxy.
- case -300:
- attempt.length > 4 ? me.onFailLoad(msg[e.errorCode]) : me.reloadService(me);
- break;
- }
- });
-
- // Open links in default browser
- webview.addEventListener('new-window', function(e) {
- e.preventDefault();
- const protocol = require('url').parse(e.url).protocol;
- // Block some Deep links to prevent that open its app (Ex: Slack)
- if ( ['slack:'].includes(protocol) ) return;
- // Allow Deep links
- if ( !['http:', 'https:', 'about:'].includes(protocol) ) return require('electron').shell.openExternal(e.url);
- });
-
- webview.addEventListener('will-navigate', function(e, url) {
- e.preventDefault();
- });
-
- let eventsOnDom = false;
- webview.addEventListener("dom-ready", function(e) {
- // Mute Webview
- if ( me.record.get('muted') || localStorage.getItem('locked') || JSON.parse(localStorage.getItem('dontDisturb')) ) me.setAudioMuted(true, true);
-
- var js_inject = '';
- // Injected code to detect new messages
- if ( me.record ) {
- var js_unread = Ext.getStore('ServicesList').getById(me.record.get('type')) ? Ext.getStore('ServicesList').getById(me.record.get('type')).get('js_unread') : '' ;
- js_unread = js_unread + me.record.get('js_unread');
- if ( js_unread !== '' ) {
- console.groupCollapsed(me.record.get('type').toUpperCase() + ' - JS Injected to Detect New Messages');
- console.info(me.type);
- console.log(js_unread);
- js_inject += js_unread;
- }
- }
-
- // Prevent Title blinking (some services have) and only allow when the title have an unread regex match: "(3) Title"
- if ( Ext.getStore('ServicesList').getById(me.record.get('type')) ? Ext.getStore('ServicesList').getById(me.record.get('type')).get('titleBlink') : false ) {
- var js_preventBlink = 'var originalTitle=document.title;Object.defineProperty(document,"title",{configurable:!0,set:function(a){null===a.match(new RegExp("[(]([0-9•]+)[)][ ](.*)","g"))&&a!==originalTitle||(document.getElementsByTagName("title")[0].innerHTML=a)},get:function(){return document.getElementsByTagName("title")[0].innerHTML}});';
- console.log(js_preventBlink);
- js_inject += js_preventBlink;
- }
-
- console.groupEnd();
-
- // Scroll always to top (bug)
- js_inject += 'document.body.scrollTop=0;';
-
- // Handles Certificate Errors
- require('electron').remote.webContents.fromId(webview.getWebContentsId()).on('certificate-error', function(event, url, error, certificate, callback) {
- if (me.record.get('trust')) {
- event.preventDefault();
- callback(true);
- } else {
- callback(false);
- }
-
- me.down('statusbar').keep = true;
- me.down('statusbar').show();
- me.down('statusbar').setStatus({
- text: ' Certification Warning',
- });
- me.down('statusbar').down('button').show();
- });
- if (!eventsOnDom) {
- require('electron').remote.webContents.fromId(webview.getWebContentsId()).on('before-input-event', (event, input) => {
- if (input.type !== 'keyDown') return;
-
- var modifiers = [];
- if (input.shift) modifiers.push('shift');
- if (input.control) modifiers.push('control');
- if (input.alt) modifiers.push('alt');
- if (input.meta) modifiers.push('meta');
- if (input.isAutoRepeat) modifiers.push('isAutoRepeat');
-
- if (input.key === 'Tab' && !(modifiers && modifiers.length)) return;
-
- // Maps special keys to fire the correct event in Mac OS
- if (require('electron').remote.process.platform === 'darwin') {
- var keys = [];
- keys['ƒ'] = 'f'; // Search
- keys[' '] = 'l'; // Lock
- keys['∂'] = 'd'; // DND
-
- input.key = keys[input.key] ? keys[input.key] : input.key;
- }
-
- if (
- input.key === 'F11' ||
- input.key === 'a' ||
- input.key === 'A' ||
- input.key === 'F12' ||
- input.key === 'q' ||
- (input.key === 'F1' && modifiers.includes('control'))
- )
- return;
-
- require('electron').remote.getCurrentWebContents().sendInputEvent({
- type: input.type,
- keyCode: input.key,
- modifiers: modifiers,
- });
- });
- eventsOnDom = true;
-
- Rambox.app.config.googleURLs.forEach((loginURL) => { if ( webview.getURL().indexOf(loginURL) > -1 ) webview.reload() })
- }
- webview.executeJavaScript(js_inject).then(result => {} ).catch(err => { console.log(err) })
- });
-
- webview.addEventListener('ipc-message', function(event) {
- var channel = event.channel;
- switch (channel) {
- case 'rambox.setUnreadCount':
- handleSetUnreadCount(event);
- break;
- case 'rambox.clearUnreadCount':
- handleClearUnreadCount(event);
- break;
- case 'rambox.showWindowAndActivateTab':
- showWindowAndActivateTab(event);
- break;
- }
- /**
- * Handles 'rambox.clearUnreadCount' messages.
- * Clears the unread count.
- */
- function handleClearUnreadCount() {
- me.tab.setBadgeText('');
- me.currentUnreadCount = 0;
- me.setUnreadCount(0);
- }
-
- /**
- * Handles 'rambox.setUnreadCount' messages.
- * Sets the badge text if the event contains an integer or a '•' (indicating non-zero but unknown number of unreads) as first argument.
- *
- * @param event
- */
- function handleSetUnreadCount(event) {
- if (Array.isArray(event.args) === true && event.args.length > 0) {
- var count = event.args[0];
- if (count === parseInt(count, 10) || "•" === count) {
- if ( count === 999999 ) count = "•";
- me.setUnreadCount(count);
- }
- }
- }
-
- function showWindowAndActivateTab(event) {
- require('electron').remote.getCurrentWindow().show();
- var tabPanel = Ext.cq1('app-main');
- // Temp fix missing cursor after upgrade to electron 3.x +
- tabPanel.setActiveTab(me);
- tabPanel.getActiveTab().getWebView().blur();
- tabPanel.getActiveTab().getWebView().focus();
- }
- });
-
- /**
- * Register page title update event listener only for services that don't specify a js_unread
- */
- if ( Ext.getStore('ServicesList').getById(me.record.get('type')) ? Ext.getStore('ServicesList').getById(me.record.get('type')).get('js_unread') === '' : false && me.record.get('js_unread') === '' ) {
- webview.addEventListener("page-title-updated", function(e) {
- var count = e.title.match(/\(([^)]+)\)/); // Get text between (...)
- count = count ? count[1] : '0';
- count = count === '•' ? count : Ext.isArray(count.match(/\d+/g)) ? count.match(/\d+/g).join("") : count.match(/\d+/g); // Some services have special characters. Example: (•)
- count = count === null ? '0' : count;
-
- me.setUnreadCount(count);
- });
- }
-
- webview.addEventListener('did-navigate', function( e ) {
- if ( e.isMainFrame && me.record.get('type') === 'tweetdeck' ) Ext.defer(function() { webview.loadURL(e.newURL); }, 1000); // Applied a defer because sometimes is not redirecting. TweetDeck 2FA is an example.
- });
-
- webview.addEventListener('update-target-url', function( url ) {
- me.down('statusbar #url').setText(url.url);
- });
- }
-
- ,setUnreadCount: function(newUnreadCount) {
- var me = this;
-
- if ( !isNaN(newUnreadCount) && (function(x) { return (x | 0) === x; })(parseFloat(newUnreadCount)) && me.record.get('includeInGlobalUnreadCounter') === true) {
- Rambox.util.UnreadCounter.setUnreadCountForService(me.record.get('id'), newUnreadCount);
- } else {
- Rambox.util.UnreadCounter.clearUnreadCountForService(me.record.get('id'));
- }
-
- me.setTabBadgeText(Rambox.util.Format.formatNumber(newUnreadCount));
-
- me.doManualNotification(parseInt(newUnreadCount));
- }
-
- ,refreshUnreadCount: function() {
- this.setUnreadCount(this.currentUnreadCount);
- }
-
- /**
- * Dispatch manual notification if
- * • service doesn't have notifications, so Rambox does them
- * • count increased
- * • not in dnd mode
- * • notifications enabled
- *
- * @param {int} count
- */
- ,doManualNotification: function(count) {
- var me = this;
- var manualNotifications = Ext.getStore('ServicesList').getById(me.type) ? Ext.getStore('ServicesList').getById(me.type).get('manual_notifications') : false;
- if ( manualNotifications && me.currentUnreadCount < count && me.record.get('notifications') && !JSON.parse(localStorage.getItem('dontDisturb'))) {
- Rambox.util.Notifier.dispatchNotification(me, count);
- }
-
- me.currentUnreadCount = count;
- }
-
- /**
- * Sets the tab badge text depending on the service config param "displayTabUnreadCounter".
- *
- * @param {string} badgeText
- */
- ,setTabBadgeText: function(badgeText) {
- var me = this;
- if (me.record.get('displayTabUnreadCounter') === true) {
- me.tab.setBadgeText(badgeText);
- } else {
- me.tab.setBadgeText('');
- }
- }
-
- /**
- * Clears the unread counter for this view:
- * • clears the badge text
- * • clears the global unread counter
- */
- ,clearUnreadCounter: function() {
- var me = this;
- me.tab.setBadgeText('');
- Rambox.util.UnreadCounter.clearUnreadCountForService(me.record.get('id'));
- }
-
- ,reloadService: function(btn) {
- var me = this;
- var webview = me.getWebView();
-
- if ( me.record.get('enabled') ) {
- me.clearUnreadCounter();
- webview.loadURL(me.src);
- }
- }
-
- ,onFailLoad: function(v) {
- let me = this
- me.errorCodeLog = []
- setTimeout(() => Ext.getCmp(me.id+'statusbar').setStatus({ text: ' The service failed at loading, Error: '+ v }), 1000);
- }
-
- ,showSearchBox: function(v) {
- var me = this;
- if ( !me.record.get('enabled') ) return;
- var webview = me.getWebView();
-
- webview.stopFindInPage('keepSelection');
- if ( v ) {
- me.down('#searchBar').show();
- setTimeout(() => { me.down('#searchBar textfield').focus() }, 100)
- } else {
- me.down('#searchBar').hide();
- me.down('#searchBar textfield').setValue('');
- }
-
- me.down('#searchBar displayfield').setValue('');
- }
-
- ,doSearchText: function(field, newValue, oldValue, eOpts, forward = true) {
- var me = this;
- var webview = me.getWebView();
-
- if ( newValue === '' ) {
- webview.stopFindInPage('clearSelection');
- me.down('#searchBar displayfield').setValue('');
- return;
- }
-
- webview.findInPage(newValue, {
- forward: forward,
- findNext: false,
- matchCase: false
- })
- }
-
- ,onSearchText: function( result ) {
- var me = this;
-
- me.down('#searchBar displayfield').setValue(result.activeMatchOrdinal+ '/' + result.matches);
- }
-
- ,toggleDevTools: function(btn) {
- var me = this;
- var webview = me.getWebView();
-
- if ( me.record.get('enabled') ) webview.isDevToolsOpened() ? webview.closeDevTools() : webview.openDevTools();
- }
-
- ,setURL: function(url) {
- var me = this;
- var webview = me.getWebView();
-
- me.src = url;
-
- if ( me.record.get('enabled') ) webview.loadURL(url);
- }
-
- ,setAudioMuted: function(muted, calledFromDisturb) {
- var me = this;
- var webview = me.getWebView();
-
- me.muted = muted;
-
- if ( !muted && !calledFromDisturb && JSON.parse(localStorage.getItem('dontDisturb')) ) return;
-
- if ( me.record.get('enabled') ) webview.setAudioMuted(muted);
- }
-
- ,closeStatusBar: function() {
- var me = this;
-
- me.down('statusbar').hide();
- me.down('statusbar').closed = true;
- me.down('statusbar').keep = me.record.get('statusbar');
- }
-
- ,setStatusBar: function(keep) {
- var me = this;
-
- me.removeDocked(me.down('statusbar'), true);
-
- if ( keep ) {
- me.addDocked(me.statusBarConstructor(false));
- } else {
- me.add(me.statusBarConstructor(true));
- }
- me.down('statusbar').keep = keep;
- }
-
- ,setNotifications: function(notification, calledFromDisturb) {
- var me = this;
- var webview = me.getWebView();
-
- me.notifications = notification;
-
- if ( notification && !calledFromDisturb && JSON.parse(localStorage.getItem('dontDisturb')) ) return;
-
- if ( me.record.get('enabled') ) ipc.send('setServiceNotifications', webview.partition, notification);
- }
-
- ,setEnabled: function(enabled) {
- var me = this;
-
- me.clearUnreadCounter();
-
- me.removeAll();
- me.add(me.webViewConstructor(enabled));
- if ( enabled ) {
- me.resumeEvent('afterrender');
- me.show();
- me.tab.setStyle('-webkit-filter', 'grayscale(0)');
- me.onAfterRender();
- } else {
- me.suspendEvent('afterrender');
- me.tab.setStyle('-webkit-filter', 'grayscale(1)');
- }
- }
-
- ,goBack: function() {
- var me = this;
- var webview = me.getWebView();
-
- if ( me.record.get('enabled') ) webview.goBack();
- }
-
- ,goForward: function() {
- var me = this;
- var webview = me.getWebView();
-
- if ( me.record.get('enabled') ) webview.goForward();
- }
-
- ,zoomIn: function() {
- if ( this.timeout ) clearTimeout( this.timeout );
- this.timeout = setTimeout(() => {
- var me = this;
- var webview = me.getWebView();
- me.zoomLevel = me.zoomLevel + 0.25;
- if ( me.record.get('enabled') ) {
- webview.setZoomLevel(me.zoomLevel);
- me.record.set('zoomLevel', me.zoomLevel);
- }
- }, 100);
- }
-
- ,zoomOut: function() {
- if ( this.timeout ) clearTimeout( this.timeout );
- this.timeout = setTimeout(() => {
- var me = this;
- var webview = me.getWebView();
- me.zoomLevel = me.zoomLevel - 0.25;
- if ( me.record.get('enabled') ) {
- webview.setZoomLevel(me.zoomLevel);
- me.record.set('zoomLevel', me.zoomLevel);
- }
- }, 100);
- }
-
- ,resetZoom: function() {
- var me = this;
- var webview = me.getWebView();
-
- me.zoomLevel = 0;
- if ( me.record.get('enabled') ) {
- webview.setZoomLevel(0);
- me.record.set('zoomLevel', me.zoomLevel);
- }
- }
-
- ,getWebView: function() {
- if ( this.record.get('enabled') ) {
- return this.down('component[cls=webview]').el.dom;
- } else {
- return false;
- }
- }
+Ext.define("Rambox.ux.WebView", {
+ extend: "Ext.panel.Panel",
+ xtype: "webview",
+
+ requires: [
+ "Rambox.util.Format",
+ "Rambox.util.Notifier",
+ "Rambox.util.UnreadCounter",
+ "Rambox.util.IconLoader",
+ ],
+
+ // private
+ zoomLevel: 0,
+ currentUnreadCount: 0,
+
+ // CONFIG
+ hideMode: "offsets",
+ initComponent: function (config) {
+ var me = this;
+
+ function getLocation(href) {
+ var match = href.match(
+ /^(https?\:)\/\/(([^:\/?#]*)(?:\:([0-9]+))?)(\/[^?#]*)(\?[^#]*|)(#.*|)$/
+ );
+ return (
+ match && {
+ protocol: match[1],
+ host: match[2],
+ hostname: match[3],
+ port: match[4],
+ pathname: match[5],
+ search: match[6],
+ hash: match[7],
+ }
+ );
+ }
+
+ const prefConfig = ipc.sendSync("getConfig");
+ Ext.apply(me, {
+ items: me.webViewConstructor(),
+ title: prefConfig.hide_tabbar_labels
+ ? ""
+ : me.record.get("tabname")
+ ? me.record.get("name")
+ : "",
+ icon:
+ me.record.get("type") === "custom"
+ ? me.record.get("logo") === ""
+ ? "resources/icons/custom.png"
+ : me.record.get("logo")
+ : "https://firebasestorage.googleapis.com/v0/b/rambox-d1326.appspot.com/o/services%2F" +
+ me.record.get("logo") +
+ "?alt=media",
+ src: me.record.get("url"),
+ type: me.record.get("type"),
+ align: me.record.get("align"),
+ notifications: me.record.get("notifications"),
+ muted: me.record.get("muted"),
+ tabConfig: {
+ listeners: {
+ afterrender: function (btn) {
+ btn.el.on("contextmenu", function (e) {
+ btn.showMenu("contextmenu");
+ e.stopEvent();
+ });
+ },
+ scope: me,
+ },
+ clickEvent: "",
+ style: !me.record.get("enabled") ? "-webkit-filter: grayscale(1)" : "",
+ menu: {
+ plain: true,
+ items: [
+ {
+ xtype: "toolbar",
+ items: [
+ {
+ xtype: "segmentedbutton",
+ allowToggle: false,
+ flex: 1,
+ items: [
+ {
+ text: "Back",
+ glyph: "xf053@FontAwesome",
+ flex: 1,
+ scope: me,
+ handler: me.goBack,
+ },
+ {
+ text: "Forward",
+ glyph: "xf054@FontAwesome",
+ iconAlign: "right",
+ flex: 1,
+ scope: me,
+ handler: me.goForward,
+ },
+ ],
+ },
+ ],
+ },
+ "-",
+ {
+ text: "Zoom In",
+ glyph: "xf00e@FontAwesome",
+ scope: me,
+ handler: me.zoomIn,
+ },
+ {
+ text: "Zoom Out",
+ glyph: "xf010@FontAwesome",
+ scope: me,
+ handler: me.zoomOut,
+ },
+ {
+ text: "Reset Zoom",
+ glyph: "xf002@FontAwesome",
+ scope: me,
+ handler: me.resetZoom,
+ },
+ "-",
+ {
+ text: locale["app.webview[0]"],
+ glyph: "xf021@FontAwesome",
+ scope: me,
+ handler: me.reloadService,
+ },
+ "-",
+ {
+ text: locale["app.webview[3]"],
+ glyph: "xf121@FontAwesome",
+ scope: me,
+ handler: me.toggleDevTools,
+ },
+ ],
+ },
+ },
+ tbar: {
+ itemId: "searchBar",
+ hidden: true,
+ items: [
+ "->",
+ {
+ xtype: "textfield",
+ emptyText: "Search...",
+ listeners: {
+ scope: me,
+ change: me.doSearchText,
+ specialkey: function (field, e) {
+ if (e.getKey() === e.ENTER)
+ return me.doSearchText(
+ field,
+ field.getValue(),
+ null,
+ null,
+ true
+ );
+ if (e.getKey() === e.ESC) return me.showSearchBox(false);
+ },
+ },
+ },
+ {
+ xtype: "displayfield",
+ },
+ {
+ xtype: "segmentedbutton",
+ allowMultiple: false,
+ allowToggle: false,
+ items: [
+ {
+ glyph: "xf053@FontAwesome",
+ handler: function () {
+ var field = this.up("toolbar").down("textfield");
+ me.doSearchText(field, field.getValue(), null, null, false);
+ },
+ },
+ {
+ glyph: "xf054@FontAwesome",
+ handler: function () {
+ var field = this.up("toolbar").down("textfield");
+ me.doSearchText(field, field.getValue(), null, null, true);
+ },
+ },
+ ],
+ },
+ {
+ xtype: "button",
+ glyph: "xf00d@FontAwesome",
+ handler: function () {
+ me.showSearchBox(false);
+ },
+ },
+ ],
+ },
+ listeners: {
+ afterrender: me.onAfterRender,
+ beforedestroy: me.onBeforeDestroy,
+ },
+ });
+
+ if (me.record.get("statusbar")) {
+ Ext.apply(me, {
+ bbar: me.statusBarConstructor(false),
+ });
+ } else {
+ me.items.push(me.statusBarConstructor(true));
+ }
+
+ me.callParent(config);
+ },
+
+ onBeforeDestroy: function () {
+ var me = this;
+
+ me.setUnreadCount(0);
+ },
+
+ webViewConstructor: function (enabled) {
+ var me = this;
+
+ var cfg;
+ enabled = enabled || me.record.get("enabled");
+
+ if (!enabled) {
+ cfg = {
+ xtype: "container",
+ html: "Service Disabled
",
+ style: "text-align:center;",
+ padding: 100,
+ };
+ } else {
+ cfg = [
+ {
+ xtype: "component",
+ cls: "webview",
+ hideMode: "offsets",
+ autoRender: true,
+ autoShow: true,
+ autoEl: {
+ tag: "webview",
+ src: me.record.get("url"),
+ style: "width:100%;height:100%;visibility:visible;",
+ partition:
+ "persist:" +
+ me.record.get("type") +
+ "_" +
+ me.id.replace("tab_", "") +
+ (localStorage.getItem("id_token")
+ ? "_" + Ext.decode(localStorage.getItem("profile")).sub
+ : ""),
+ plugins: "true",
+ allowtransparency: "on",
+ autosize: "on",
+ webpreferences:
+ "nativeWindowOpen=yes, spellcheck=no, contextIsolation=no",
+ allowpopups: "on",
+ // ,disablewebsecurity: 'on' // Disabled because some services (Like Google Drive) dont work with this enabled
+ useragent: me.getUserAgent(),
+ preload: "./resources/js/rambox-service-api.js",
+ },
+ },
+ ];
+ }
+
+ return cfg;
+ },
+ getUserAgent: function () {
+ var ua = ipc.sendSync("getConfig").user_agent
+ ? ipc.sendSync("getConfig").user_agent
+ : Ext.getStore("ServicesList").getById(this.record.get("type"))
+ ? Ext.getStore("ServicesList")
+ .getById(this.record.get("type"))
+ .get("userAgent")
+ : "";
+ return ua.length === 0
+ ? window.clientInformation.userAgent
+ .replace(/Rambox\/([0-9]\.?)+\s/gi, "")
+ .replace(/Electron\/([0-9]\.?)+\s/gi, "")
+ : ua;
+ },
+
+ statusBarConstructor: function (floating) {
+ var me = this;
+
+ return {
+ xtype: "statusbar",
+ id: me.id + "statusbar",
+ hidden: !me.record.get("statusbar"),
+ keep: me.record.get("statusbar"),
+ y: floating ? "-18px" : "auto",
+ height: 19,
+ dock: "bottom",
+ defaultText: ' Ready',
+ busyIconCls: "",
+ busyText:
+ ' ' +
+ locale["app.webview[4]"],
+ items: [
+ {
+ xtype: "tbtext",
+ itemId: "url",
+ },
+ {
+ xtype: "button",
+ glyph: "xf00d@FontAwesome",
+ scale: "small",
+ ui: "decline",
+ padding: 0,
+ scope: me,
+ hidden: floating,
+ handler: me.closeStatusBar,
+ tooltip: {
+ text: "Close statusbar until next time",
+ mouseOffset: [0, -60],
+ },
+ },
+ ],
+ };
+ },
+
+ onAfterRender: function () {
+ var me = this;
+
+ if (!me.record.get("enabled")) return;
+
+ var webview = me.getWebView();
+ me.errorCodeLog = [];
+
+ // Google Analytics Event
+ ga_storage._trackEvent("Services", "load", me.type, 1, true);
+
+ // Notifications in Webview
+ me.setNotifications(
+ localStorage.getItem("locked") ||
+ JSON.parse(localStorage.getItem("dontDisturb"))
+ ? false
+ : me.record.get("notifications")
+ );
+
+ // Show and hide spinner when is loading
+ webview.addEventListener("did-start-loading", function () {
+ console.info("Start loading...", me.src);
+
+ require("electron")
+ .remote.webContents.fromId(webview.getWebContentsId())
+ .session.webRequest.onBeforeSendHeaders((details, callback) => {
+ Rambox.app.config.googleURLs.forEach((loginURL) => {
+ if (details.url.indexOf(loginURL) > -1)
+ details.requestHeaders["User-Agent"] =
+ "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:70.0) Gecko/20100101 Firefox/70.0";
+ });
+ callback({ cancel: false, requestHeaders: details.requestHeaders });
+ });
+
+ if (!me.down("statusbar").closed || !me.down("statusbar").keep)
+ me.down("statusbar").show();
+ me.down("statusbar").showBusy();
+ });
+ webview.addEventListener("did-stop-loading", function () {
+ me.down("statusbar").clearStatus({ useDefaults: true });
+ if (!me.down("statusbar").keep) me.down("statusbar").hide();
+ });
+
+ webview.addEventListener("did-finish-load", function (e) {
+ Rambox.app.setTotalServicesLoaded(
+ Rambox.app.getTotalServicesLoaded() + 1
+ );
+
+ // Apply saved zoom level
+ webview.setZoomLevel(me.record.get("zoomLevel"));
+
+ // Fix cursor sometimes dissapear
+ let currentTab = Ext.cq1("app-main").getActiveTab();
+ if (currentTab.id === me.id) {
+ webview.blur();
+ webview.focus();
+ }
+ // Set special icon for some service (like Slack)
+ Rambox.util.IconLoader.loadServiceIconUrl(me, webview);
+ });
+
+ // On search text
+ webview.addEventListener("found-in-page", function (e) {
+ me.onSearchText(e.result);
+ });
+
+ // On search text
+ webview.addEventListener("did-fail-load", function (e) {
+ console.info("The service fail at loading", me.src, e);
+
+ if (me.record.get("disableAutoReloadOnFail") || !e.isMainFrame) return;
+ me.errorCodeLog.push(e.errorCode);
+
+ var attempt = me.errorCodeLog.filter(function (code) {
+ return code === e.errorCode;
+ });
+
+ // Error codes: https://cs.chromium.org/chromium/src/net/base/net_error_list.h
+ var msg = [];
+ msg[-2] = "NET error: failed.";
+ msg[-3] = "An operation was aborted (due to user action)";
+ msg[-7] = "Connection timeout.";
+ msg[-21] = "Network change.";
+ msg[-100] = "The connection was reset. Check your internet connection.";
+ msg[-101] = "The connection was reset. Check your internet connection.";
+ msg[-105] = "Name not resolved. Check your internet connection.";
+ msg[-106] = "There is no active internet connection.";
+ msg[-118] = "Connection timed out. Check your internet connection.";
+ msg[-130] =
+ "Proxy connection failed. Please, check the proxy configuration.";
+ msg[-300] = "The URL is invalid.";
+ msg[-324] = "Empty response. Check your internet connection.";
+
+ switch (e.errorCode) {
+ case 0:
+ break;
+ case -3: // An operation was aborted (due to user action) I think that gmail an other pages that use iframes stop some of them making this error fired
+ if (attempt.length <= 4) return;
+ setTimeout(() => me.reloadService(me), 200);
+ me.errorCodeLog = [];
+ break;
+ case -2:
+ case -7:
+ case -21:
+ case -118:
+ case -324:
+ case -100:
+ case -101:
+ case -105:
+ attempt.length > 4
+ ? me.onFailLoad(msg[e.errorCode])
+ : setTimeout(() => me.reloadService(me), 2000);
+ break;
+ case -106:
+ me.onFailLoad(msg[e.errorCode]);
+ break;
+ case -130:
+ // Could not create a connection to the proxy server. An error occurred
+ // either in resolving its name, or in connecting a socket to it.
+ // Note that this does NOT include failures during the actual "CONNECT" method
+ // of an HTTP proxy.
+ case -300:
+ attempt.length > 4
+ ? me.onFailLoad(msg[e.errorCode])
+ : me.reloadService(me);
+ break;
+ }
+ });
+
+ // Open links in default browser
+ webview.addEventListener("new-window", function (e) {
+ e.preventDefault();
+ const protocol = require("url").parse(e.url).protocol;
+ // Block some Deep links to prevent that open its app (Ex: Slack)
+ if (["slack:"].includes(protocol)) return;
+ // Allow Deep links
+ if (!["http:", "https:", "about:"].includes(protocol))
+ return require("electron").shell.openExternal(e.url);
+ });
+
+ webview.addEventListener("will-navigate", function (e, url) {
+ e.preventDefault();
+ });
+
+ let eventsOnDom = false;
+ webview.addEventListener("dom-ready", function (e) {
+ // Mute Webview
+ if (
+ me.record.get("muted") ||
+ localStorage.getItem("locked") ||
+ JSON.parse(localStorage.getItem("dontDisturb"))
+ )
+ me.setAudioMuted(true, true);
+
+ var js_inject = "";
+ // Injected code to detect new messages
+ if (me.record) {
+ var js_unread = Ext.getStore("ServicesList").getById(
+ me.record.get("type")
+ )
+ ? Ext.getStore("ServicesList")
+ .getById(me.record.get("type"))
+ .get("js_unread")
+ : "";
+ js_unread = js_unread + me.record.get("js_unread");
+ if (js_unread !== "") {
+ console.groupCollapsed(
+ me.record.get("type").toUpperCase() +
+ " - JS Injected to Detect New Messages"
+ );
+ console.info(me.type);
+ console.log(js_unread);
+ js_inject += js_unread;
+ }
+ }
+
+ // Prevent Title blinking (some services have) and only allow when the title have an unread regex match: "(3) Title"
+ if (
+ Ext.getStore("ServicesList").getById(me.record.get("type"))
+ ? Ext.getStore("ServicesList")
+ .getById(me.record.get("type"))
+ .get("titleBlink")
+ : false
+ ) {
+ var js_preventBlink =
+ 'var originalTitle=document.title;Object.defineProperty(document,"title",{configurable:!0,set:function(a){null===a.match(new RegExp("[(]([0-9•]+)[)][ ](.*)","g"))&&a!==originalTitle||(document.getElementsByTagName("title")[0].innerHTML=a)},get:function(){return document.getElementsByTagName("title")[0].innerHTML}});';
+ console.log(js_preventBlink);
+ js_inject += js_preventBlink;
+ }
+
+ console.groupEnd();
+
+ // Scroll always to top (bug)
+ js_inject += "document.body.scrollTop=0;";
+
+ // Handles Certificate Errors
+ require("electron")
+ .remote.webContents.fromId(webview.getWebContentsId())
+ .on(
+ "certificate-error",
+ function (event, url, error, certificate, callback) {
+ if (me.record.get("trust")) {
+ event.preventDefault();
+ callback(true);
+ } else {
+ callback(false);
+ }
+
+ me.down("statusbar").keep = true;
+ me.down("statusbar").show();
+ me.down("statusbar").setStatus({
+ text:
+ ' Certification Warning',
+ });
+ me.down("statusbar").down("button").show();
+ }
+ );
+ if (!eventsOnDom) {
+ require("electron")
+ .remote.webContents.fromId(webview.getWebContentsId())
+ .on("before-input-event", (event, input) => {
+ if (input.type !== "keyDown") return;
+
+ var modifiers = [];
+ if (input.shift) modifiers.push("shift");
+ if (input.control) modifiers.push("control");
+ if (input.alt) modifiers.push("alt");
+ if (input.meta) modifiers.push("meta");
+ if (input.isAutoRepeat) modifiers.push("isAutoRepeat");
+
+ if (input.key === "Tab" && !(modifiers && modifiers.length)) return;
+
+ // Maps special keys to fire the correct event in Mac OS
+ if (require("electron").remote.process.platform === "darwin") {
+ var keys = [];
+ keys["ƒ"] = "f"; // Search
+ keys[" "] = "l"; // Lock
+ keys["∂"] = "d"; // DND
+
+ input.key = keys[input.key] ? keys[input.key] : input.key;
+ }
+
+ if (
+ input.key === "F11" ||
+ input.key === "a" ||
+ input.key === "A" ||
+ input.key === "F12" ||
+ input.key === "q" ||
+ (input.key === "F1" && modifiers.includes("control"))
+ )
+ return;
+
+ require("electron").remote.getCurrentWebContents().sendInputEvent({
+ type: input.type,
+ keyCode: input.key,
+ modifiers: modifiers,
+ });
+ });
+ eventsOnDom = true;
+
+ Rambox.app.config.googleURLs.forEach((loginURL) => {
+ if (webview.getURL().indexOf(loginURL) > -1) webview.reload();
+ });
+ }
+ webview
+ .executeJavaScript(js_inject)
+ .then((result) => {})
+ .catch((err) => {
+ console.log(err);
+ });
+ });
+
+ webview.addEventListener("ipc-message", function (event) {
+ var channel = event.channel;
+ switch (channel) {
+ case "rambox.setUnreadCount":
+ handleSetUnreadCount(event);
+ break;
+ case "rambox.clearUnreadCount":
+ handleClearUnreadCount(event);
+ break;
+ case "rambox.showWindowAndActivateTab":
+ showWindowAndActivateTab(event);
+ break;
+ }
+ /**
+ * Handles 'rambox.clearUnreadCount' messages.
+ * Clears the unread count.
+ */
+ function handleClearUnreadCount() {
+ me.tab.setBadgeText("");
+ me.currentUnreadCount = 0;
+ me.setUnreadCount(0);
+ }
+
+ /**
+ * Handles 'rambox.setUnreadCount' messages.
+ * Sets the badge text if the event contains an integer or a '•' (indicating non-zero but unknown number of unreads) as first argument.
+ *
+ * @param event
+ */
+ function handleSetUnreadCount(event) {
+ if (Array.isArray(event.args) === true && event.args.length > 0) {
+ var count = event.args[0];
+ if (count === parseInt(count, 10) || "•" === count) {
+ if (count === 999999) count = "•";
+ me.setUnreadCount(count);
+ }
+ }
+ }
+
+ function showWindowAndActivateTab(event) {
+ require("electron").remote.getCurrentWindow().show();
+ var tabPanel = Ext.cq1("app-main");
+ // Temp fix missing cursor after upgrade to electron 3.x +
+ tabPanel.setActiveTab(me);
+ tabPanel.getActiveTab().getWebView().blur();
+ tabPanel.getActiveTab().getWebView().focus();
+ }
+ });
+
+ /**
+ * Register page title update event listener only for services that don't specify a js_unread
+ */
+ if (
+ Ext.getStore("ServicesList").getById(me.record.get("type"))
+ ? Ext.getStore("ServicesList")
+ .getById(me.record.get("type"))
+ .get("js_unread") === ""
+ : false && me.record.get("js_unread") === ""
+ ) {
+ webview.addEventListener("page-title-updated", function (e) {
+ var count = e.title.match(/\(([^)]+)\)/); // Get text between (...)
+ count = count ? count[1] : "0";
+ count =
+ count === "•"
+ ? count
+ : Ext.isArray(count.match(/\d+/g))
+ ? count.match(/\d+/g).join("")
+ : count.match(/\d+/g); // Some services have special characters. Example: (•)
+ count = count === null ? "0" : count;
+
+ me.setUnreadCount(count);
+ });
+ }
+
+ webview.addEventListener("did-navigate", function (e) {
+ if (e.isMainFrame && me.record.get("type") === "tweetdeck")
+ Ext.defer(function () {
+ webview.loadURL(e.newURL);
+ }, 1000); // Applied a defer because sometimes is not redirecting. TweetDeck 2FA is an example.
+ });
+
+ webview.addEventListener("update-target-url", function (url) {
+ me.down("statusbar #url").setText(url.url);
+ });
+ },
+
+ setUnreadCount: function (newUnreadCount) {
+ var me = this;
+
+ if (
+ !isNaN(newUnreadCount) &&
+ (function (x) {
+ return (x | 0) === x;
+ })(parseFloat(newUnreadCount)) &&
+ me.record.get("includeInGlobalUnreadCounter") === true
+ ) {
+ Rambox.util.UnreadCounter.setUnreadCountForService(
+ me.record.get("id"),
+ newUnreadCount
+ );
+ } else {
+ Rambox.util.UnreadCounter.clearUnreadCountForService(me.record.get("id"));
+ }
+
+ me.setTabBadgeText(Rambox.util.Format.formatNumber(newUnreadCount));
+
+ me.doManualNotification(parseInt(newUnreadCount));
+ },
+
+ refreshUnreadCount: function () {
+ this.setUnreadCount(this.currentUnreadCount);
+ },
+
+ /**
+ * Dispatch manual notification if
+ * • service doesn't have notifications, so Rambox does them
+ * • count increased
+ * • not in dnd mode
+ * • notifications enabled
+ *
+ * @param {int} count
+ */
+ doManualNotification: function (count) {
+ var me = this;
+ var manualNotifications = Ext.getStore("ServicesList").getById(me.type)
+ ? Ext.getStore("ServicesList")
+ .getById(me.type)
+ .get("manual_notifications")
+ : false;
+ if (
+ manualNotifications &&
+ me.currentUnreadCount < count &&
+ me.record.get("notifications") &&
+ !JSON.parse(localStorage.getItem("dontDisturb"))
+ ) {
+ Rambox.util.Notifier.dispatchNotification(me, count);
+ }
+
+ me.currentUnreadCount = count;
+ },
+
+ /**
+ * Sets the tab badge text depending on the service config param "displayTabUnreadCounter".
+ *
+ * @param {string} badgeText
+ */
+ setTabBadgeText: function (badgeText) {
+ var me = this;
+ if (me.record.get("displayTabUnreadCounter") === true) {
+ me.tab.setBadgeText(badgeText);
+ } else {
+ me.tab.setBadgeText("");
+ }
+ },
+
+ /**
+ * Clears the unread counter for this view:
+ * • clears the badge text
+ * • clears the global unread counter
+ */
+ clearUnreadCounter: function () {
+ var me = this;
+ me.tab.setBadgeText("");
+ Rambox.util.UnreadCounter.clearUnreadCountForService(me.record.get("id"));
+ },
+
+ reloadService: function (btn) {
+ var me = this;
+ var webview = me.getWebView();
+
+ if (me.record.get("enabled")) {
+ me.clearUnreadCounter();
+ webview.loadURL(me.src);
+ }
+ },
+
+ onFailLoad: function (v) {
+ let me = this;
+ me.errorCodeLog = [];
+ setTimeout(
+ () =>
+ Ext.getCmp(me.id + "statusbar").setStatus({
+ text:
+ ' The service failed at loading, Error: ' +
+ v,
+ }),
+ 1000
+ );
+ },
+
+ showSearchBox: function (v) {
+ var me = this;
+ if (!me.record.get("enabled")) return;
+ var webview = me.getWebView();
+
+ webview.stopFindInPage("keepSelection");
+ if (v) {
+ me.down("#searchBar").show();
+ setTimeout(() => {
+ me.down("#searchBar textfield").focus();
+ }, 100);
+ } else {
+ me.down("#searchBar").hide();
+ me.down("#searchBar textfield").setValue("");
+ }
+
+ me.down("#searchBar displayfield").setValue("");
+ },
+
+ doSearchText: function (field, newValue, oldValue, eOpts, forward = true) {
+ var me = this;
+ var webview = me.getWebView();
+
+ if (newValue === "") {
+ webview.stopFindInPage("clearSelection");
+ me.down("#searchBar displayfield").setValue("");
+ return;
+ }
+
+ webview.findInPage(newValue, {
+ forward: forward,
+ findNext: false,
+ matchCase: false,
+ });
+ },
+
+ onSearchText: function (result) {
+ var me = this;
+
+ me.down("#searchBar displayfield").setValue(
+ result.activeMatchOrdinal + "/" + result.matches
+ );
+ },
+
+ toggleDevTools: function (btn) {
+ var me = this;
+ var webview = me.getWebView();
+
+ if (me.record.get("enabled"))
+ webview.isDevToolsOpened()
+ ? webview.closeDevTools()
+ : webview.openDevTools();
+ },
+
+ setURL: function (url) {
+ var me = this;
+ var webview = me.getWebView();
+
+ me.src = url;
+
+ if (me.record.get("enabled")) webview.loadURL(url);
+ },
+
+ setAudioMuted: function (muted, calledFromDisturb) {
+ var me = this;
+ var webview = me.getWebView();
+
+ me.muted = muted;
+
+ if (
+ !muted &&
+ !calledFromDisturb &&
+ JSON.parse(localStorage.getItem("dontDisturb"))
+ )
+ return;
+
+ if (me.record.get("enabled")) webview.setAudioMuted(muted);
+ },
+
+ closeStatusBar: function () {
+ var me = this;
+
+ me.down("statusbar").hide();
+ me.down("statusbar").closed = true;
+ me.down("statusbar").keep = me.record.get("statusbar");
+ },
+
+ setStatusBar: function (keep) {
+ var me = this;
+
+ me.removeDocked(me.down("statusbar"), true);
+
+ if (keep) {
+ me.addDocked(me.statusBarConstructor(false));
+ } else {
+ me.add(me.statusBarConstructor(true));
+ }
+ me.down("statusbar").keep = keep;
+ },
+
+ setNotifications: function (notification, calledFromDisturb) {
+ var me = this;
+ var webview = me.getWebView();
+
+ me.notifications = notification;
+
+ if (
+ notification &&
+ !calledFromDisturb &&
+ JSON.parse(localStorage.getItem("dontDisturb"))
+ )
+ return;
+
+ if (me.record.get("enabled"))
+ ipc.send("setServiceNotifications", webview.partition, notification);
+ },
+
+ setEnabled: function (enabled) {
+ var me = this;
+
+ me.clearUnreadCounter();
+
+ me.removeAll();
+ me.add(me.webViewConstructor(enabled));
+ if (enabled) {
+ me.resumeEvent("afterrender");
+ me.show();
+ me.tab.setStyle("-webkit-filter", "grayscale(0)");
+ me.onAfterRender();
+ } else {
+ me.suspendEvent("afterrender");
+ me.tab.setStyle("-webkit-filter", "grayscale(1)");
+ }
+ },
+
+ goBack: function () {
+ var me = this;
+ var webview = me.getWebView();
+
+ if (me.record.get("enabled")) webview.goBack();
+ },
+
+ goForward: function () {
+ var me = this;
+ var webview = me.getWebView();
+
+ if (me.record.get("enabled")) webview.goForward();
+ },
+
+ zoomIn: function () {
+ if (this.timeout) clearTimeout(this.timeout);
+ this.timeout = setTimeout(() => {
+ var me = this;
+ var webview = me.getWebView();
+ me.zoomLevel = me.zoomLevel + 0.25;
+ if (me.record.get("enabled")) {
+ webview.setZoomLevel(me.zoomLevel);
+ me.record.set("zoomLevel", me.zoomLevel);
+ }
+ }, 100);
+ },
+
+ zoomOut: function () {
+ if (this.timeout) clearTimeout(this.timeout);
+ this.timeout = setTimeout(() => {
+ var me = this;
+ var webview = me.getWebView();
+ me.zoomLevel = me.zoomLevel - 0.25;
+ if (me.record.get("enabled")) {
+ webview.setZoomLevel(me.zoomLevel);
+ me.record.set("zoomLevel", me.zoomLevel);
+ }
+ }, 100);
+ },
+
+ resetZoom: function () {
+ var me = this;
+ var webview = me.getWebView();
+
+ me.zoomLevel = 0;
+ if (me.record.get("enabled")) {
+ webview.setZoomLevel(0);
+ me.record.set("zoomLevel", me.zoomLevel);
+ }
+ },
+
+ getWebView: function () {
+ if (this.record.get("enabled")) {
+ return this.down("component[cls=webview]").el.dom;
+ } else {
+ return false;
+ }
+ },
});
diff --git a/app/view/main/MainController.js b/app/view/main/MainController.js
index 81d311b7..ec52f3a8 100644
--- a/app/view/main/MainController.js
+++ b/app/view/main/MainController.js
@@ -1,546 +1,675 @@
-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(`
+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');
- }
+ }
+ 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");
+ },
});
diff --git a/app/view/preferences/Preferences.js b/app/view/preferences/Preferences.js
index 7ef806d4..c7cf01e1 100644
--- a/app/view/preferences/Preferences.js
+++ b/app/view/preferences/Preferences.js
@@ -1,382 +1,412 @@
-Ext.define('Rambox.view.preferences.Preferences',{
- extend: 'Ext.window.Window'
- ,xtype: 'preferences'
+Ext.define("Rambox.view.preferences.Preferences", {
+ extend: "Ext.window.Window",
+ xtype: "preferences",
- ,requires: [
- 'Rambox.view.preferences.PreferencesController'
- ,'Rambox.view.preferences.PreferencesModel'
- ,'Ext.form.field.ComboBox'
- ,'Ext.form.field.Checkbox'
- ]
+ requires: [
+ "Rambox.view.preferences.PreferencesController",
+ "Rambox.view.preferences.PreferencesModel",
+ "Ext.form.field.ComboBox",
+ "Ext.form.field.Checkbox",
+ ],
- ,controller: 'preferences-preferences'
- ,viewModel: {
- type: 'preferences-preferences'
- }
+ controller: "preferences-preferences",
+ viewModel: {
+ type: "preferences-preferences",
+ },
- ,title: locale['preferences[0]']
- ,width: 420
- ,height: 500
- ,modal: true
- ,closable: true
- ,minimizable: false
- ,maximizable: false
- ,draggable: true
- ,resizable: false
- ,scrollable: 'vertical'
- ,bodyStyle: 'margin-right:15px;'
- ,buttons: [
- {
- text: locale['button[1]']
- ,ui: 'decline'
- ,handler: 'cancel'
- }
- ,'->'
- ,{
- text: locale['button[4]']
- ,handler: 'save'
- }
- ]
+ title: locale["preferences[0]"],
+ width: 420,
+ height: 500,
+ modal: true,
+ closable: true,
+ minimizable: false,
+ maximizable: false,
+ draggable: true,
+ resizable: false,
+ scrollable: "vertical",
+ bodyStyle: "margin-right:15px;",
+ buttons: [
+ {
+ text: locale["button[1]"],
+ ui: "decline",
+ handler: "cancel",
+ },
+ "->",
+ {
+ text: locale["button[4]"],
+ handler: "save",
+ },
+ ],
- ,initComponent: function() {
- var config = ipc.sendSync('getConfig');
+ initComponent: function () {
+ var config = ipc.sendSync("getConfig");
- var defaultServiceOptions = [];
- defaultServiceOptions.push({ value: 'ramboxTab', label: 'Rambox Tab' });
- defaultServiceOptions.push({ value: 'last', label: 'Last Active Service' });
- Ext.getStore('Services').each(function(rec) {
- defaultServiceOptions.push({
- value: rec.get('id')
- ,label: rec.get('name')
- });
- });
+ var defaultServiceOptions = [];
+ defaultServiceOptions.push({ value: "ramboxTab", label: "Rambox Tab" });
+ defaultServiceOptions.push({ value: "last", label: "Last Active Service" });
+ Ext.getStore("Services").each(function (rec) {
+ defaultServiceOptions.push({
+ value: rec.get("id"),
+ label: rec.get("name"),
+ });
+ });
- this.items = [
- {
- xtype: 'form'
- ,bodyPadding: 20
- ,items: [
- {
- xtype: 'container'
- ,layout: 'hbox'
- ,items: [
- {
- xtype: 'combo'
- ,name: 'locale'
- ,fieldLabel: 'Language'
- ,labelAlign: 'left'
- ,flex: 1
- ,labelWidth: 80
- ,value: config.locale
- ,displayField: 'label'
- ,valueField: 'value'
- ,editable: false
- ,store: Ext.create('Ext.data.Store', {
- fields: ['value', 'label']
- ,data: [
- { 'value': 'af', 'auth0': 'af', 'label': 'Afrikaans' }
- ,{ 'value': 'ar', 'auth0': 'en', 'label': 'Arabic' }
- ,{ 'value': 'bs2', 'auth0': 'en', 'label': 'Barndutsch, Switzerland' }
- ,{ 'value': 'bn', 'auth0': 'en', 'label': 'Bengali' }
- ,{ 'value': 'bg', 'auth0': 'en', 'label': 'Bulgarian' }
- ,{ 'value': 'ca', 'auth0': 'ca', 'label': 'Catalan' }
- ,{ 'value': 'ceb', 'auth0': 'en', 'label': 'Cebuano' }
- ,{ 'value': 'zh-CN', 'auth0': 'zh', 'label': 'Chinese Simplified' }
- ,{ 'value': 'zh-TW', 'auth0': 'zh-tw', 'label': 'Chinese Traditional' }
- ,{ 'value': 'hr', 'auth0': 'en', 'label': 'Croatian' }
- ,{ 'value': 'cs', 'auth0': 'cs', 'label': 'Czech' }
- ,{ 'value': 'da', 'auth0': 'da', 'label': 'Danish' }
- ,{ 'value': 'nl', 'auth0': 'nl', 'label': 'Dutch' }
- ,{ 'value': 'en', 'auth0': 'en', 'label': 'English' }
- ,{ 'value': 'fi', 'auth0': 'fi', 'label': 'Finnish' }
- ,{ 'value': 'fil', 'auth0': 'en', 'label': 'Filipino' }
- ,{ 'value': 'fr', 'auth0': 'fr', 'label': 'French' }
- ,{ 'value': 'de', 'auth0': 'de', 'label': 'German' }
- ,{ 'value': 'de-CH', 'auth0': 'de', 'label': 'German, Switzerland' }
- ,{ 'value': 'el', 'auth0': 'el', 'label': 'Greek' }
- ,{ 'value': 'he', 'auth0': 'en', 'label': 'Hebrew' }
- ,{ 'value': 'hi', 'auth0': 'en', 'label': 'Hindi' }
- ,{ 'value': 'hu', 'auth0': 'hu', 'label': 'Hungarian' }
- ,{ 'value': 'id', 'auth0': 'en', 'label': 'Indonesian' }
- ,{ 'value': 'it', 'auth0': 'it', 'label': 'Italian' }
- ,{ 'value': 'ja', 'auth0': 'ja', 'label': 'Japanese' }
- ,{ 'value': 'ko', 'auth0': 'ko', 'label': 'Korean' }
- ,{ 'value': 'no', 'auth0': 'no', 'label': 'Norwegian' }
- ,{ 'value': 'fa', 'auth0': 'fa', 'label': 'Persian' }
- ,{ 'value': 'pl', 'auth0': 'pl', 'label': 'Polish' }
- ,{ 'value': 'pt-PT', 'auth0': 'pt-br', 'label': 'Portuguese' }
- ,{ 'value': 'pt-BR', 'auth0': 'pt-br', 'label': 'Portuguese (Brazilian)' }
- ,{ 'value': 'ro', 'auth0': 'ro', 'label': 'Romanian' }
- ,{ 'value': 'ru', 'auth0': 'ru', 'label': 'Russian' }
- ,{ 'value': 'sr', 'auth0': 'en', 'label': 'Serbian (Cyrillic)' }
- ,{ 'value': 'sk', 'auth0': 'sk', 'label': 'Slovak' }
- ,{ 'value': 'es-ES', 'auth0': 'es', 'label': 'Spanish' }
- ,{ 'value': 'sv-SE', 'auth0': 'sv', 'label': 'Swedish' }
- ,{ 'value': 'tl', 'auth0': 'en', 'label': 'Tagalog' }
- ,{ 'value': 'th', 'auth0': 'en', 'label': 'Thai' }
- ,{ 'value': 'tr', 'auth0': 'tr', 'label': 'Turkish' }
- ,{ 'value': 'uk', 'auth0': 'en', 'label': 'Ukrainian' }
- ,{ 'value': 'ur-PK', 'auth0': 'en', 'label': 'Urdu (Pakistan)' }
- ,{ 'value': 'vi', 'auth0': 'en', 'label': 'Vietnamese' }
- ]
- })
- }
- ,{
- xtype: 'button'
- ,text: 'Help us Translate'
- ,style: 'border-top-left-radius:0;border-bottom-left-radius:0;'
- ,href: 'https://crowdin.com/project/rambox/invite'
- }
- ]
- }
- ,{
- xtype: 'label'
- ,text: 'English is the only language that has full translation. We are working with all the others, help us!'
- ,style: 'display:block;font-size:10px;line-height:15px;'
- ,margin: '0 0 10 0'
- }
- ,{
- xtype: 'checkbox'
- ,name: 'auto_launch'
- ,boxLabel: locale['preferences[5]']
- ,value: config.auto_launch
- }
- ,{
- xtype: 'checkbox'
- ,name: 'start_minimized'
- ,boxLabel: locale['preferences[4]']
- ,value: config.start_minimized
- }
- ,{
- xtype: 'checkbox'
- ,name: 'darkreader'
- ,boxLabel: locale['preferences[29]']
- ,value: config.darkreader
- }
- ,{
- xtype: 'checkbox'
- ,name: 'hide_menu_bar'
- ,boxLabel: locale['preferences[1]']+' (Alt
key to display)'
- ,value: config.hide_menu_bar
- ,hidden: process.platform === 'darwin'
- }
- ,{
- xtype: 'combo'
- ,name: 'tabbar_location'
- ,fieldLabel: locale['preferences[11]']
- ,labelAlign: 'left'
- ,width: 380
- ,labelWidth: 180
- ,value: config.tabbar_location
- ,displayField: 'label'
- ,valueField: 'value'
- ,editable: false
- ,store: Ext.create('Ext.data.Store', {
- fields: ['value', 'label']
- ,data: [
- { 'value': 'top', 'label': 'Top' }
- ,{ 'value': 'left', 'label': 'Left' }
- ,{ 'value': 'bottom', 'label': 'Bottom' }
- ,{ 'value': 'right', 'label': 'Right' }
- ]
- })
- }
- ,{
- xtype: 'checkbox'
- ,name: 'hide_tabbar_labels'
- ,boxLabel: locale['preferences[28]']
- ,value: config.hide_tabbar_labels
- }
- ,{
- xtype: 'combo'
- ,name: 'default_service'
- ,fieldLabel: locale['preferences[12]']
- ,labelAlign: 'top'
- //,width: 380
- //,labelWidth: 105
- ,value: config.default_service
- ,displayField: 'label'
- ,valueField: 'value'
- ,editable: false
- ,store: Ext.create('Ext.data.Store', {
- fields: ['value', 'label']
- ,data: defaultServiceOptions
- })
- }
- ,{
- xtype: 'combo'
- ,name: 'window_display_behavior'
- ,fieldLabel: locale['preferences[13]']
- ,labelAlign: 'left'
- ,width: 380
- ,labelWidth: 105
- ,value: config.window_display_behavior
- ,displayField: 'label'
- ,valueField: 'value'
- ,editable: false
- ,store: Ext.create('Ext.data.Store', {
- fields: ['value', 'label']
- ,data: [
- { 'value': 'show_taskbar', 'label': locale['preferences[14]'] }
- ,{ 'value': 'show_trayIcon', 'label': locale['preferences[15]'] }
- ,{ 'value': 'taskbar_tray', 'label': locale['preferences[16]'] }
- ]
- })
- ,hidden: process.platform === 'darwin'
- }
- ,{
- xtype: 'combo'
- ,name: 'window_close_behavior'
- ,fieldLabel: locale['preferences[17]']
- ,labelAlign: 'left'
- ,width: 380
- ,labelWidth: 180
- ,value: config.window_close_behavior
- ,displayField: 'label'
- ,valueField: 'value'
- ,editable: false
- ,store: Ext.create('Ext.data.Store', {
- fields: ['value', 'label']
- ,data: [
- { 'value': 'keep_in_tray', 'label': locale['preferences[18]'] }
- ,{ 'value': 'keep_in_tray_and_taskbar', 'label': locale['preferences[19]'] }
- ,{ 'value': 'quit', 'label': locale['preferences[20]'] }
- ]
- })
- ,hidden: process.platform === 'darwin'
- }
- ,{
- xtype: 'checkbox'
- ,name: 'always_on_top'
- ,boxLabel: locale['preferences[21]']
- ,value: config.always_on_top
- }
- ,{
- xtype: 'checkbox'
- ,name: 'systemtray_indicator'
- ,boxLabel: locale['preferences[22]']
- ,value: config.systemtray_indicator
- ,hidden: process.platform === 'darwin'
- }
- ,{
- xtype: 'checkbox'
- ,name: 'flash_frame'
- ,boxLabel: process.platform === 'darwin' ? locale['preferences[10]'] : locale['preferences[9]']
- ,value: config.flash_frame
- }
- ,{
- xtype: 'checkbox'
- ,name: 'disable_gpu'
- ,boxLabel: locale['preferences[23]']
- ,value: config.disable_gpu
- }
- ,{
- xtype: 'checkbox'
- ,name: 'enable_hidpi_support'
- ,boxLabel: locale['preferences[8]']
- ,value: config.enable_hidpi_support
- ,hidden: process.platform !== 'win32'
- },
- {
- xtype: 'textfield'
- ,fieldLabel: 'Override User-Agent for all services (needs to relaunch)'
- ,labelAlign: 'top'
- ,name: 'user_agent'
- ,value: config.user_agent
- ,width: 360
- ,emptyText: 'Leave blank for default user agent'
- }
- ,{
- xtype: 'fieldset'
- ,title: locale['preferences[24]']
- ,collapsed: !config.master_password
- ,checkboxToggle: true
- ,checkboxName: 'master_password'
- ,margin: '10 0 0 0'
- ,padding: 10
- ,layout: 'hbox'
- ,defaults: { labelAlign: 'top' }
- ,items: [
- {
- xtype: 'textfield'
- ,inputType: 'password'
- ,fieldLabel: locale['preferences[25]']
- ,name: 'master_password1'
- ,itemId: 'pass'
- ,flex: 1
- ,listeners: {
- validitychange: function(field) {
- field.next().validate();
- },
- blur: function(field) {
- field.next().validate();
- }
- }
- }
- ,{
- xtype: 'textfield'
- ,inputType: 'password'
- ,fieldLabel: locale['preferences[26]']
- ,name: 'master_password2'
- ,margin: '0 0 0 10'
- ,vtype: 'password'
- ,initialPassField: 'pass'
- ,flex: 1
- }
- ]
- }
- ,{
- xtype: 'fieldset'
- ,title: 'Proxy (needs to relaunch) - Free Proxy Servers'
- ,collapsed: !config.proxy
- ,checkboxToggle: true
- ,checkboxName: 'proxy'
- ,margin: '10 0 0 0'
- ,padding: 10
- ,layout: 'vbox'
- ,defaults: { labelAlign: 'left' }
- ,items: [
- {
- xtype: 'textfield'
- ,vtype: 'url'
- ,fieldLabel: 'Host'
- ,name: 'proxyHost'
- ,value: config.proxyHost
- //,flex: 1
- }
- ,{
- xtype: 'numberfield'
- ,fieldLabel: 'Port'
- ,name: 'proxyPort'
- ,value: config.proxyPort
- }
- ,{
- xtype: 'textfield'
- ,fieldLabel: 'Login'
- ,name: 'proxyLogin'
- ,value: config.proxyLogin
- ,emptyText: 'Optional'
- }
- ,{
- xtype: 'textfield'
- ,fieldLabel: 'Password'
- ,name: 'proxyPassword'
- ,value: config.proxyPassword
- ,emptyText: 'Optional'
- ,inputType: 'password'
- }
- ]
- }
- ,{
- xtype: 'checkbox'
- ,name: 'sendStatistics'
- ,boxLabel: locale['preferences[27]']
- ,value: config.sendStatistics
- }
- ]
- }
- ];
+ this.items = [
+ {
+ xtype: "form",
+ bodyPadding: 20,
+ items: [
+ {
+ xtype: "container",
+ layout: "hbox",
+ items: [
+ {
+ xtype: "combo",
+ name: "locale",
+ fieldLabel: "Language",
+ labelAlign: "left",
+ flex: 1,
+ labelWidth: 80,
+ value: config.locale,
+ displayField: "label",
+ valueField: "value",
+ editable: false,
+ store: Ext.create("Ext.data.Store", {
+ fields: ["value", "label"],
+ data: [
+ { value: "af", auth0: "af", label: "Afrikaans" },
+ { value: "ar", auth0: "en", label: "Arabic" },
+ {
+ value: "bs2",
+ auth0: "en",
+ label: "Barndutsch, Switzerland",
+ },
+ { value: "bn", auth0: "en", label: "Bengali" },
+ { value: "bg", auth0: "en", label: "Bulgarian" },
+ { value: "ca", auth0: "ca", label: "Catalan" },
+ { value: "ceb", auth0: "en", label: "Cebuano" },
+ {
+ value: "zh-CN",
+ auth0: "zh",
+ label: "Chinese Simplified",
+ },
+ {
+ value: "zh-TW",
+ auth0: "zh-tw",
+ label: "Chinese Traditional",
+ },
+ { value: "hr", auth0: "en", label: "Croatian" },
+ { value: "cs", auth0: "cs", label: "Czech" },
+ { value: "da", auth0: "da", label: "Danish" },
+ { value: "nl", auth0: "nl", label: "Dutch" },
+ { value: "en", auth0: "en", label: "English" },
+ { value: "fi", auth0: "fi", label: "Finnish" },
+ { value: "fil", auth0: "en", label: "Filipino" },
+ { value: "fr", auth0: "fr", label: "French" },
+ { value: "de", auth0: "de", label: "German" },
+ {
+ value: "de-CH",
+ auth0: "de",
+ label: "German, Switzerland",
+ },
+ { value: "el", auth0: "el", label: "Greek" },
+ { value: "he", auth0: "en", label: "Hebrew" },
+ { value: "hi", auth0: "en", label: "Hindi" },
+ { value: "hu", auth0: "hu", label: "Hungarian" },
+ { value: "id", auth0: "en", label: "Indonesian" },
+ { value: "it", auth0: "it", label: "Italian" },
+ { value: "ja", auth0: "ja", label: "Japanese" },
+ { value: "ko", auth0: "ko", label: "Korean" },
+ { value: "no", auth0: "no", label: "Norwegian" },
+ { value: "fa", auth0: "fa", label: "Persian" },
+ { value: "pl", auth0: "pl", label: "Polish" },
+ { value: "pt-PT", auth0: "pt-br", label: "Portuguese" },
+ {
+ value: "pt-BR",
+ auth0: "pt-br",
+ label: "Portuguese (Brazilian)",
+ },
+ { value: "ro", auth0: "ro", label: "Romanian" },
+ { value: "ru", auth0: "ru", label: "Russian" },
+ { value: "sr", auth0: "en", label: "Serbian (Cyrillic)" },
+ { value: "sk", auth0: "sk", label: "Slovak" },
+ { value: "es-ES", auth0: "es", label: "Spanish" },
+ { value: "sv-SE", auth0: "sv", label: "Swedish" },
+ { value: "tl", auth0: "en", label: "Tagalog" },
+ { value: "th", auth0: "en", label: "Thai" },
+ { value: "tr", auth0: "tr", label: "Turkish" },
+ { value: "uk", auth0: "en", label: "Ukrainian" },
+ { value: "ur-PK", auth0: "en", label: "Urdu (Pakistan)" },
+ { value: "vi", auth0: "en", label: "Vietnamese" },
+ ],
+ }),
+ },
+ {
+ xtype: "button",
+ text: "Help us Translate",
+ style: "border-top-left-radius:0;border-bottom-left-radius:0;",
+ href: "https://crowdin.com/project/rambox/invite",
+ },
+ ],
+ },
+ {
+ xtype: "label",
+ text:
+ "English is the only language that has full translation. We are working with all the others, help us!",
+ style: "display:block;font-size:10px;line-height:15px;",
+ margin: "0 0 10 0",
+ },
+ {
+ xtype: "checkbox",
+ name: "auto_launch",
+ boxLabel: locale["preferences[5]"],
+ value: config.auto_launch,
+ },
+ {
+ xtype: "checkbox",
+ name: "start_minimized",
+ boxLabel: locale["preferences[4]"],
+ value: config.start_minimized,
+ },
+ {
+ xtype: "checkbox",
+ name: "darkreader",
+ boxLabel: locale["preferences[29]"],
+ value: config.darkreader,
+ },
+ {
+ xtype: "checkbox",
+ name: "hide_menu_bar",
+ boxLabel:
+ locale["preferences[1]"] + " (Alt
key to display)",
+ value: config.hide_menu_bar,
+ hidden: process.platform === "darwin",
+ },
+ {
+ xtype: "combo",
+ name: "tabbar_location",
+ fieldLabel: locale["preferences[11]"],
+ labelAlign: "left",
+ width: 380,
+ labelWidth: 180,
+ value: config.tabbar_location,
+ displayField: "label",
+ valueField: "value",
+ editable: false,
+ store: Ext.create("Ext.data.Store", {
+ fields: ["value", "label"],
+ data: [
+ { value: "top", label: "Top" },
+ { value: "left", label: "Left" },
+ { value: "bottom", label: "Bottom" },
+ { value: "right", label: "Right" },
+ ],
+ }),
+ },
+ {
+ xtype: "checkbox",
+ name: "hide_tabbar_labels",
+ boxLabel: locale["preferences[28]"],
+ value: config.hide_tabbar_labels,
+ },
+ {
+ xtype: "combo",
+ name: "default_service",
+ fieldLabel: locale["preferences[12]"],
+ labelAlign: "top",
+ //,width: 380
+ //,labelWidth: 105
+ value: config.default_service,
+ displayField: "label",
+ valueField: "value",
+ editable: false,
+ store: Ext.create("Ext.data.Store", {
+ fields: ["value", "label"],
+ data: defaultServiceOptions,
+ }),
+ },
+ {
+ xtype: "combo",
+ name: "window_display_behavior",
+ fieldLabel: locale["preferences[13]"],
+ labelAlign: "left",
+ width: 380,
+ labelWidth: 105,
+ value: config.window_display_behavior,
+ displayField: "label",
+ valueField: "value",
+ editable: false,
+ store: Ext.create("Ext.data.Store", {
+ fields: ["value", "label"],
+ data: [
+ { value: "show_taskbar", label: locale["preferences[14]"] },
+ { value: "show_trayIcon", label: locale["preferences[15]"] },
+ { value: "taskbar_tray", label: locale["preferences[16]"] },
+ ],
+ }),
+ hidden: process.platform === "darwin",
+ },
+ {
+ xtype: "combo",
+ name: "window_close_behavior",
+ fieldLabel: locale["preferences[17]"],
+ labelAlign: "left",
+ width: 380,
+ labelWidth: 180,
+ value: config.window_close_behavior,
+ displayField: "label",
+ valueField: "value",
+ editable: false,
+ store: Ext.create("Ext.data.Store", {
+ fields: ["value", "label"],
+ data: [
+ { value: "keep_in_tray", label: locale["preferences[18]"] },
+ {
+ value: "keep_in_tray_and_taskbar",
+ label: locale["preferences[19]"],
+ },
+ { value: "quit", label: locale["preferences[20]"] },
+ ],
+ }),
+ hidden: process.platform === "darwin",
+ },
+ {
+ xtype: "checkbox",
+ name: "always_on_top",
+ boxLabel: locale["preferences[21]"],
+ value: config.always_on_top,
+ },
+ {
+ xtype: "checkbox",
+ name: "systemtray_indicator",
+ boxLabel: locale["preferences[22]"],
+ value: config.systemtray_indicator,
+ hidden: process.platform === "darwin",
+ },
+ {
+ xtype: "checkbox",
+ name: "flash_frame",
+ boxLabel:
+ process.platform === "darwin"
+ ? locale["preferences[10]"]
+ : locale["preferences[9]"],
+ value: config.flash_frame,
+ },
+ {
+ xtype: "checkbox",
+ name: "disable_gpu",
+ boxLabel: locale["preferences[23]"],
+ value: config.disable_gpu,
+ },
+ {
+ xtype: "checkbox",
+ name: "enable_hidpi_support",
+ boxLabel: locale["preferences[8]"],
+ value: config.enable_hidpi_support,
+ hidden: process.platform !== "win32",
+ },
+ {
+ xtype: "textfield",
+ fieldLabel:
+ "Override User-Agent for all services (needs to relaunch)",
+ labelAlign: "top",
+ name: "user_agent",
+ value: config.user_agent,
+ width: 360,
+ emptyText: "Leave blank for default user agent",
+ },
+ {
+ xtype: "fieldset",
+ title: locale["preferences[24]"],
+ collapsed: !config.master_password,
+ checkboxToggle: true,
+ checkboxName: "master_password",
+ margin: "10 0 0 0",
+ padding: 10,
+ layout: "hbox",
+ defaults: { labelAlign: "top" },
+ items: [
+ {
+ xtype: "textfield",
+ inputType: "password",
+ fieldLabel: locale["preferences[25]"],
+ name: "master_password1",
+ itemId: "pass",
+ flex: 1,
+ listeners: {
+ validitychange: function (field) {
+ field.next().validate();
+ },
+ blur: function (field) {
+ field.next().validate();
+ },
+ },
+ },
+ {
+ xtype: "textfield",
+ inputType: "password",
+ fieldLabel: locale["preferences[26]"],
+ name: "master_password2",
+ margin: "0 0 0 10",
+ vtype: "password",
+ initialPassField: "pass",
+ flex: 1,
+ },
+ ],
+ },
+ {
+ xtype: "fieldset",
+ title:
+ 'Proxy (needs to relaunch) - Free Proxy Servers',
+ collapsed: !config.proxy,
+ checkboxToggle: true,
+ checkboxName: "proxy",
+ margin: "10 0 0 0",
+ padding: 10,
+ layout: "vbox",
+ defaults: { labelAlign: "left" },
+ items: [
+ {
+ xtype: "textfield",
+ vtype: "url",
+ fieldLabel: "Host",
+ name: "proxyHost",
+ value: config.proxyHost,
+ //,flex: 1
+ },
+ {
+ xtype: "numberfield",
+ fieldLabel: "Port",
+ name: "proxyPort",
+ value: config.proxyPort,
+ },
+ {
+ xtype: "textfield",
+ fieldLabel: "Login",
+ name: "proxyLogin",
+ value: config.proxyLogin,
+ emptyText: "Optional",
+ },
+ {
+ xtype: "textfield",
+ fieldLabel: "Password",
+ name: "proxyPassword",
+ value: config.proxyPassword,
+ emptyText: "Optional",
+ inputType: "password",
+ },
+ ],
+ },
+ {
+ xtype: "checkbox",
+ name: "sendStatistics",
+ boxLabel: locale["preferences[27]"],
+ value: config.sendStatistics,
+ },
+ ],
+ },
+ ];
- this.callParent();
- }
+ this.callParent();
+ },
});
diff --git a/electron/main.js b/electron/main.js
index 5aab2ad4..d68d5906 100644
--- a/electron/main.js
+++ b/electron/main.js
@@ -33,38 +33,38 @@ if (isDev)
// Initial Config
const config = new Config({
- defaults: {
- always_on_top: false
- ,hide_menu_bar: false
- ,tabbar_location: 'top'
- ,hide_tabbar_labels: false
- ,window_display_behavior: 'taskbar_tray'
- ,auto_launch: !isDev
- ,flash_frame: true
- ,window_close_behavior: 'keep_in_tray'
- ,start_minimized: false
- ,darkreader: true
- ,systemtray_indicator: true
- ,master_password: false
- ,dont_disturb: false
- ,disable_gpu: process.platform === 'linux'
- ,proxy: false
- ,proxyHost: ''
- ,proxyPort: ''
- ,proxyLogin: ''
- ,proxyPassword: ''
- ,locale: 'en'
- ,enable_hidpi_support: false
- ,user_agent: ''
- ,default_service: 'ramboxTab'
- ,sendStatistics: false
-
- ,x: undefined
- ,y: undefined
- ,width: 1000
- ,height: 800
- ,maximized: false
- }
+ defaults: {
+ always_on_top: false,
+ hide_menu_bar: false,
+ tabbar_location: "top",
+ hide_tabbar_labels: false,
+ window_display_behavior: "taskbar_tray",
+ auto_launch: !isDev,
+ flash_frame: true,
+ window_close_behavior: "keep_in_tray",
+ start_minimized: false,
+ darkreader: true,
+ systemtray_indicator: true,
+ master_password: false,
+ dont_disturb: false,
+ disable_gpu: process.platform === "linux",
+ proxy: false,
+ proxyHost: "",
+ proxyPort: "",
+ proxyLogin: "",
+ proxyPassword: "",
+ locale: "en",
+ enable_hidpi_support: false,
+ user_agent: "",
+ default_service: "ramboxTab",
+ sendStatistics: false,
+
+ x: undefined,
+ y: undefined,
+ width: 1000,
+ height: 800,
+ maximized: false,
+ },
});
// Fix issues with HiDPI scaling on Windows platform
diff --git a/package.json b/package.json
index 3bc3ae7a..6c2f62c1 100644
--- a/package.json
+++ b/package.json
@@ -1,241 +1,241 @@
{
- "name": "Rambox",
- "productName": "Rambox",
- "version": "0.7.9",
- "description": "Free and Open Source messaging and emailing app that combines common web applications into one.",
- "main": "electron/main.js",
- "repository": {
- "type": "git",
- "url": "https://github.com/ramboxapp/community-edition.git"
- },
- "bugs": {
- "url": "https://github.com/ramboxapp/community-edition/issues"
- },
- "homepage": "https://rambox.app",
- "keywords": [
- "Rambox",
- "messaging",
- "app",
- "slack",
- "whatsapp",
- "facebook",
- "messenger",
- "telegram",
- "google",
- "hangouts",
- "skype"
- ],
- "author": "Rambox LLC ",
- "license": "GPL-3.0",
- "scripts": {
- "start": "electron electron/main.js",
- "start:debug": "electron electron/main.js --enable-logging",
- "dev": "electron electron/main.js",
- "test": "./node_modules/.bin/mocha test/tests/**/*.spec.js",
- "sencha:clean": "rm -rf ./build/production",
- "sencha:compile": "sencha app build && npm --prefix ./build/production/Rambox/ install ./build/production/Rambox/",
- "sencha:compile:build": "sencha app build",
- "clean": "rm -rf ./dist",
- "clean:osx": "rm -rf ./dist/Rambox-darwin-*",
- "clean:win": "rm -rf ./dist/Rambox-win32-*",
- "pack": "npm run pack:osx && npm run pack:win",
- "pack:osx": "electron-packager \"./build/production/Rambox/\" \"Rambox\" --out=dist --platform=darwin --arch=x64 --icon=resources/installer/Icon.icns --app-version=0.2.0 --build-version=64-bit --version-string.CompanyName=\"Rambox\" --version-string.ProductName=\"Rambox\" --asar --prune --overwrite",
- "pack:win": "npm run pack:win32 && npm run pack:win64",
- "pack:win32": "electron-packager \"./build/production/Rambox/\" \"Rambox\" --out=dist --platform=win32 --arch=ia32 --icon=resources/installer/Icon.ico --app-version=0.2.0 --build-version=32-bit --version-string.CompanyName=\"Rambox\" --version-string.ProductName=\"Rambox\" --asar --prune --overwrite",
- "pack:win64": "electron-packager \"./build/production/Rambox/\" \"Rambox\" --out=dist --platform=win32 --arch=x64 --icon=resources/installer/Icon.ico --app-version=0.2.0 --build-version=64-bit --version-string.CompanyName=\"Rambox\" --version-string.ProductName=\"Rambox\" --asar --prune --overwrite",
- "pack:linux": "npm run pack:linux32 && npm run pack:linux64",
- "pack:linux32": "electron-packager \"./build/production/Rambox/\" \"Rambox\" --out=dist --platform=linux --arch=ia32 --icon=resources/installer/Icon.ico --app-version=0.2.0 --build-version=64-bit --version-string.CompanyName=\"Rambox\" --version-string.ProductName=\"Rambox\" --asar --prune --overwrite",
- "pack:linux64": "electron-packager \"./build/production/Rambox/\" \"Rambox\" --out=dist --platform=linux --arch=x64 --icon=resources/installer/Icon.ico --app-version=0.2.0 --build-version=64-bit --version-string.CompanyName=\"Rambox\" --version-string.ProductName=\"Rambox\" --asar --prune --overwrite",
- "build": "npm run build:linux && npm run build:osx && npm run build:win",
- "build:osx": "electron-builder --macos",
- "build:linux": "electron-builder --linux --publish=onTagOrDraft",
- "build:linux32": "electron-builder --linux --ia32 --publish=onTagOrDraft",
- "build:linux64": "electron-builder --linux --x64 --publish=onTagOrDraft",
- "build:win": "electron-builder --win --ia32 --x64",
- "build:win32": "electron-builder --win --ia32",
- "build:win64": "electron-builder --win --x64",
- "setup:osx": "npm run sencha:clean && npm run sencha:compile && npm run clean:osx && npm run pack:osx && npm run build:osx",
- "setup:win": "npm run sencha:clean && npm run sencha:compile && npm run clean:win && npm run pack:win && npm run build:win",
- "all:win": "npm run sencha:clean && npm run sencha:compile && npm run clean:win && npm run pack:win && npm run zip:win32 && npm run zip:win64 && npm run build:win",
- "all:linux": "npm run sencha:clean && npm run sencha:compile && npm run build:linux",
- "translations:download": "node languages.js download",
- "translations:generate": "node languages.js generate"
- },
- "build": {
- "productName": "Rambox",
- "appId": "com.grupovrs.ramboxce",
- "afterSign": "resources/installer/notarize.js",
- "asar": true,
- "electronVersion": "11.4.10",
- "electronDownload": {
- "version": "11.4.10"
- },
- "mac": {
- "category": "public.app-category.productivity",
- "artifactName": "Rambox-${version}-mac.${ext}",
- "target": [
- "default"
- ],
- "hardenedRuntime": true,
- "gatekeeperAssess": false,
- "entitlements": "resources/installer/entitlements.mac.plist",
- "entitlementsInherit": "resources/installer/entitlements.mac.plist",
- "extendInfo": {
- "NSMicrophoneUsageDescription": "Apps inside Rambox CE may need access to your microphone. Please, grant access to have a better experience.",
- "NSCameraUsageDescription": "Apps inside Rambox CE may need access to your camera. Please, grant access to have a better experience."
- }
- },
- "dmg": {
- "title": "Rambox",
- "iconSize": 128,
- "sign": false,
- "contents": [
- {
- "x": 355,
- "y": 125,
- "type": "link",
- "path": "/Applications"
- },
- {
- "x": 155,
- "y": 125,
- "type": "file"
- }
- ]
- },
- "win": {
- "publisherName": "Rambox LLC",
- "artifactName": "Rambox-${version}-win-${arch}.${ext}",
- "target": [
- "nsis",
- "zip"
- ]
- },
- "nsis": {
- "deleteAppDataOnUninstall": true,
- "oneClick": false,
- "perMachine": false,
- "runAfterFinish": true
- },
- "snap": {
- "publish": [
- {
- "provider": "github"
- }
- ],
- "plugs": [
- "default",
- "camera",
- "audio-record",
- "audio-playback",
- "removable-media",
- "raw-usb",
- "u2f-devices",
- "cups-control"
- ]
- },
- "linux": {
- "icon": "resources/installer/icons",
- "category": "Network",
- "desktop": {
- "Terminal": "false",
- "Type": "Application",
- "Categories": "GTK;GNOME;Network;Email;Chat;InstantMessaging;"
- },
- "artifactName": "Rambox-${version}-linux-${arch}.${ext}",
- "executableArgs": [
- "--no-sandbox"
- ],
- "target": [
- {
- "target": "snap",
- "arch": [
- "x64"
- ]
- },
- {
- "target": "AppImage",
- "arch": [
- "x64",
- "ia32"
- ]
- },
- {
- "target": "deb",
- "arch": [
- "x64",
- "ia32"
- ]
- },
- {
- "target": "rpm",
- "arch": [
- "x64",
- "ia32"
- ]
- },
- {
- "target": "zip",
- "arch": [
- "x64",
- "ia32"
- ]
- },
- {
- "target": "tar.gz",
- "arch": [
- "x64",
- "ia32"
- ]
- }
- ]
- },
- "directories": {
- "buildResources": "resources/installer/",
- "output": "dist/"
- },
- "publish": [
- {
- "provider": "github",
- "owner": "ramboxapp",
- "repo": "community-edition",
- "vPrefixedTagName": false
- }
- ]
- },
- "devDependencies": {
- "asar": "0.12.4",
- "chai": "3.5.0",
- "crowdin": "1.0.0",
- "csvjson": "4.3.3",
- "electron": "11.4.10",
- "electron-builder": "22.9.1",
- "electron-notarize": "1.0.0",
- "electron-packager": "15.1.0",
- "mocha": "5.2.0",
- "spectron": "3.8.0"
- },
- "dependencies": {
- "@exponent/electron-cookies": "2.0.0",
- "auth0-js": "9.13.2",
- "auto-launch-patched": "5.0.2",
- "crypto": "1.0.1",
- "darkreader": "4.9.17",
- "diskusage": "1.1.3",
- "electron-contextmenu-wrapper": "git+https://github.com/ramboxapp/electron-contextmenu-wrapper.git",
- "electron-is-dev": "0.3.0",
- "electron-log": "2.2.17",
- "electron-store": "6.0.0",
- "electron-updater": "4.1.2",
- "is-online": "8.2.0",
- "mime": "2.3.1",
- "mousetrap": "1.6.3",
- "request": "2.88.0",
- "request-promise": "4.2.2",
- "rimraf": "2.6.1",
- "tmp": "0.0.28"
- },
- "volta": {
- "node": "14.16.1"
- }
+ "name": "Rambox",
+ "productName": "Rambox",
+ "version": "0.7.9",
+ "description": "Free and Open Source messaging and emailing app that combines common web applications into one.",
+ "main": "electron/main.js",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/ramboxapp/community-edition.git"
+ },
+ "bugs": {
+ "url": "https://github.com/ramboxapp/community-edition/issues"
+ },
+ "homepage": "https://rambox.app",
+ "keywords": [
+ "Rambox",
+ "messaging",
+ "app",
+ "slack",
+ "whatsapp",
+ "facebook",
+ "messenger",
+ "telegram",
+ "google",
+ "hangouts",
+ "skype"
+ ],
+ "author": "Rambox LLC ",
+ "license": "GPL-3.0",
+ "scripts": {
+ "start": "electron electron/main.js",
+ "start:debug": "electron electron/main.js --enable-logging",
+ "dev": "electron electron/main.js",
+ "test": "./node_modules/.bin/mocha test/tests/**/*.spec.js",
+ "sencha:clean": "rm -rf ./build/production",
+ "sencha:compile": "sencha app build && npm --prefix ./build/production/Rambox/ install ./build/production/Rambox/",
+ "sencha:compile:build": "sencha app build",
+ "clean": "rm -rf ./dist",
+ "clean:osx": "rm -rf ./dist/Rambox-darwin-*",
+ "clean:win": "rm -rf ./dist/Rambox-win32-*",
+ "pack": "npm run pack:osx && npm run pack:win",
+ "pack:osx": "electron-packager \"./build/production/Rambox/\" \"Rambox\" --out=dist --platform=darwin --arch=x64 --icon=resources/installer/Icon.icns --app-version=0.2.0 --build-version=64-bit --version-string.CompanyName=\"Rambox\" --version-string.ProductName=\"Rambox\" --asar --prune --overwrite",
+ "pack:win": "npm run pack:win32 && npm run pack:win64",
+ "pack:win32": "electron-packager \"./build/production/Rambox/\" \"Rambox\" --out=dist --platform=win32 --arch=ia32 --icon=resources/installer/Icon.ico --app-version=0.2.0 --build-version=32-bit --version-string.CompanyName=\"Rambox\" --version-string.ProductName=\"Rambox\" --asar --prune --overwrite",
+ "pack:win64": "electron-packager \"./build/production/Rambox/\" \"Rambox\" --out=dist --platform=win32 --arch=x64 --icon=resources/installer/Icon.ico --app-version=0.2.0 --build-version=64-bit --version-string.CompanyName=\"Rambox\" --version-string.ProductName=\"Rambox\" --asar --prune --overwrite",
+ "pack:linux": "npm run pack:linux32 && npm run pack:linux64",
+ "pack:linux32": "electron-packager \"./build/production/Rambox/\" \"Rambox\" --out=dist --platform=linux --arch=ia32 --icon=resources/installer/Icon.ico --app-version=0.2.0 --build-version=64-bit --version-string.CompanyName=\"Rambox\" --version-string.ProductName=\"Rambox\" --asar --prune --overwrite",
+ "pack:linux64": "electron-packager \"./build/production/Rambox/\" \"Rambox\" --out=dist --platform=linux --arch=x64 --icon=resources/installer/Icon.ico --app-version=0.2.0 --build-version=64-bit --version-string.CompanyName=\"Rambox\" --version-string.ProductName=\"Rambox\" --asar --prune --overwrite",
+ "build": "npm run build:linux && npm run build:osx && npm run build:win",
+ "build:osx": "electron-builder --macos",
+ "build:linux": "electron-builder --linux --publish=onTagOrDraft",
+ "build:linux32": "electron-builder --linux --ia32 --publish=onTagOrDraft",
+ "build:linux64": "electron-builder --linux --x64 --publish=onTagOrDraft",
+ "build:win": "electron-builder --win --ia32 --x64",
+ "build:win32": "electron-builder --win --ia32",
+ "build:win64": "electron-builder --win --x64",
+ "setup:osx": "npm run sencha:clean && npm run sencha:compile && npm run clean:osx && npm run pack:osx && npm run build:osx",
+ "setup:win": "npm run sencha:clean && npm run sencha:compile && npm run clean:win && npm run pack:win && npm run build:win",
+ "all:win": "npm run sencha:clean && npm run sencha:compile && npm run clean:win && npm run pack:win && npm run zip:win32 && npm run zip:win64 && npm run build:win",
+ "all:linux": "npm run sencha:clean && npm run sencha:compile && npm run build:linux",
+ "translations:download": "node languages.js download",
+ "translations:generate": "node languages.js generate"
+ },
+ "build": {
+ "productName": "Rambox",
+ "appId": "com.grupovrs.ramboxce",
+ "afterSign": "resources/installer/notarize.js",
+ "asar": true,
+ "electronVersion": "11.4.10",
+ "electronDownload": {
+ "version": "11.4.10"
+ },
+ "mac": {
+ "category": "public.app-category.productivity",
+ "artifactName": "Rambox-${version}-mac.${ext}",
+ "target": [
+ "default"
+ ],
+ "hardenedRuntime": true,
+ "gatekeeperAssess": false,
+ "entitlements": "resources/installer/entitlements.mac.plist",
+ "entitlementsInherit": "resources/installer/entitlements.mac.plist",
+ "extendInfo": {
+ "NSMicrophoneUsageDescription": "Apps inside Rambox CE may need access to your microphone. Please, grant access to have a better experience.",
+ "NSCameraUsageDescription": "Apps inside Rambox CE may need access to your camera. Please, grant access to have a better experience."
+ }
+ },
+ "dmg": {
+ "title": "Rambox",
+ "iconSize": 128,
+ "sign": false,
+ "contents": [
+ {
+ "x": 355,
+ "y": 125,
+ "type": "link",
+ "path": "/Applications"
+ },
+ {
+ "x": 155,
+ "y": 125,
+ "type": "file"
+ }
+ ]
+ },
+ "win": {
+ "publisherName": "Rambox LLC",
+ "artifactName": "Rambox-${version}-win-${arch}.${ext}",
+ "target": [
+ "nsis",
+ "zip"
+ ]
+ },
+ "nsis": {
+ "deleteAppDataOnUninstall": true,
+ "oneClick": false,
+ "perMachine": false,
+ "runAfterFinish": true
+ },
+ "snap": {
+ "publish": [
+ {
+ "provider": "github"
+ }
+ ],
+ "plugs": [
+ "default",
+ "camera",
+ "audio-record",
+ "audio-playback",
+ "removable-media",
+ "raw-usb",
+ "u2f-devices",
+ "cups-control"
+ ]
+ },
+ "linux": {
+ "icon": "resources/installer/icons",
+ "category": "Network",
+ "desktop": {
+ "Terminal": "false",
+ "Type": "Application",
+ "Categories": "GTK;GNOME;Network;Email;Chat;InstantMessaging;"
+ },
+ "artifactName": "Rambox-${version}-linux-${arch}.${ext}",
+ "executableArgs": [
+ "--no-sandbox"
+ ],
+ "target": [
+ {
+ "target": "snap",
+ "arch": [
+ "x64"
+ ]
+ },
+ {
+ "target": "AppImage",
+ "arch": [
+ "x64",
+ "ia32"
+ ]
+ },
+ {
+ "target": "deb",
+ "arch": [
+ "x64",
+ "ia32"
+ ]
+ },
+ {
+ "target": "rpm",
+ "arch": [
+ "x64",
+ "ia32"
+ ]
+ },
+ {
+ "target": "zip",
+ "arch": [
+ "x64",
+ "ia32"
+ ]
+ },
+ {
+ "target": "tar.gz",
+ "arch": [
+ "x64",
+ "ia32"
+ ]
+ }
+ ]
+ },
+ "directories": {
+ "buildResources": "resources/installer/",
+ "output": "dist/"
+ },
+ "publish": [
+ {
+ "provider": "github",
+ "owner": "ramboxapp",
+ "repo": "community-edition",
+ "vPrefixedTagName": false
+ }
+ ]
+ },
+ "devDependencies": {
+ "asar": "0.12.4",
+ "chai": "3.5.0",
+ "crowdin": "1.0.0",
+ "csvjson": "4.3.3",
+ "electron": "11.4.10",
+ "electron-builder": "22.9.1",
+ "electron-notarize": "1.0.0",
+ "electron-packager": "15.1.0",
+ "mocha": "5.2.0",
+ "spectron": "3.8.0"
+ },
+ "dependencies": {
+ "@exponent/electron-cookies": "2.0.0",
+ "auth0-js": "9.13.2",
+ "auto-launch-patched": "5.0.2",
+ "crypto": "1.0.1",
+ "darkreader": "4.9.17",
+ "diskusage": "1.1.3",
+ "electron-contextmenu-wrapper": "git+https://github.com/ramboxapp/electron-contextmenu-wrapper.git",
+ "electron-is-dev": "0.3.0",
+ "electron-log": "2.2.17",
+ "electron-store": "6.0.0",
+ "electron-updater": "4.1.2",
+ "is-online": "8.2.0",
+ "mime": "2.3.1",
+ "mousetrap": "1.6.3",
+ "request": "2.88.0",
+ "request-promise": "4.2.2",
+ "rimraf": "2.6.1",
+ "tmp": "0.0.28"
+ },
+ "volta": {
+ "node": "14.16.1"
+ }
}
diff --git a/resources/js/darkreader.js b/resources/js/darkreader.js
index ad74dfa6..6eb81710 100644
--- a/resources/js/darkreader.js
+++ b/resources/js/darkreader.js
@@ -1,14 +1,14 @@
-const { ipcRenderer } = require('electron');
-const darkreader = require('darkreader');
+const { ipcRenderer } = require("electron");
+const darkreader = require("darkreader");
darkreader.setFetchMethod(window.fetch);
+const getIsEnabled = () => ipcRenderer.sendSync("getConfig").darkreader;
+const canEnable = () =>
+ document.readyState === "complete" || document.readyState === "interactive";
-const getIsEnabled = () => ipcRenderer.sendSync('getConfig').darkreader;
-const canEnable = () => document.readyState === 'complete' || document.readyState === 'interactive';
-
-document.addEventListener('readystatechange', () => {
- console.log(document.readyState)
- if (canEnable()) {
- getIsEnabled()? darkreader.enable(): darkreader.disable();
- }
-});
\ No newline at end of file
+document.addEventListener("readystatechange", () => {
+ console.log(document.readyState);
+ if (canEnable()) {
+ getIsEnabled() ? darkreader.enable() : darkreader.disable();
+ }
+});
diff --git a/resources/js/rambox-service-api.js b/resources/js/rambox-service-api.js
index 9869b725..782616be 100644
--- a/resources/js/rambox-service-api.js
+++ b/resources/js/rambox-service-api.js
@@ -3,9 +3,12 @@
*/
const { desktopCapturer, ipcRenderer } = require("electron");
-require("./darkreader.js")
-const { ipcRenderer } = require('electron');
-const { ContextMenuBuilder, ContextMenuListener } = require('electron-contextmenu-wrapper');
+require("./darkreader.js");
+const { ipcRenderer } = require("electron");
+const {
+ ContextMenuBuilder,
+ ContextMenuListener,
+} = require("electron-contextmenu-wrapper");
/**
* Make the Rambox API available via a global "rambox" variable.
diff --git a/resources/languages/en.js b/resources/languages/en.js
index 1dc80752..c5e8aa61 100644
--- a/resources/languages/en.js
+++ b/resources/languages/en.js
@@ -1 +1,252 @@
-var locale=[];locale["preferences[0]"]="Preferences";locale["preferences[1]"]="Auto-hide Menu bar";locale["preferences[2]"]="Show in Taskbar";locale["preferences[3]"]="Keep Rambox in the taskbar when closing it";locale["preferences[4]"]="Start minimized";locale["preferences[5]"]="Start automatically on system startup";locale["preferences[6]"]="Don't need to see the menu bar all the time?";locale["preferences[7]"]="To temporarily show the menu bar, just press the Alt key.";locale["app.update[0]"]="New version is available!";locale["app.update[1]"]="Download";locale["app.update[2]"]="Changelog";locale["app.update[3]"]="You are up to date!";locale["app.update[4]"]="You have the latest version of Rambox.";locale["app.about[0]"]="About Rambox";locale["app.about[1]"]="Free and Open Source messaging and emailing app that combines common web applications into one.";locale["app.about[2]"]="Version";locale["app.about[3]"]="Platform";locale["app.about[4]"]="Developed by";locale["app.main[0]"]="Add a new Service";locale["app.main[1]"]="Messaging";locale["app.main[2]"]="Email";locale["app.main[3]"]="No services found... Try another search.";locale["app.main[4]"]="Enabled Services";locale["app.main[5]"]="ALIGN";locale["app.main[6]"]="Left";locale["app.main[7]"]="Right";locale["app.main[8]"]="Item";locale["app.main[9]"]="Items";locale["app.main[10]"]="Remove all Services";locale["app.main[11]"]="Prevent notifications";locale["app.main[12]"]="Muted";locale["app.main[13]"]="Configure";locale["app.main[14]"]="Remove";locale["app.main[15]"]="No services added...";locale["app.main[16]"]="Don't Disturb";locale["app.main[17]"]="Disable notifications and sounds in all services. Perfect to be concentrated and focused.";locale["app.main[18]"]="Shortcut key";locale["app.main[19]"]="Lock Rambox";locale["app.main[20]"]="Lock this app if you will be away for a period of time.";locale["app.main[21]"]="Logout";locale["app.main[22]"]="Login";locale["app.main[23]"]="Login to save your configuration (no credentials stored) to sync with all your computers.";locale["app.main[24]"]="Powered by";locale["app.main[25]"]="Donate";locale["app.main[26]"]="with";locale["app.main[27]"]="from Argentina as an Open Source project.";locale["app.window[0]"]="Add";locale["app.window[1]"]="Edit";locale["app.window[2]"]="Name";locale["app.window[3]"]="Options";locale["app.window[4]"]="Align to Right";locale["app.window[5]"]="Show notifications";locale["app.window[6]"]="Mute all sounds";locale["app.window[7]"]="Advanced";locale["app.window[8]"]="Custom Code";locale["app.window[9]"]="read more...";locale["app.window[10]"]="Add service";locale["app.window[11]"]="team";locale["app.window[12]"]="Please confirm...";locale["app.window[13]"]="Are you sure you want to remove";locale["app.window[14]"]="Are you sure you want to remove all services?";locale["app.window[15]"]="Add Custom Service";locale["app.window[16]"]="Edit Custom Service";locale["app.window[17]"]="URL";locale["app.window[18]"]="Logo";locale["app.window[19]"]="Trust invalid authority certificates";locale["app.window[20]"]="ON";locale["app.window[21]"]="OFF";locale["app.window[22]"]="Enter a temporal password to unlock it later";locale["app.window[23]"]="Repeat the temporal password";locale["app.window[24]"]="Warning";locale["app.window[25]"]="Passwords are not the same. Please try again...";locale["app.window[26]"]="Rambox is locked";locale["app.window[27]"]="UNLOCK";locale["app.window[28]"]="Connecting...";locale["app.window[29]"]="Please wait until we get your configuration.";locale["app.window[30]"]="Import";locale["app.window[31]"]="You don't have any service saved. Do you want to import your current services?";locale["app.window[32]"]="Clear services";locale["app.window[33]"]="Do you want to remove all your current services to start over?";locale["app.window[34]"]="If no, you will be logged out.";locale["app.window[35]"]="Confirm";locale["app.window[36]"]="To import your configuration, Rambox needs to remove all your current services. Do you want to continue?";locale["app.window[37]"]="Closing your session...";locale["app.window[38]"]="Are you sure you want to logout?";locale["app.webview[0]"]="Reload";locale["app.webview[1]"]="Go Online";locale["app.webview[2]"]="Go Offline";locale["app.webview[3]"]="Toggle Developer Tools";locale["app.webview[4]"]="Loading...";locale["preferences[8]"]="Enable HiDPI support (needs to relaunch)";locale["preferences[9]"]="Flash Taskbar on new message";locale["preferences[10]"]="Bounce Dock on new message";locale["preferences[11]"]="Service bar location";locale["preferences[12]"]="Default service to display when Rambox starts";locale["preferences[13]"]="Display behaviour";locale["preferences[14]"]="Show in Taskbar";locale["preferences[15]"]="Show Tray Icon";locale["preferences[16]"]="Show in Taskbar and Tray Icon";locale["preferences[17]"]="When closing the main window";locale["preferences[18]"]="Keep in tray";locale["preferences[19]"]="Keep in tray and/or taskbar";locale["preferences[20]"]="Quit";locale["preferences[21]"]="Always on top";locale["preferences[22]"]="Show System Tray indicator on unread messages";locale["preferences[23]"]="Disable Hardware Acceleration (needs to relaunch)";locale["preferences[24]"]="Master Password - Ask for password on startup";locale["preferences[25]"]="Password";locale["preferences[26]"]="Repeat Password";locale["preferences[27]"]="Send anonymous usage statistics to help us improve Rambox (needs to relaunch)";locale["preferences[28]"]="Hide service bar labels (requires restart)";;locale["preferences[29]"]="Enable global dark theme (Darkreader). Needs relaunch to apply for service tabs.";locale["button[0]"]="Ok";locale["button[1]"]="Cancel";locale["button[2]"]="Yes";locale["button[3]"]="No";locale["button[4]"]="Save";locale["main.dialog[0]"]="Certification Error";locale["main.dialog[1]"]="The service with the following URL has an invalid authority certification.";locale["main.dialog[2]"]="You have to remove the service and add it again";locale["menu.help[0]"]="Visit Rambox Website";locale["menu.help[1]"]="Report an Issue...";locale["menu.help[2]"]="Ask for Help";locale["menu.help[3]"]="Donate";locale["menu.help[4]"]="Help";locale["menu.edit[0]"]="Edit";locale["menu.edit[1]"]="Undo";locale["menu.edit[2]"]="Redo";locale["menu.edit[3]"]="Cut";locale["menu.edit[4]"]="Copy";locale["menu.edit[5]"]="Paste";locale["menu.edit[6]"]="Select All";locale["menu.view[0]"]="View";locale["menu.view[1]"]="Reload";locale["menu.view[2]"]="Toggle Full Screen";locale["menu.view[3]"]="Toggle Developer Tools";locale["menu.window[0]"]="Window";locale["menu.window[1]"]="Minimize";locale["menu.window[2]"]="Close";locale["menu.window[3]"]="Always on top";locale["menu.help[5]"]="Check for updates...";locale["menu.help[6]"]="About Rambox";locale["menu.osx[0]"]="Services";locale["menu.osx[1]"]="Hide Rambox";locale["menu.osx[2]"]="Hide Others";locale["menu.osx[3]"]="Show All";locale["menu.file[0]"]="File";locale["menu.file[1]"]="Quit Rambox";locale["tray[0]"]="Show/Hide Window";locale["tray[1]"]="Quit";locale["services[0]"]="WhatsApp is a cross-platform mobile messaging app for iPhone, BlackBerry, Android, Windows Phone and Nokia. Send text, video, images, audio for free.";locale["services[1]"]="Slack brings all your communication together in one place. It’s real-time messaging, archiving and search for modern teams.";locale["services[2]"]="Noysi is a communication tool for teams where privacy is guaranteed. With Noysi you can access all your conversations and files in seconds from anywhere and unlimited.";locale["services[3]"]="Instantly reach the people in your life for free. Messenger is just like texting, but you don't have to pay for every message.";locale["services[4]"]="Stay in touch with family and friends for free. Get international calling, free online calls and Skype for Business on desktop and mobile.";locale["services[5]"]="Hangouts bring conversations to life with photos, emoji, and even group video calls for free. Connect with friends across computers, Android, and Apple devices.";locale["services[6]"]="HipChat is hosted group chat and video chat built for teams. Supercharge real-time collaboration with persistent chat rooms, file sharing, and screen sharing.";locale["services[7]"]="Telegram is a messaging app with a focus on speed and security. It’s super-fast, simple, secure and free.";locale["services[8]"]="WeChat is a free messaging calling app that allows you to easily connect with family; friends across countries. It’s the all-in-one communications app for free text (SMS/MMS), voice; video calls, moments, photo sharing, and games.";locale["services[9]"]="Gmail, Google's free email service, is one of the world's most popular email programs.";locale["services[10]"]="Inbox by Gmail is a new app from the Gmail team. Inbox is an organized place to get things done and get back to what matters. Bundles keep emails organized.";locale["services[11]"]="ChatWork is a group chat app for business. Secure messaging, video chat, task management and file sharing. Real-time communication and increase productivity for teams.";locale["services[12]"]="GroupMe brings group text messaging to every phone. Group message with the people in your life that are important to you.";locale["services[13]"]="The world's most advanced team chat meets enterprise search.";locale["services[14]"]="Gitter is built on top of GitHub and is tightly integrated with your organizations, repositories, issues and activity.";locale["services[15]"]="Steam is a digital distribution platform developed by Valve Corporation offering digital rights management (DRM), multiplayer gaming and social networking services.";locale["services[16]"]="Step up your game with a modern voice & text chat app. Crystal clear voice, multiple server and channel support, mobile apps, and more.";locale["services[17]"]="Take control. Do more. Outlook is the free email and calendar service that helps you stay on top of what matters and get things done.";locale["services[18]"]="Outlook for Business";locale["services[19]"]="Web-based email service offered by the American company Yahoo!. The service is free for personal use, and paid-for business email plans are available.";locale["services[20]"]="Free and web-based encrypted email service founded in 2013 at the CERN research facility. ProtonMail is designed as a zero-knowledge system, using client-side encryption to protect emails and user data before they are sent to ProtonMail servers, in contrast to other common webmail services such as Gmail and Hotmail.";locale["services[21]"]="Tutanota is an open-source end-to-end encrypted email software and freemium hosted secure email service based on this software.";locale["services[22]"]="versions of service. Hushmail uses OpenPGP standards and the source is available for download.";locale["services[23]"]="Collaborative email and threaded group chat for productive teams. A single app for all your internal and external communication.";locale["services[24]"]="From group messages and video calls all the way to helpdesk killer features our goal is to become the number one cross-platform open source chat solution.";locale["services[25]"]="HD quality calls, private and group chats with inline photos, music and video. Also available for your phone or tablet.";locale["services[26]"]="Sync is a business chat tool that will boost productivity for your team.";locale["services[27]"]="No description...";locale["services[28]"]="Allows you to instant message with anyone on the Yahoo server. Tells you when you get mail, and gives stock quotes.";locale["services[29]"]="Voxer is a messaging app for your smartphone with live voice (like a PTT walkie talkie), text, photo and location sharing.";locale["services[30]"]="Dasher lets you say what you really want with pics, GIFs, links and more. Take a poll to find out what your friends really think of your new boo.";locale["services[31]"]="Flowdock is your team's chat with a shared inbox. Teams using Flowdock stay up-to-date, react in seconds instead of days, and never forget anything.";locale["services[32]"]="Mattermost is an open source, self-hosted Slack-alternative. As an alternative to proprietary SaaS messaging, Mattermost brings all your team communication into one place, making it searchable and accessible anywhere.";locale["services[33]"]="DingTalk is a multi-sided platform empowers small and medium-sized business to communicate effectively.";locale["services[34]"]="The mysms family of applications helps you text anywhere and enhances your messaging experience on your smartphone, tablet and computer.";locale["services[35]"]="ICQ is an open source instant messaging computer program that was first developed and popularized.";locale["services[36]"]="TweetDeck is a social media dashboard application for management of Twitter accounts.";locale["services[37]"]="Custom Service";locale["services[38]"]="Add a custom service if is not listed above.";locale["services[39]"]="Zinc is a secure communication app for mobile workers, with text, voice, video, file sharing and more.";locale["services[40]"]="Freenode, formerly known as Open Projects Network, is an IRC network used to discuss peer-directed projects.";locale["services[41]"]="Text from your computer, sync'd with your Android phone & number.";locale["services[42]"]="Free and open source webmail software for the masses, written in PHP.";locale["services[43]"]="Horde is a free and open source web-based groupware.";locale["services[44]"]="SquirrelMail is a standards-based webmail package written in PHP.";locale["services[45]"]="Ad-free business Email Hosting with a clean, minimalist interface. Integrated Calendar, Contacts, Notes, Tasks apps.";locale["services[46]"]="Zoho chat is a secure and scalable real-time communication and collaboration platform for teams to improve their productivity.";module.exports = locale;
\ No newline at end of file
+var locale = [];
+locale["preferences[0]"] = "Preferences";
+locale["preferences[1]"] = "Auto-hide Menu bar";
+locale["preferences[2]"] = "Show in Taskbar";
+locale["preferences[3]"] = "Keep Rambox in the taskbar when closing it";
+locale["preferences[4]"] = "Start minimized";
+locale["preferences[5]"] = "Start automatically on system startup";
+locale["preferences[6]"] = "Don't need to see the menu bar all the time?";
+locale["preferences[7]"] =
+ "To temporarily show the menu bar, just press the Alt key.";
+locale["app.update[0]"] = "New version is available!";
+locale["app.update[1]"] = "Download";
+locale["app.update[2]"] = "Changelog";
+locale["app.update[3]"] = "You are up to date!";
+locale["app.update[4]"] = "You have the latest version of Rambox.";
+locale["app.about[0]"] = "About Rambox";
+locale["app.about[1]"] =
+ "Free and Open Source messaging and emailing app that combines common web applications into one.";
+locale["app.about[2]"] = "Version";
+locale["app.about[3]"] = "Platform";
+locale["app.about[4]"] = "Developed by";
+locale["app.main[0]"] = "Add a new Service";
+locale["app.main[1]"] = "Messaging";
+locale["app.main[2]"] = "Email";
+locale["app.main[3]"] = "No services found... Try another search.";
+locale["app.main[4]"] = "Enabled Services";
+locale["app.main[5]"] = "ALIGN";
+locale["app.main[6]"] = "Left";
+locale["app.main[7]"] = "Right";
+locale["app.main[8]"] = "Item";
+locale["app.main[9]"] = "Items";
+locale["app.main[10]"] = "Remove all Services";
+locale["app.main[11]"] = "Prevent notifications";
+locale["app.main[12]"] = "Muted";
+locale["app.main[13]"] = "Configure";
+locale["app.main[14]"] = "Remove";
+locale["app.main[15]"] = "No services added...";
+locale["app.main[16]"] = "Don't Disturb";
+locale["app.main[17]"] =
+ "Disable notifications and sounds in all services. Perfect to be concentrated and focused.";
+locale["app.main[18]"] = "Shortcut key";
+locale["app.main[19]"] = "Lock Rambox";
+locale["app.main[20]"] =
+ "Lock this app if you will be away for a period of time.";
+locale["app.main[21]"] = "Logout";
+locale["app.main[22]"] = "Login";
+locale["app.main[23]"] =
+ "Login to save your configuration (no credentials stored) to sync with all your computers.";
+locale["app.main[24]"] = "Powered by";
+locale["app.main[25]"] = "Donate";
+locale["app.main[26]"] = "with";
+locale["app.main[27]"] = "from Argentina as an Open Source project.";
+locale["app.window[0]"] = "Add";
+locale["app.window[1]"] = "Edit";
+locale["app.window[2]"] = "Name";
+locale["app.window[3]"] = "Options";
+locale["app.window[4]"] = "Align to Right";
+locale["app.window[5]"] = "Show notifications";
+locale["app.window[6]"] = "Mute all sounds";
+locale["app.window[7]"] = "Advanced";
+locale["app.window[8]"] = "Custom Code";
+locale["app.window[9]"] = "read more...";
+locale["app.window[10]"] = "Add service";
+locale["app.window[11]"] = "team";
+locale["app.window[12]"] = "Please confirm...";
+locale["app.window[13]"] = "Are you sure you want to remove";
+locale["app.window[14]"] = "Are you sure you want to remove all services?";
+locale["app.window[15]"] = "Add Custom Service";
+locale["app.window[16]"] = "Edit Custom Service";
+locale["app.window[17]"] = "URL";
+locale["app.window[18]"] = "Logo";
+locale["app.window[19]"] = "Trust invalid authority certificates";
+locale["app.window[20]"] = "ON";
+locale["app.window[21]"] = "OFF";
+locale["app.window[22]"] = "Enter a temporal password to unlock it later";
+locale["app.window[23]"] = "Repeat the temporal password";
+locale["app.window[24]"] = "Warning";
+locale["app.window[25]"] = "Passwords are not the same. Please try again...";
+locale["app.window[26]"] = "Rambox is locked";
+locale["app.window[27]"] = "UNLOCK";
+locale["app.window[28]"] = "Connecting...";
+locale["app.window[29]"] = "Please wait until we get your configuration.";
+locale["app.window[30]"] = "Import";
+locale["app.window[31]"] =
+ "You don't have any service saved. Do you want to import your current services?";
+locale["app.window[32]"] = "Clear services";
+locale["app.window[33]"] =
+ "Do you want to remove all your current services to start over?";
+locale["app.window[34]"] = "If no, you will be logged out.";
+locale["app.window[35]"] = "Confirm";
+locale["app.window[36]"] =
+ "To import your configuration, Rambox needs to remove all your current services. Do you want to continue?";
+locale["app.window[37]"] = "Closing your session...";
+locale["app.window[38]"] = "Are you sure you want to logout?";
+locale["app.webview[0]"] = "Reload";
+locale["app.webview[1]"] = "Go Online";
+locale["app.webview[2]"] = "Go Offline";
+locale["app.webview[3]"] = "Toggle Developer Tools";
+locale["app.webview[4]"] = "Loading...";
+locale["preferences[8]"] = "Enable HiDPI support (needs to relaunch)";
+locale["preferences[9]"] = "Flash Taskbar on new message";
+locale["preferences[10]"] = "Bounce Dock on new message";
+locale["preferences[11]"] = "Service bar location";
+locale["preferences[12]"] = "Default service to display when Rambox starts";
+locale["preferences[13]"] = "Display behaviour";
+locale["preferences[14]"] = "Show in Taskbar";
+locale["preferences[15]"] = "Show Tray Icon";
+locale["preferences[16]"] = "Show in Taskbar and Tray Icon";
+locale["preferences[17]"] = "When closing the main window";
+locale["preferences[18]"] = "Keep in tray";
+locale["preferences[19]"] = "Keep in tray and/or taskbar";
+locale["preferences[20]"] = "Quit";
+locale["preferences[21]"] = "Always on top";
+locale["preferences[22]"] = "Show System Tray indicator on unread messages";
+locale["preferences[23]"] = "Disable Hardware Acceleration (needs to relaunch)";
+locale["preferences[24]"] = "Master Password - Ask for password on startup";
+locale["preferences[25]"] = "Password";
+locale["preferences[26]"] = "Repeat Password";
+locale["preferences[27]"] =
+ "Send anonymous usage statistics to help us improve Rambox (needs to relaunch)";
+locale["preferences[28]"] = "Hide service bar labels (requires restart)";
+locale["preferences[29]"] =
+ "Enable global dark theme (Darkreader). Needs relaunch to apply for service tabs.";
+locale["button[0]"] = "Ok";
+locale["button[1]"] = "Cancel";
+locale["button[2]"] = "Yes";
+locale["button[3]"] = "No";
+locale["button[4]"] = "Save";
+locale["main.dialog[0]"] = "Certification Error";
+locale["main.dialog[1]"] =
+ "The service with the following URL has an invalid authority certification.";
+locale["main.dialog[2]"] = "You have to remove the service and add it again";
+locale["menu.help[0]"] = "Visit Rambox Website";
+locale["menu.help[1]"] = "Report an Issue...";
+locale["menu.help[2]"] = "Ask for Help";
+locale["menu.help[3]"] = "Donate";
+locale["menu.help[4]"] = "Help";
+locale["menu.edit[0]"] = "Edit";
+locale["menu.edit[1]"] = "Undo";
+locale["menu.edit[2]"] = "Redo";
+locale["menu.edit[3]"] = "Cut";
+locale["menu.edit[4]"] = "Copy";
+locale["menu.edit[5]"] = "Paste";
+locale["menu.edit[6]"] = "Select All";
+locale["menu.view[0]"] = "View";
+locale["menu.view[1]"] = "Reload";
+locale["menu.view[2]"] = "Toggle Full Screen";
+locale["menu.view[3]"] = "Toggle Developer Tools";
+locale["menu.window[0]"] = "Window";
+locale["menu.window[1]"] = "Minimize";
+locale["menu.window[2]"] = "Close";
+locale["menu.window[3]"] = "Always on top";
+locale["menu.help[5]"] = "Check for updates...";
+locale["menu.help[6]"] = "About Rambox";
+locale["menu.osx[0]"] = "Services";
+locale["menu.osx[1]"] = "Hide Rambox";
+locale["menu.osx[2]"] = "Hide Others";
+locale["menu.osx[3]"] = "Show All";
+locale["menu.file[0]"] = "File";
+locale["menu.file[1]"] = "Quit Rambox";
+locale["tray[0]"] = "Show/Hide Window";
+locale["tray[1]"] = "Quit";
+locale["services[0]"] =
+ "WhatsApp is a cross-platform mobile messaging app for iPhone, BlackBerry, Android, Windows Phone and Nokia. Send text, video, images, audio for free.";
+locale["services[1]"] =
+ "Slack brings all your communication together in one place. It’s real-time messaging, archiving and search for modern teams.";
+locale["services[2]"] =
+ "Noysi is a communication tool for teams where privacy is guaranteed. With Noysi you can access all your conversations and files in seconds from anywhere and unlimited.";
+locale["services[3]"] =
+ "Instantly reach the people in your life for free. Messenger is just like texting, but you don't have to pay for every message.";
+locale["services[4]"] =
+ "Stay in touch with family and friends for free. Get international calling, free online calls and Skype for Business on desktop and mobile.";
+locale["services[5]"] =
+ "Hangouts bring conversations to life with photos, emoji, and even group video calls for free. Connect with friends across computers, Android, and Apple devices.";
+locale["services[6]"] =
+ "HipChat is hosted group chat and video chat built for teams. Supercharge real-time collaboration with persistent chat rooms, file sharing, and screen sharing.";
+locale["services[7]"] =
+ "Telegram is a messaging app with a focus on speed and security. It’s super-fast, simple, secure and free.";
+locale["services[8]"] =
+ "WeChat is a free messaging calling app that allows you to easily connect with family; friends across countries. It’s the all-in-one communications app for free text (SMS/MMS), voice; video calls, moments, photo sharing, and games.";
+locale["services[9]"] =
+ "Gmail, Google's free email service, is one of the world's most popular email programs.";
+locale["services[10]"] =
+ "Inbox by Gmail is a new app from the Gmail team. Inbox is an organized place to get things done and get back to what matters. Bundles keep emails organized.";
+locale["services[11]"] =
+ "ChatWork is a group chat app for business. Secure messaging, video chat, task management and file sharing. Real-time communication and increase productivity for teams.";
+locale["services[12]"] =
+ "GroupMe brings group text messaging to every phone. Group message with the people in your life that are important to you.";
+locale["services[13]"] =
+ "The world's most advanced team chat meets enterprise search.";
+locale["services[14]"] =
+ "Gitter is built on top of GitHub and is tightly integrated with your organizations, repositories, issues and activity.";
+locale["services[15]"] =
+ "Steam is a digital distribution platform developed by Valve Corporation offering digital rights management (DRM), multiplayer gaming and social networking services.";
+locale["services[16]"] =
+ "Step up your game with a modern voice & text chat app. Crystal clear voice, multiple server and channel support, mobile apps, and more.";
+locale["services[17]"] =
+ "Take control. Do more. Outlook is the free email and calendar service that helps you stay on top of what matters and get things done.";
+locale["services[18]"] = "Outlook for Business";
+locale["services[19]"] =
+ "Web-based email service offered by the American company Yahoo!. The service is free for personal use, and paid-for business email plans are available.";
+locale["services[20]"] =
+ "Free and web-based encrypted email service founded in 2013 at the CERN research facility. ProtonMail is designed as a zero-knowledge system, using client-side encryption to protect emails and user data before they are sent to ProtonMail servers, in contrast to other common webmail services such as Gmail and Hotmail.";
+locale["services[21]"] =
+ "Tutanota is an open-source end-to-end encrypted email software and freemium hosted secure email service based on this software.";
+locale["services[22]"] =
+ "versions of service. Hushmail uses OpenPGP standards and the source is available for download.";
+locale["services[23]"] =
+ "Collaborative email and threaded group chat for productive teams. A single app for all your internal and external communication.";
+locale["services[24]"] =
+ "From group messages and video calls all the way to helpdesk killer features our goal is to become the number one cross-platform open source chat solution.";
+locale["services[25]"] =
+ "HD quality calls, private and group chats with inline photos, music and video. Also available for your phone or tablet.";
+locale["services[26]"] =
+ "Sync is a business chat tool that will boost productivity for your team.";
+locale["services[27]"] = "No description...";
+locale["services[28]"] =
+ "Allows you to instant message with anyone on the Yahoo server. Tells you when you get mail, and gives stock quotes.";
+locale["services[29]"] =
+ "Voxer is a messaging app for your smartphone with live voice (like a PTT walkie talkie), text, photo and location sharing.";
+locale["services[30]"] =
+ "Dasher lets you say what you really want with pics, GIFs, links and more. Take a poll to find out what your friends really think of your new boo.";
+locale["services[31]"] =
+ "Flowdock is your team's chat with a shared inbox. Teams using Flowdock stay up-to-date, react in seconds instead of days, and never forget anything.";
+locale["services[32]"] =
+ "Mattermost is an open source, self-hosted Slack-alternative. As an alternative to proprietary SaaS messaging, Mattermost brings all your team communication into one place, making it searchable and accessible anywhere.";
+locale["services[33]"] =
+ "DingTalk is a multi-sided platform empowers small and medium-sized business to communicate effectively.";
+locale["services[34]"] =
+ "The mysms family of applications helps you text anywhere and enhances your messaging experience on your smartphone, tablet and computer.";
+locale["services[35]"] =
+ "ICQ is an open source instant messaging computer program that was first developed and popularized.";
+locale["services[36]"] =
+ "TweetDeck is a social media dashboard application for management of Twitter accounts.";
+locale["services[37]"] = "Custom Service";
+locale["services[38]"] = "Add a custom service if is not listed above.";
+locale["services[39]"] =
+ "Zinc is a secure communication app for mobile workers, with text, voice, video, file sharing and more.";
+locale["services[40]"] =
+ "Freenode, formerly known as Open Projects Network, is an IRC network used to discuss peer-directed projects.";
+locale["services[41]"] =
+ "Text from your computer, sync'd with your Android phone & number.";
+locale["services[42]"] =
+ "Free and open source webmail software for the masses, written in PHP.";
+locale["services[43]"] = "Horde is a free and open source web-based groupware.";
+locale["services[44]"] =
+ "SquirrelMail is a standards-based webmail package written in PHP.";
+locale["services[45]"] =
+ "Ad-free business Email Hosting with a clean, minimalist interface. Integrated Calendar, Contacts, Notes, Tasks apps.";
+locale["services[46]"] =
+ "Zoho chat is a secure and scalable real-time communication and collaboration platform for teams to improve their productivity.";
+module.exports = locale;