Compare commits

...

548 Commits

Author SHA1 Message Date
Ramiro Saenz eaa33fc8f3
EOL: Thank you, thank you, thank you, thank you 3 years ago
Ramiro Saenz 0669dafde5 EOL: Thank you, thank you, thank you, thank you 3 years ago
Ramiro Saenz 78acfeed42 Update .travis.yml 3 years ago
Ramiro Saenz f9e9a547bd Update appveyor.yml 3 years ago
Ramiro Saenz 02aa8ce840 Update appveyor.yml 3 years ago
Ramiro Saenz 6c31dcce1d Update appveyor.yml 3 years ago
Ramiro Saenz 7f3ecf5e1e Update appveyor.yml 3 years ago
Ramiro Saenz 287ee85067 CI fixes 3 years ago
Ramiro Saenz b7a5b39b1f
Merge pull request #3109 from KevinRoebert/master 3 years ago
Ramiro Saenz 6fcd982b46
Merge pull request #3102 from rodriguescelio/fix/screen-share 3 years ago
Kevin 5c4ee8d06a
Update package.json 3 years ago
Kevin R cb654525e0
Added Apple Silicon Support 3 years ago
Ramiro Saenz 1eebe2445f
Removed invitation to Slack 4 years ago
Celio Rodrigues 4a79697487 Fixed the screenshare capability 4 years ago
Ramiro Saenz 84a8f20bbc Versioning 4 years ago
Ramiro Saenz 04413c81eb Fixed exit on Master Password screen 4 years ago
Ramiro Saenz 1605ec5ebd Temporary fix to load Twitter and other websites inside webviews 4 years ago
Ramiro Saenz 6f4f33d53d Minor fixes 4 years ago
Ramiro Saenz f3fc3c7cf0 Removed diskusage because of build problems 4 years ago
Ramiro Saenz 89d0560ed3 Update appveyor.yml 4 years ago
Ramiro Saenz cc39ed6980 Update appveyor.yml 4 years ago
Ramiro Saenz 58f53323f3 Update appveyor.yml 4 years ago
Ramiro Saenz 82a44e93fc Updated Node 4 years ago
Ramiro Saenz c91ef575e3 Updated Electron and fixed some major bugs 4 years ago
Ramiro Saenz 5e94ebf0e9
Merge pull request #2897 from mhatvan/chore/update-electron 4 years ago
Ramiro Saenz c26845662c
Merge branch 'master' into chore/update-electron 4 years ago
Ramiro Saenz 008efd5f08 Reviewed code and tested 4 years ago
Ramiro Saenz 4f0c6e9bc1
Merge pull request #2807 from Vioner/fix/#2077-stop-rambox-when-running-out-of-space 4 years ago
mhatvan e18ff5e003
chore: Update Electron (#2871) 4 years ago
Ramiro Saenz 611235aee6 Added required scope to snap 5 years ago
Ramiro Saenz a8e5a42e51 Added new permissions to Snap package 5 years ago
Ramiro Saenz 2037dbafe5 Versioning 5 years ago
Ramiro Saenz 5eed7f02fd Changed URLs for updates and services 5 years ago
Ramiro Saenz 58b5975912 Added new Google URLs to avoid security rule 5 years ago
Karol Putra f8610047eb Merge branch 'fix/#2077-stop-rambox-when-running-out-of-space' of https://github.com/Vioner/community-edition into fix/#2077-stop-rambox-when-running-out-of-space 5 years ago
Karol Putra 072997e59c Added availableSpaceWatchDog. 5 years ago
Karol Putra 4127e0a707 Added availableSpaceWatchDog 5 years ago
Ramiro Saenz e14cfdff86 Update package.json 5 years ago
Ramiro Saenz 82f70c0c89 Changed URLs 5 years ago
Ramiro Saenz 120512e386 Update electron to 7.23.4 5 years ago
Ramiro Saenz dcaa45e86f Changed publisher name 5 years ago
Ramiro Saenz 95d04aa76e Versioning 5 years ago
Ramiro Saenz 025a8fab68 Fixes #2780 5 years ago
Ramiro Saenz 18ae907bd0 Update README.md 5 years ago
Ramiro Saenz 155a7fd2a2 Fixes #2706 5 years ago
Ramiro Saenz 6e1220fbae Added Volta 5 years ago
Ramiro Saenz c0293be615 Merge branch 'master' of https://github.com/saenzramiro/rambox 5 years ago
Ramiro Saenz 03e0c3be2d
Merge pull request #2639 from Zarel/patch-3 5 years ago
Ramiro Saenz 429721393e
Merge pull request #2751 from ramboxapp/dependabot/npm_and_yarn/electron-7.2.4 5 years ago
Ramiro Saenz 813c0d4628
Merge pull request #2671 from ramboxapp/dependabot/npm_and_yarn/auth0-js-9.13.2 5 years ago
Ramiro Saenz 3048d9d28c Install exact versions of libs 5 years ago
dependabot[bot] eb88f5d8fc
Bump electron from 7.1.12 to 7.2.4 5 years ago
Vulich Fernando d4b89a48ac Fix Do Not Disturb Tooltip 5 years ago
dependabot[bot] 02c0c549ce
Bump auth0-js from 9.7.3 to 9.13.2 5 years ago
Vulich Fernando ef2a2a9f15
Add files via upload 5 years ago
Vulich Fernando 9a5e686bb0
Add files via upload 5 years ago
Vulich Fernando 01265fdbae
Add files via upload 5 years ago
Vulich Fernando 02c8bacb2a
Add files via upload 5 years ago
Guangcong Luo c00109417f
Update repo URL in CONTRIBUTING.md 5 years ago
Vulich Fernando e01453b6a0
Merge pull request #2635 from Zarel/patch-1 5 years ago
Guangcong Luo d748323142
Update CONTRIBUTING.md with new services location 5 years ago
Vulich Fernando 7261dd10c6 Versioning 5 years ago
Vulich Fernando 10f577549a Provide option to disable auto-reload on fail 5 years ago
Vulich Fernando bec9bae9b9 Fix: Blue screen after getting the backup from Auth0 5 years ago
Vulich Fernando 151caa037d
Merge pull request #2621 from andia89/minimized 5 years ago
andreas 2185f32dd8 Adds requested changes for start minimized 5 years ago
Ramiro Saenz 168eacb2fe Added script for notarization 5 years ago
Ramiro Saenz 9166c49aae Fixed camera and mic permissions prompt 5 years ago
Ramiro Saenz 3326447d0f
Merge pull request #2628 from ramboxapp/0.7.4 5 years ago
Ramiro Saenz 313b29cd00 Versioning 5 years ago
Ramiro Saenz 7a3e4b1e6a Notarization of MacOS app 5 years ago
Ramiro Saenz 2ae71facd5 Grant camera/microphone permission to macOS Catalina 5 years ago
Vulich Fernando 4dd81ccf74 URL Regex update 5 years ago
Vulich Fernando 3937f43ffe Electron 7.1.12 5 years ago
Vulich Fernando fb1ab0dae5
Merge pull request #2623 from BKPepe/fix_readme 5 years ago
Josef Schlehofer 66f16e465d
Drop Table of Contents from menu 5 years ago
Josef Schlehofer 7d63ba374e
Fix Services available in Table of Contents 5 years ago
andreas e4f6746b28 Fixes start miniized 5 years ago
Vulich Fernando 634989427d Get the services list from Github 5 years ago
Vulich Fernando 14ab68acd7 Reload service when fail at loading 5 years ago
Vulich Fernando 7947cc20dd Grant camera/microphone permission to macOS Catalina 5 years ago
Vulich Fernando 78e86721f4 Bump to electron 7.1.12 5 years ago
Vulich Fernando 1a5ff9c8d1 Improvement of the fix for Google login issues 5 years ago
Vulich Fernando 55351f6f72 Versioning to 0.7.3 5 years ago
Vulich Fernando 83e7fd38d6 Fix: Google login issue "You are trying to sign in from a browser or app that doesn't allow us to keep your account secure" 5 years ago
Vulich Fernando ad0f70ab34 Fix Keyboard shortcuts for switching apps do not focus the app 5 years ago
Vulich Fernando 54747e8719 Fix: Services aren't editable due broken URL validation 5 years ago
Vulich Fernando c309c0f385 Change Mac DND shortcut to Cmd+Alt+D 5 years ago
Vulich Fernando 906c997ccb Fix Copy/Paste READY READY READY READY 5 years ago
Vulich Fernando 18e5794724 Versioning to 0.7.2 6 years ago
Vulich Fernando 30d93831df Fix: Skype not loading and issues with badges and notifications 6 years ago
Ramiro Saenz 48e4e9f627
Update FUNDING.yml 6 years ago
Vulich Fernando 748b1857d8 Minor fixes 6 years ago
Vulich Fernando 51e5ad8858 Versioning to 0.7.1 6 years ago
Vulich Fernando 4b8962c753
Update README.md 6 years ago
Vulich Fernando 4ad7edc4ea Fix: shortcuts interferes with Chrome/Safari/Firefox 6 years ago
Vulich Fernando 44cb534e18
Merge pull request #2453 from StormPooper/patch-1 6 years ago
Daniel Smith f3a064a237
Update DND and Lock shortcut prompts 6 years ago
Vulich Fernando 18e1ed0809 Minor focus fix 6 years ago
Vulich Fernando 7cf83a695f Fix: Rambox stays on the master password window 6 years ago
Vulich Fernando 8992c2cdda Fix Cmd+number tab changing in MacOs 6 years ago
Vulich Fernando 1f5f966e06 minor CSS fix 6 years ago
Ramiro Saenz 1874c3b900
Update .travis.yml 6 years ago
Vulich Fernando b73c7f0444 Remove unused Icons 6 years ago
Vulich Fernando 0aebff3cbb Code Cleaning 6 years ago
Vulich Fernando a5f158ecad Fix: Linux build failure 6 years ago
Vulich Fernando e1344ea05b Get Services remotely and Bump Electron to 7.1.1 6 years ago
Vulich Fernando 0ae49f55fa
Merge pull request #2409 from jcherniak/gv-update-sept-2019 6 years ago
Vulich Fernando fccf9646ac Change Regex to validate services URLs 6 years ago
Vulich Fernando ecbea2e944 Fix:Window doesn't restore from Tray in Linux 6 years ago
Vulich Fernando 8456831acc Zoom: fixes and improvements 6 years ago
Vulich Fernando 28080c10bc Change Shortcuts for DND and LockRambox 6 years ago
Vulich Fernando 55d957d5af Add Unread code to Teams 6 years ago
Vulich Fernando df66ae160a Fix: Webview is no longer focused when switching tabs 6 years ago
Vulich Fernando 7384c17c9f Fix: Fast switching with Command+1/2/3/etc. does not work 6 years ago
Vulich Fernando 1723b2472f Fix: Cursor missing 6 years ago
Vulich Fernando 5454c07f46 Logo: update Teams, Outlook and Outlook365 6 years ago
Vulich Fernando 8226efaf30
Merge pull request #2415 from ash14/fix/slack-icon 6 years ago
Vulich Fernando 7654d4ac47
Merge pull request #2379 from StormPooper/feature/update-mastodon-logo 6 years ago
Vulich Fernando 2de8e8e41b
Merge pull request #2370 from Lomanic/fix/ms-teams-blank-page 6 years ago
Vulich Fernando 41977ea554 Update: Unread Code Outlook 6 years ago
Ashvin 983b489d52
Update Slack icon fetching script 6 years ago
Justin Cherniak fbbb1b73eb Fix Google Voice unread count for September 2019 updates 6 years ago
Ramiro Saenz 76939cbc3e
Create FUNDING.yml 6 years ago
Daniel Smith f3b2c943ac Update to use official logo instead of unused favicon from PDF 6 years ago
Daniel Smith ef7afecb80 Update Mastodon logo 6 years ago
Lomanic 42be7f3a1f Fix MS Teams blank page 6 years ago
Juan Manuel Gonzalez Alama 516fa1c1b7 Update ServicesList.js 6 years ago
Juan Manuel Gonzalez Alama 5658ee5c33 Update ServicesList.js 6 years ago
Ramiro Saenz e82a945a72
Update README.md 6 years ago
Ramiro Saenz 8d509c4bca Merge branch 'master' of https://github.com/saenzramiro/rambox 6 years ago
Ramiro Saenz a5716b76c3
Merge pull request #2310 from mwohlert/feature/add-aws-workmail 6 years ago
Ramiro Saenz 0b8306d6a5 Versioning 6 years ago
Michel Wohlert 40fca201e8 Add AWS WorkMail Service 6 years ago
Juan Manuel Gonzalez Alama 51b4be02d6 Update updater.js 6 years ago
Ramiro Saenz 90f93202c4 Versioning 6 years ago
Ramiro Saenz 4e7ebdf175 Added new languages 6 years ago
Juan Manuel Gonzalez Alama 2af377c60c Merge branch 'master' of https://github.com/saenzramiro/rambox 6 years ago
Juan Manuel Gonzalez Alama 8687b2486d Update ServicesList.js 6 years ago
Ramiro Saenz 2bdd4ed07e
Update README.md 6 years ago
Juan Manuel Gonzalez Alama ef015d60c6 Update ServicesList.js 6 years ago
Juan Manuel Gonzalez Alama d619a66a99 Update ServicesList.js 6 years ago
Juan Manuel Gonzalez Alama e8c664be1c Update ServicesList.js 6 years ago
Juan Manuel Gonzalez Alama 9b344beb46 Fix Whatsapp counter 6 years ago
Juan Manuel Gonzalez Alama aa1d051b8f Update MainController.js 6 years ago
Juan Manuel Gonzalez Alama 6fd77c45e8 Disable "Remove All" if there are no services 6 years ago
Juan Manuel Gonzalez Alama b191445926 Update MainController.js 6 years ago
Juan Manuel Gonzalez Alama 6b1fb166a3 Fixed minimize behavior 6 years ago
Ramiro Saenz 810f9b9688
Update stale.yml 6 years ago
Ramiro Saenz ca7693bf84 Enable opening links in Skype 6 years ago
Ramiro Saenz c725d1984b Fixed bug on macOS when restart app on new version 6 years ago
Ramiro Saenz c61e3b7475 Versioning 6 years ago
Ramiro Saenz 8a53e4fac5 Prevent to block main process 6 years ago
Ramiro Saenz 6f382d9663
Merge pull request #2232 from maxerbox/allow-to-disable-no-connection-message 6 years ago
Ramiro Saenz 2c8d7452c5 🎪 6 years ago
mxb e27fc8d83f Dialog is always on top, and changed the way we check internet connection 6 years ago
mxb 3f3b9e66ee Added is-online package 6 years ago
Ramiro Saenz 90ccdc27cc
Merge pull request #2227 from maxerbox/fixed-snap-configuration 6 years ago
Ramiro Saenz 67164bab1e
Merge pull request #2229 from maxerbox/fixed-input-proxy-password 6 years ago
Ramiro Saenz 956ff0377e Identation 6 years ago
Ramiro Saenz 7752c37a01
Merge pull request #2230 from maxerbox/fix-input-bypass-lock 6 years ago
Ramiro Saenz 819c625f93
Merge pull request #2231 from maxerbox/fix-copy-past-not-working-master-password-field 6 years ago
Ramiro Saenz 086ceba908 Minor bug 6 years ago
Ramiro Saenz fe9056105a Improved search text feature 6 years ago
Ramiro Saenz dbeab3f95c Merge branch 'master' of https://github.com/saenzramiro/rambox 6 years ago
Ramiro Saenz 0446c9cae3 Display tabbar gray on Do Not Disturb enabled 6 years ago
Ramiro Saenz 4b0c54f7fc Fixed unread bug on window closed and keep in tray 6 years ago
Ramiro Saenz e00c86ef57 Fixed minor bug 6 years ago
Ramiro Saenz 3b8dbfef8b Added Google Duo 6 years ago
mxb 587947f867 Rewrittend the function 6 years ago
mxb 6dd7984e6d Added new message: sConfig 6 years ago
mxb 4877920787 Added handlePaste function 6 years ago
mxb 8f30ec7b8d Added script fix 6 years ago
mxb e3542d411d Set inputType as password 6 years ago
mxb 9ba564c713 Improved list 6 years ago
mxb 67b50b54ca Added camera plug 6 years ago
Juan Manuel Gonzalez Alama d4d7c4b49e
Merge pull request #2219 from maxerbox/fix-locale-language 6 years ago
Juan Manuel Gonzalez Alama 874d79e76c Update main.js 6 years ago
Juan Manuel Gonzalez Alama e664792072
Merge pull request #2223 from maxerbox/Added-search-feature 6 years ago
Juan Manuel Gonzalez Alama c961e594a5 Code review 6 years ago
mxb 93580405fc Added search feature 6 years ago
mxb 8e19c59170 Updated regular expressions for user agent 6 years ago
mxb 7bdd0a0a97 Allow to send accept language header to websites, according to settings 6 years ago
Ramiro Saenz c74bb72c7d Fixed error on save preferences 6 years ago
Ramiro Saenz e0917cb1d0 Versioning 6 years ago
Ramiro Saenz b1adbc4d25 Removed Rambox in User Agent in production 6 years ago
Ramiro Saenz 3a4e318a4f Updated electron-builder and electron-updater 6 years ago
Ramiro Saenz ecaf73835b Fixed security vulnerabilities 6 years ago
Ramiro Saenz 83d4c5cbb4
Merge pull request #2195 from nopticon/fix/allow-more-than-25-services 6 years ago
Ramiro Saenz 981dbdc445 Added more visual style when the app is in DO NOT DISTURB 6 years ago
Ramiro Saenz 9142b11928
Merge pull request #2205 from maxerbox/fix-invalid-version-whatsapp 6 years ago
Ramiro Saenz 15b2533c65
Merge pull request #2206 from maxerbox/fix-electron-issue-key-propragation 6 years ago
Ramiro Saenz f59b518e58 Minor adjustment 6 years ago
Ramiro Saenz bc844f47a0 Merge branch 'master' of https://github.com/saenzramiro/rambox 6 years ago
Ramiro Saenz 57b2c4e7b9 Use vanilla JS to detect unread code in Slack 6 years ago
mxb f9b24f1761 Closes #2191 6 years ago
mxb 106621efcc Fix issue with electron before-input-event 6 years ago
mxb aefcfa80fc Removed user agent 6 years ago
mxb 4b35ecbd25 Removed electron from user agent, because whatsapp user agent parsing server side is poorly functional 6 years ago
Guillermo Azurdia 26f65b3c05
Fix issue when adding more than 25 services. 6 years ago
Ramiro Saenz 61af48511d Updated to Electron 4.1.4 6 years ago
Ramiro Saenz 86cfd302d1 Temp fix missing cursor after upgrade to electron 3.x + 6 years ago
Ramiro Saenz d2a0170fda Removed Dasher 6 years ago
Ramiro Saenz f0159e3c02 Prevent execute AutoLaunch on dev 6 years ago
Ramiro Saenz f07625a04e typo 6 years ago
Ramiro Saenz 3886b03acf Removed Google Allo 6 years ago
Ramiro Saenz 3bfb040969 Fixed right click / context menu 6 years ago
Ramiro Saenz eaf9dff537 Changed Gmail unread code to read also from tabs like Promotions,etc 6 years ago
Ramiro Saenz 37768b9c36 Options menu does not adapt to screen 6 years ago
Ramiro Saenz 51bdce2715
Merge pull request #2034 from maxerbox/patch-4 6 years ago
Ramiro Saenz c407ecc685
Merge pull request #2050 from arthur-fr/googlecalendar 6 years ago
Ramiro Saenz 394a1debd2
Merge pull request #2055 from maxerbox/patch-5 6 years ago
Ramiro Saenz 44836bd5b8 Update languages 6 years ago
Ramiro Saenz 3168c35b46 Merge branch 'master' of https://github.com/saenzramiro/rambox 6 years ago
Ramiro Saenz 3318e39cb5
Merge pull request #2144 from bertyhell/pr/2101-hide-service-labels 6 years ago
Ramiro Saenz 0c4875ab1a Updated Electron to 4.1.1 6 years ago
Ramiro Saenz 9a4ec26997
Merge pull request #2160 from bartekczyz/master 6 years ago
Ramiro Saenz c406af2f82 Add UserAgent to WhatsApp 6 years ago
Ramiro Saenz e615605342 Versioning 6 years ago
Ramiro Saenz b89c8a0f98
Fix AZERTY Ctrl Z and Ctrl W 6 years ago
Ramiro Saenz e32bcce9d1
Update WebView.js 6 years ago
mxb fdd1ae30f6 Put keycode at the top 6 years ago
Simon Sassi b844524ee3
Merge pull request #2138 from maxerbox/fix-electron-webview-event-not-propaggaded 6 years ago
Simon Sassi 942730b90a
Merge pull request #2086 from aleeks/update-slack-logo 6 years ago
Simon Sassi 4fdabe4055
Merge pull request #2099 from dgoltzsche/update-riot-logo 6 years ago
Simon Sassi 99c29e8994
Merge pull request #2145 from bertyhell/patch-1 6 years ago
Simon Sassi fca5efa6c0
Merge pull request #2139 from maxerbox/fix/invalid-user-agents 6 years ago
Simon Sassi c32bdb9c58
Merge pull request #2078 from mxmehl/patch-1 6 years ago
mxb a4f5ec66d3 Replaced keycode to keycodes, better lib 6 years ago
Bartek Czyż 1376383050 Allow mainWindow to be undefined 6 years ago
Bert Verhelst 8114c44276 Set hide_tabbar_labels default to false 6 years ago
Bert Verhelst a897769a54
Update sencha required version to 6.6.0.13 6 years ago
Bert Verhelst d726ed0b23 feat: #2101 Add option to hide tabbar labels 6 years ago
Vulich Fernando 20fd553a36 Update Crisp URL 6 years ago
mxb 5086880fac Removed list of invalid user agents 6 years ago
mxb d71fc7b177 Now directly handling key events from webview 6 years ago
mxb 5807007e48 Simply allowing keyMap to be accessed from everywhere 6 years ago
mxb 7ee9e1c2ef Simply allowing keyMap to be accessed from eveywhere 6 years ago
mxb 837aeb240f Added keycode to package.json 6 years ago
Simon Sassi 87b60ad296
Merge branch 'master' into patch-5 6 years ago
Ramiro Saenz 37381a0312
Update package.json 6 years ago
Ramiro Saenz 8c07f419bc
Merge pull request #2124 from maxerbox/fix/discord-unread_js 6 years ago
Ramiro Saenz 16e8323799
Merge pull request #2111 from maxerbox/fix/electron-update-3.1.3 6 years ago
mxb 086e5d2a77 Fix unread js for discord dm count 6 years ago
mxb 382c382bca Updated electron version 6 years ago
mxb 5941ba18ae did-get-redirect-request events removed 6 years ago
mxb 380dff555f Replaced makeSingleInstance method, deprecated 6 years ago
David Goltzsche b689833f29 Update Riot logo 6 years ago
Alex Sampaio de9f191d5e Logo: update slack logo resources 6 years ago
Max 832fa4d19a
Fix links to new Github org 6 years ago
Simon Sassi 768eaede43
Fixed external link opening 6 years ago
@rthur 6dac82ea62 Added Google Calendar 6 years ago
Simon Sassi 921fc80447
Unscaped espaced json character xD 6 years ago
Simon Sassi 8a240df1da
Escaped json special characters 6 years ago
Simon Sassi 65f5699bb8
Edited gmail notification check 6 years ago
Ramiro Saenz f0182d9355 Removed migration tool 6 years ago
Ramiro Saenz 0f846b90f2 Update pt-BR.js 6 years ago
Ramiro Saenz e160a3da30 Versioning 6 years ago
Ramiro Saenz 9c0f13dc1e Bypass WhatsApp minimum requirement 6 years ago
Ramiro Saenz c73407c692 Changed DND icon on toggle 6 years ago
Ramiro Saenz f5c15ee6db
Merge pull request #1916 from brad/teams-video 6 years ago
Ramiro Saenz 63b3b414af
Merge pull request #1632 from ozskywalker/feature/user-agent-control 6 years ago
Ramiro Saenz 211f2ba5d3
Merge pull request #1923 from vraravam/npm-audit-fix 6 years ago
Ramiro Saenz 1c7f834c42
Merge pull request #1977 from chojpsh1/hajeong 6 years ago
Ramiro Saenz 1feca8d954
Merge pull request #1988 from noerw/fix/mattermost-unread 6 years ago
Ramiro Saenz 92a9a93f4a Bypass WhatsApp minimum requirement 6 years ago
Ramiro Saenz bd6137b5d9 Updated Electron to 2.0.14 6 years ago
Ramiro Saenz 2416494879 Changed category 6 years ago
Norwin Roosen a0eb32194d mattermost: show "•" instead of number for unread channels 6 years ago
Norwin Roosen 4dada56df5 fix mattermost unread count JS 6 years ago
chojpsh1 17066c2df0 change disturb icon via state of button press 7 years ago
brad d7818ac153
fix #1292, fix #1829 enable video chat in ms teams 7 years ago
brad 697b8192b9
Revert "fix #1292, fix #1829 enable video chat in ms teams" 7 years ago
Ramiro Saenz fb05993719
Bots 7 years ago
Ramiro Saenz 15286628ba
Update lock.yml 7 years ago
Ramiro Saenz 1079fc575b
Bot 7 years ago
Ramiro Saenz 9e11d4e8af
Bot 7 years ago
Ramiro Saenz 514ca6411a
Bot 7 years ago
Vijay Raghavan Aravamudhan 3b2e7eb78f Fixing issues reported by npm audit. 7 years ago
brad 248fad7b2a
fix #1292, fix #1829 enable video chat in ms teams 7 years ago
Ramiro Saenz 781534545e Merge branch 'master' of https://github.com/saenzramiro/rambox 7 years ago
Ramiro Saenz 6b3166e905 Fixed Slack icon 7 years ago
Ramiro Saenz 0ff76ef982
Merge pull request #971 from qoheniac/patch-1 7 years ago
Ramiro Saenz 770a8412fb Changed all unread to use "rambox" class 7 years ago
Ramiro Saenz 0da6a1b0ca Fixed Riot unread counter 7 years ago
Ramiro Saenz 4873d33ccc Fixed Mattermost unread counter 7 years ago
Ramiro Saenz d92a47d260 Versioning 7 years ago
Ramiro Saenz fe93b6c686 typo 7 years ago
Ramiro Saenz fc18d5c26f
Merge pull request #1857 from maxerbox/patch-1 7 years ago
Ramiro Saenz fdebe61717 Merge branch 'master' of https://github.com/saenzramiro/rambox 7 years ago
Ramiro Saenz 9dcf54b11e
Merge pull request #1858 from maxerbox/patch-2 7 years ago
Ramiro Saenz 38e9ac6a3a Removed unused params 7 years ago
Ramiro Saenz f8fd898c17
Merge pull request #1863 from cseas/master 7 years ago
Ramiro Saenz 73f4e1fb90
Merge pull request #1864 from maxerbox/patch-3 7 years ago
Ramiro Saenz 252c17b7f6 ✌️ 7 years ago
Ramiro Saenz bc8dd7b12d Fixed backup-restore configuration 7 years ago
Ramiro Saenz b8f03be07f
Update README.md 7 years ago
Ramiro Saenz 5167800590
Update README.md 7 years ago
Ramiro Saenz 423f572c56 Versioning 7 years ago
Ramiro Saenz 2c12ed2805 Fixed context menu on apps 7 years ago
Ramiro Saenz 2a47cbaba1 Fixed backup and restore configuration 7 years ago
Ramiro Saenz 124988382d Show downloaded version on update 7 years ago
Ramiro Saenz 96cd6c5f19 Remove unused packages 7 years ago
Ramiro Saenz 1cb4b068f2 Enable autoUpdate for all platforms 7 years ago
Ramiro Saenz 36f27d076e ✌️ 7 years ago
Ramiro Saenz 18737dee08 ✌️ 7 years ago
Ramiro Saenz 4eb3c114b1 Update CI steps 7 years ago
Ramiro Saenz 0fee18bfd2 Changed appID 7 years ago
Ramiro Saenz 7dd69a1f89 Added autoUpdate for Mac 7 years ago
Ramiro Saenz efb3e686d6 Removed Squirrel handle 7 years ago
Ramiro Saenz c868be96a6 Added description 7 years ago
Ramiro Saenz fd1b833266 Changed new repo URL 7 years ago
Ramiro Saenz ea6d542223 Added new updater and custom NSIS installer 7 years ago
Ramiro Saenz 7958b8dc1d 🐾 7 years ago
Ramiro Saenz fb3cefe6e6 🐾 7 years ago
Ramiro Saenz f62e61e89a 🐾 7 years ago
Ramiro Saenz 9b29149e60 🐾 7 years ago
Ramiro Saenz d2b83a6bc5 Ups 7 years ago
Ramiro Saenz 6dea43d052 Improved AppVeyor 7 years ago
Ramiro Saenz 2774981f42 Updates 7 years ago
Ramiro Saenz e6bbd5ea18 More updates 7 years ago
Ramiro Saenz 08430440ff 🎷 7 years ago
Ramiro Saenz 6bd487eb1d Removed dual package.json used for old electron-builder 7 years ago
Ramiro Saenz 4413928fe3 Added electron-updater 7 years ago
Ramiro Saenz 9542213c58 Prevent bug "window.close" related with Electron 7 years ago
Ramiro Saenz 093a29f344 Improved taskbar badge and system tray icon 7 years ago
Ramiro Saenz b5c6b0e9bd Versioning 7 years ago
Ramiro Saenz dc792f5e31 🐶 7 years ago
Ramiro Saenz 35c0ac9e1f Changed to electron-updater for auto updates 7 years ago
Ramiro Saenz af5fd12158 Change donation link 7 years ago
Ramiro Saenz dc5cde7208 💫 7 years ago
Simon Sassi 74b93b6cc0
Update rambox-service-api.js 7 years ago
Simon Sassi 9e3573b987
Fixed issue whith gmail and notifications 7 years ago
Abhijeet Singh 32141e7306
Fixed title for services available in index 7 years ago
Abhijeet Singh 1459e650b1
Fixed index link for services available 7 years ago
Ramiro Saenz ed01d3a5af 💎 7 years ago
Ramiro Saenz e1eddcc942 Some improves 7 years ago
Ramiro Saenz 89070dea64 Added timeStamp server for codeSign 7 years ago
Ramiro Saenz 2707011fb5 Removed deploy 7 years ago
Ramiro Saenz e24f7f21e5 CI 7 years ago
Ramiro Saenz 7cb44e4f35 Code signing 7 years ago
Ramiro Saenz bae5b12af9 Some configurations 7 years ago
Ramiro Saenz aa9031eb85 Test 7 years ago
Ramiro Saenz b8556faaca Test 7 years ago
Ramiro Saenz 3575f5c741 Test 7 years ago
Ramiro Saenz 29e40e3a34 Test 7 years ago
Ramiro Saenz 634abf6f5e Test 7 years ago
Ramiro Saenz fe60ce3800 Travis test 7 years ago
Ramiro Saenz 0415054044 Travis test 7 years ago
Ramiro Saenz 7cf7ffadd2 Travis test 7 years ago
Ramiro Saenz 2307a5afb5 Travis test 7 years ago
Ramiro Saenz 900ec57fef Travis test 7 years ago
Ramiro Saenz a2e22a1291 Travis test 7 years ago
Ramiro Saenz fa7ac3320f Travis test 7 years ago
Ramiro Saenz 26041a2298 Travis test 7 years ago
Ramiro Saenz eab78e39e3 Travis test 7 years ago
Ramiro Saenz c088bca116 Travis test 7 years ago
Ramiro Saenz dc687aa6b6 Travis test 7 years ago
Ramiro Saenz 61b31aff0c Travis test 7 years ago
Ramiro Saenz e4b844b229 Travis test 7 years ago
Ramiro Saenz 09d87993e2 Travis test 7 years ago
Simon Sassi 6c4d4fe268
Fixed double quote escaping 7 years ago
Simon Sassi 76ca900b0e
Updated google js_unread in order to be compatible 7 years ago
Simon Sassi ab8ccd7151
Changed js_unread function for service discord 7 years ago
Ramiro Saenz 1d5b93a9bb 🎰 7 years ago
Ramiro Saenz c97f800000 🎰 7 years ago
Ramiro Saenz b4e2f235aa Added "Try Rambox Pro" button 7 years ago
Ramiro Saenz f37a0d178f 🎰 7 years ago
Ramiro Saenz 60e5b62842 🎰 7 years ago
Ramiro Saenz 93b71bb21b 🎰 7 years ago
Ramiro Saenz e9f76af5da 🎰 7 years ago
Ramiro Saenz 25c748b80e 🎰 7 years ago
Ramiro Saenz f530810654 🎰 7 years ago
Ramiro Saenz 75edc8ad4b
Update README.md 7 years ago
Ramiro Saenz 6f1e49caff
Update README.md 7 years ago
Ramiro Saenz f0d2cedfac Ups 7 years ago
Ramiro Saenz f11d2d335a Renamed Zoho Chat to Zoho Cliq 7 years ago
Ramiro Saenz b2e447cd13 Merge branch 'pr/812' 7 years ago
Ramiro Saenz 798434b603
Merge pull request #1714 from Insasse/feature/#1381-outlook-de-eu-us 7 years ago
Ramiro Saenz 6071010c8f Added a note 7 years ago
Ramiro Saenz 229e2f2abe Merge branch 'pr/1853' 7 years ago
Ramiro Saenz f5b551fedd 👋 7 years ago
Álvaro Brey 87290a541b
Inbox: fix update badge function. 7 years ago
Álvaro Brey 877d057bef
Inbox: only update unread count if the current view is the Inbox view. 7 years ago
Ramiro Saenz ceb0d156e3 Removed Yahoo! Messenger 7 years ago
Ramiro Saenz 79abfcb6e6
Merge pull request #1746 from nil0x42/patch-1 7 years ago
Ramiro Saenz 3058ba5f9b Rebranded app 7 years ago
Ramiro Saenz 223e289f72
Merge pull request #1682 from JakobStruye/spark-to-webex 7 years ago
Ramiro Saenz aaf9f13b2c
Merge branch 'master' into spark-to-webex 7 years ago
Ramiro Saenz ca56909e00
Merge pull request #1655 from Faoc/fix/start-minimized 7 years ago
Ramiro Saenz 85060c54c6
Merge pull request #1661 from rzumstein/new-gmail 7 years ago
Ramiro Saenz 6c92a0c658 Added Tawkto logo 7 years ago
Ramiro Saenz 7d0f50fc1e
Merge pull request #1677 from Pmoshbr/patch-1 7 years ago
Ramiro Saenz 3068124b06
Merge branch 'master' into patch-1 7 years ago
Ramiro Saenz e7b8a41534
Merge pull request #1634 from mukkoo/patch-1 7 years ago
Ramiro Saenz c8785074da Merge branch 'pr/1704' 7 years ago
Ramiro Saenz caa09dca9d Removed old prop 7 years ago
Ramiro Saenz a5e1804807 Versioning 7 years ago
Ramiro Saenz b0ca419dc7 Merge branch 'pr/1706' 7 years ago
Ramiro Saenz 9c6b008aac Updated to Electron 2.0.8 7 years ago
Ramiro Saenz 4e2894a850
Merge pull request #1722 from iliu/fix/gmail-labs 7 years ago
Ramiro Saenz f8212597fa
Merge pull request #1744 from carlosV2/add-messages-service 7 years ago
Ramiro Saenz eee9f8c81a
Merge branch 'master' into add-messages-service 7 years ago
Ramiro Saenz c5e86f8c10 Merge branch 'pr/1759' 7 years ago
Ramiro Saenz 1bcdfa814c Merging 7 years ago
Ramiro Saenz 88fabdc836 Merge branch 'master' of https://github.com/saenzramiro/rambox 7 years ago
Ramiro Saenz f31f90f91b Fixed authentications 7 years ago
Ramiro Saenz f9820eef8f Changed repo URL 7 years ago
Ramiro Saenz 7aba401630 Updated languages 7 years ago
Ramiro Saenz 234a1c3bef Transparent background 7 years ago
Ramiro Saenz 4679ea2944 Updated libs 7 years ago
Ramiro Saenz 1cef492dc6
Update README.md 7 years ago
Ramiro Saenz c11134e6ed Merge branch 'master' of https://github.com/saenzramiro/rambox 7 years ago
Ramiro Saenz 19ab2d7c82 Disable send anonymous usage statistics by default and added option in Preferences 7 years ago
Ramiro Saenz 1fd8faf12c Updated languages and added new strings for translations 7 years ago
Ramiro Saenz a2ab4c1395
Merge pull request #1788 from dneustadt/add-devrant-service 7 years ago
Ramiro Saenz 32635003fb
Merge branch 'master' into add-devrant-service 7 years ago
Ramiro Saenz b708d120fe Merge branch 'master' of https://github.com/saenzramiro/rambox 7 years ago
Ramiro Saenz 562f4f9d9f Changed code to prevent errors in sencha compilation 7 years ago
Ramiro Saenz 26dbe266e7
Merge pull request #1773 from TheGoddessInari/tighten_security 7 years ago
Ramiro Saenz 25b193f7b5
Merge branch 'master' into tighten_security 7 years ago
Ramiro Saenz c35ec611e2 🎈 7 years ago
Ramiro Saenz f33805f00e Updated Zinc icon 7 years ago
Ramiro Saenz dec1347d96
Merge pull request #1828 from frju365/master 7 years ago
frju365 6126cd7399
[mod] Tutanota URL 7 years ago
Ramiro Saenz ee9ca07488
Merge pull request #1804 from Foggalong/master 7 years ago
Joshua H. Fogg 5cab460d56
Added Reddit icon 7 years ago
Joshua H. Fogg f188bd81c2
Added Reddit to service list 7 years ago
Ramiro Saenz 198c11ab9c
Merge pull request #1701 from saenzramiro/Ash258 7 years ago
Jakob Struye 481da04805 Setting "•" as unread count now possible from js_unread, updated Slack js_unread to do this. TODO add for other services with "•". 7 years ago
David Neustadt 0ea5e8a695 added devRant service 7 years ago
TheGoddessInari 7efe5e148e Use https everywhere. 7 years ago
TheGoddessInari 4c3781ff4f Sencha update. 7 years ago
Ramiro Saenz 6c8a877611
Merge pull request #1782 from sbol-coolblue/feature/fix-donate-link 7 years ago
Sander Bol 76d1e051fd
Fix donation link 7 years ago
TheGoddessInari 8d808207c8 Don't allow insecure content. 7 years ago
TheGoddessInari 4deb627343 Update from electron-config 0.2.1 to electron-store 2.0.0. 7 years ago
TheGoddessInari 5a1a44d589 Update to electron 2.0.5 to receive critical bugfixes (no breaking 7 years ago
TheGoddessInari 4b99bb2008 npm audit is very upset about the state of the repo, fix it. 7 years ago
TheGoddessInari e289462739 Fix ICQ's update count. Make it use the non-title update method as 7 years ago
Jakob Struye ed027cc3fa Removed the 'dont_update_from_title' flag, now updates from title iff no js_unread is set 7 years ago
Carlos Ortega c35e6bba9a Improve unread checking function 7 years ago
Carlos Ortega eb08d021b5 Replace name with Android Messages 7 years ago
Carlos Ortega ec4d9f940c Add js snippet to get the unread counter 7 years ago
nil0x42 2454c5d9cc
Add ProtonMail Onion 7 years ago
Carlos Ortega 00efb722ec Add the messages tag into the list of services 7 years ago
Carlos Ortega 566a026cc4 Add service into the services list 7 years ago
Carlos Ortega 3039f97604 Add the icon 7 years ago
Isaac Liu 3176672190 enable gmail labs 7 years ago
Insasse f7e6b06aa4 #1381 - add the ability for users to type in their top level domain 7 years ago
Jakub Čábera ccfc303316 Respec uppercase for READMEs 7 years ago
Jakub Čábera 5dd1d11a27 Respec Uppercase for Readmes 7 years ago
Jakub Čábera 0c50d3e0d3 Use direct links 7 years ago
Jakob Struye 3dca29c814 Rebranded Cisco Spark to Cisco Webex Teams 7 years ago
Ryan Zumstein d661565c25 Fix Gmail important count 7 years ago
Philip Danza Franco 7df1d01ca1
Include Tawk.to Chat service 7 years ago
rzumstein 30abb3a3c0 Show notifications in new Gmail interface 7 years ago
Jakub Čábera cd9c187ddf Icon list 7 years ago
Jakub Čábera 68c8ff8414 Icon list 7 years ago
Jakub Čábera 194f91722e Icon list 7 years ago
Jakub Čábera 6eb99a71d4 Icon list 7 years ago
Jakub Čábera a56cb94505 Icon list 7 years ago
Jakub Čábera c4c9bd856c Icon list 7 years ago
Jakub Čábera 98ef4b0af2 Icons list 7 years ago
Jakub Čábera 40968e00ea Icons list 7 years ago
Jakub Čábera 5077669309 Bypass vscode and github markdown renderer diff 7 years ago
Jakub Čábera 22e699398e Update Markdown files 7 years ago
Fabian Ochmann a9d0d25c01 Fixes not starting minimized on Linux/MacOS systems 7 years ago
Ramiro Saenz 3a4c89bd65
Merge pull request #1622 from KTOmega/left-service-bar 7 years ago
Ramiro Saenz d15d7c0efd
Merge pull request #1627 from JakobStruye/fix-fastmail-type 7 years ago
Ramiro Saenz 72c314c0bb
Merge pull request #1619 from Ash258/patch-1 7 years ago
Ramiro Saenz c6d5a6127b
Merge pull request #1643 from GarciaPL/master 7 years ago
GarciaPL 1492a84c17 Clearing password text field after inserting wrong password 7 years ago
Filippo Gangi Dino 8f2128db40
Fix selector for Ryver notifications count 7 years ago
failathon a86c584e5d Feature: Override User-Agent for all services 7 years ago
Jakob Struye 19bd2a39d2 Corrected FastMail service type from 'mail' to 'email' 7 years ago
Kevin Tran 156e9acad4 Properly reconfigure tab reorderer after redock 7 years ago
Kevin Tran 99f5855fb4 Change size of service bar preference combo box 7 years ago
Kevin Tran caf47c7051 Allow service bar to be snapped to any side 7 years ago
Kevin Tran bae36e1ddf Minor code-cosmetic changes. 7 years ago
Kevin Tran 41783e4931 Propagate config changes to view. 7 years ago
Kevin Tran a51f1bb8e4 Add orientation check for tab bar on initialize. 7 years ago
Kevin Tran 8b4a7136a3 Add the "Vertical service bar" preference. 7 years ago
Ramiro Saenz d4484d2f6d
Update README.md 7 years ago
Jakub Čábera 5442893361
Update Discord unread function 7 years ago
Ramiro Saenz 0c1407f115
Update appveyor.yml 7 years ago
Ramiro Saenz a7f6146d82
Update appveyor.yml 7 years ago
Ramiro Saenz 9c270b23a6
Update appveyor.yml 7 years ago
Ramiro Saenz 9bd240162c
Update appveyor.yml 7 years ago
Ramiro Saenz 3fd338588f
Update appveyor.yml 7 years ago
Ramiro Saenz b916be461b
Update .travis.yml 7 years ago
Ramiro Saenz 25417014fb
Update appveyor.yml 7 years ago
Ramiro Saenz ee308ba5d1
Update appveyor.yml 7 years ago
Ramiro Saenz 6051711efb
Update .travis.yml 7 years ago
Ramiro Saenz 06c0a068e8
Update .travis.yml 7 years ago
Ramiro Saenz 8119be62d2
Update .travis.yml 7 years ago
Ramiro Saenz 6400fce43e
Update .travis.yml 7 years ago
Ramiro Saenz 1752ea33e2
Update .travis.yml 7 years ago
Ramiro Saenz 62bfc21fb3
Update .travis.yml 7 years ago
Ramiro Saenz 99a514096b
Added snapcraft support 7 years ago
Ramiro Saenz 8d5e2b3040
0.5.17 7 years ago
Ramiro Saenz c099819e6f Versioning 7 years ago
Ramiro Saenz 3441ada1b0 Added NSIS support 7 years ago
Ramiro Saenz ac52ef0bad Fixed unread tray error 7 years ago
Ramiro Saenz b3506b34f9 Added Messenger for Business 7 years ago
Ramiro Saenz c30d5ca695 Snapcraft support 7 years ago
Ramiro Saenz 97481e7c8c Updated auth0-js lib 7 years ago
Ramiro Saenz e7d75bda71 Added donate button to tabbar 7 years ago
Ramiro Saenz 094957e2d8 Merge remote-tracking branch 'refs/remotes/origin/master' into 0.5.17 7 years ago
Ramiro Saenz bcaab5b8c5
Update README.md 7 years ago
Ramiro Saenz 44df038999
Delete TODO.md 7 years ago
Ramiro Saenz 80377937f5 Missing libs 7 years ago
Ramiro Saenz be6d5bd104
Merge pull request #1465 from M4urice/patch 7 years ago
Ramiro Saenz 175cba778c
Update README.md 7 years ago
Ramiro Saenz 70d2ce6ac1
Merge pull request #1472 from jacebenson/fix/contributing 7 years ago
Ramiro Saenz 2bba1287c3
Merge pull request #1531 from wolv-dev/fix/1495_gmail_refresh 7 years ago
Ramiro Saenz d0d9ae7f4a
Merge pull request #1406 from luukschakenraad/change-teamwork-url 7 years ago
Ramiro Saenz 84de33fc1d
Merge pull request #1559 from a2nt/patch-2 7 years ago
Ramiro Saenz f4ab6e4e73
Merge pull request #1523 from StephenBrown2/patch-1 7 years ago
Ramiro Saenz 2d176f2858
Update README.md 7 years ago
Ramiro Saenz d6d5420a58
Merge pull request #1539 from Ash258/patch-1 7 years ago
Ramiro Saenz 4df4b1fc94
Merge pull request #1572 from bawachhe/master 7 years ago
Ramiro Saenz 8a13e7d973
Merge pull request #1579 from qubidt/googleVoice 7 years ago
Ramiro Saenz 61fe9551ee
Merge pull request #1603 from dieresys/issue-1249 7 years ago
Ramiro Saenz be2fac6cbd
Merge pull request #1607 from rzumstein/status-bar 7 years ago
Ramiro Saenz 3769f6ef45
Merge pull request #1608 from xPaw/master 7 years ago
Ramiro Saenz b224e58bb9
Merge pull request #1074 from Thalagyrt/electron-context-menu 7 years ago
Pavel Djundik 7c6f3842dc
Update The Lounge logo 7 years ago
Ryan Zumstein 14d6ca3fd0 Add statusbar toggling 7 years ago
Manuel Muradas 7328d3f02c Update service align on tab position change #1249 7 years ago
Bao Trinh eb095dfe61
Update Google Voice service checkUnread function 7 years ago
Brent Krone-Schmidt 678c391257 add hangouts chat 7 years ago
Tony Air dd19272b10
Use m.vk.com cuz it fits small window size 7 years ago
Ash258 9044a70330
Add missing yml rule in .editorconfig 7 years ago
Andreas Winter a72bc77fca [FIX][#1495] Changed gmail url to labs=0 to fix refreh error, replaced old with new gmail icon 7 years ago
Stephen Brown II 6964e25d72
Update Allo js_unread function 7 years ago
Ramiro Saenz e628079ddd
Removed snap temporary 7 years ago
Ramiro Saenz 85f876f4c8
Update .travis.yml 7 years ago
Ramiro Saenz 11cfe374b7
0.5.16 7 years ago
Ramiro Saenz 6226a5fa7c
Merge pull request #824 from flexiondotorg/snap-support 7 years ago
Jace Benson 1e23c5ea49 moved getting involved content to contributing 7 years ago
Maurice Schleußinger 876a5e0804 Fix https://github.com/saenzramiro/rambox/issues/1464 by hiding enable_hidpi_support on non-Windows platforms. 7 years ago
Luuk Schakenraad bee2e687bb Change teamwork Chat URL template 7 years ago
James Riley c27f5d1771 Added electron-context-menu. 8 years ago
qoheniac f2dedda3a9 Update package.json 8 years ago
Martin Wimpress b93a8a53aa Strict confinement 8 years ago
Martin Wimpress 6a5306950a Add snap support. 8 years ago
Patrice Bouillet bb4caf5629 Add Sococo Service 8 years ago
  1. 10
      .editorconfig
  2. 21
      .github/CONTRIBUTING.md
  3. 3
      .github/FUNDING.yml
  4. 25
      .github/config.yml
  5. 35
      .github/lock.yml
  6. 14
      .github/no-response.yml
  7. 26
      .github/stale.yml
  8. 21
      .gitignore
  9. 2
      .npmrc
  10. 82
      .sencha/app/Boot.js
  11. 17
      .sencha/app/Microloader.js
  12. 4
      .sencha/app/app.defaults.json
  13. 33
      .sencha/app/build-impl.xml
  14. 74
      .sencha/app/defaults.properties
  15. 65
      .sencha/app/init-impl.xml
  16. 115
      .sencha/app/js-impl.xml
  17. 4
      .sencha/app/native.defaults.properties
  18. 4
      .sencha/app/package.defaults.properties
  19. 62
      .sencha/app/page-impl.xml
  20. 29
      .sencha/app/refresh-impl.xml
  21. 205
      .sencha/app/sass-impl.xml
  22. 3
      .sencha/app/sencha.cfg
  23. 35
      .sencha/app/slice-impl.xml
  24. 59
      .sencha/app/watch-impl.xml
  25. 106
      .travis.yml
  26. 6
      Backers.md
  27. 216
      CONTRIBUTING.md
  28. 283
      README.md
  29. 6
      TODO.md
  30. 53
      app.js
  31. 10
      app.json
  32. 416
      app/Application.js
  33. 29
      app/README.md
  34. 30
      app/Readme.md
  35. 5
      app/model/README.md
  36. 4
      app/model/ServiceList.js
  37. 42
      app/package.json
  38. 0
      app/store/README.md
  39. 16
      app/store/Services.js
  40. 893
      app/store/ServicesList.js
  41. 17
      app/util/IconLoader.js
  42. 259
      app/ux/Auth0.js
  43. 461
      app/ux/WebView.js
  44. 33
      app/view/add/Add.js
  45. 1
      app/view/add/AddController.js
  46. 147
      app/view/main/Main.js
  47. 162
      app/view/main/MainController.js
  48. 1
      app/view/main/MainModel.js
  49. 154
      app/view/preferences/Preferences.js
  50. 9
      app/view/preferences/PreferencesController.js
  51. 52
      appveyor.yml
  52. 368
      electron/main.js
  53. 85
      electron/menu.js
  54. 11
      electron/tray.js
  55. 32
      electron/updater.js
  56. 4
      env-sample.js
  57. 2
      ext/packages/ext-aria/build/resources/Readme.md
  58. 2
      ext/packages/ext-aria/resources/Readme.md
  59. 4
      ext/packages/ext-aria/sass/etc/Readme.md
  60. 1
      ext/packages/sencha-soap/Readme.md
  61. 65
      index.html
  62. 2
      languages.js
  63. 21
      masterpassword.html
  64. 7605
      package-lock.json
  65. 224
      package.json
  66. 1
      packages/local/rambox-default-theme/Readme.md
  67. 47
      packages/local/rambox-default-theme/examples/Readme.md
  68. 8
      packages/local/rambox-default-theme/sass/Readme.md
  69. 4
      packages/local/rambox-default-theme/sass/etc/Readme.md
  70. 12
      packages/local/rambox-default-theme/sass/etc/all.scss
  71. 4
      packages/local/rambox-default-theme/sass/src/Readme.md
  72. 3
      packages/local/rambox-default-theme/src/Readme.md
  73. 4
      resources/Readme.md
  74. BIN
      resources/icons/airdroid.png
  75. BIN
      resources/icons/allo.png
  76. BIN
      resources/icons/amium.png
  77. BIN
      resources/icons/androidmessages.png
  78. BIN
      resources/icons/aol.png
  79. BIN
      resources/icons/awsworkmail.png
  80. BIN
      resources/icons/bearychat.png
  81. BIN
      resources/icons/bip.png
  82. BIN
      resources/icons/calendar.png
  83. BIN
      resources/icons/ciscospark.png
  84. BIN
      resources/icons/cliq.png
  85. BIN
      resources/icons/clocktweets.png
  86. BIN
      resources/icons/converse.png
  87. BIN
      resources/icons/crisp.png
  88. BIN
      resources/icons/dasher.png
  89. BIN
      resources/icons/devrant.png
  90. BIN
      resources/icons/dingtalk.png
  91. BIN
      resources/icons/discord.png
  92. BIN
      resources/icons/drift.png
  93. BIN
      resources/icons/duo.png
  94. BIN
      resources/icons/element.png
  95. BIN
      resources/icons/facebook.png
  96. BIN
      resources/icons/fastmail.png
  97. BIN
      resources/icons/fleep.png
  98. BIN
      resources/icons/flock.png
  99. BIN
      resources/icons/freenode.png
  100. BIN
      resources/icons/glip.png
  101. Some files were not shown because too many files have changed in this diff Show More

10
.editorconfig

@ -8,3 +8,13 @@ root = true
end_of_line = lf
insert_final_newline = true
indent_style = tab
tab_width = 2
[*.{yml,yaml}]
indent_style = space
indent_size = 2
[*.{md}]
indent_style = space
indent_size = 4
trim_trailing_whitespace = false

21
.github/CONTRIBUTING.md

@ -1,32 +1,27 @@
# Contributing
## Submitting issues
* Please search the existing issues first, it's likely that your issue was already reported or even fixed.
- Please search the existing issues first, it's likely that your issue was already reported or even fixed.
- Go to "Issues" and type any word in the top search/command bar.
- Consider to search on closed issues. To do that just remove "is:open" from the search field.
- More info on [search syntax within github](https://help.github.com/articles/searching-issues)
* Report the issue using our [template][template], it includes all the information we need to track down the issue.
- More info on [search syntax within github](https://help.github.com/articles/searching-issues).
- Report the issue using our [template](https://github.com/saenzramiro/rambox/blob/master/.github/ISSUE_TEMPLATE.md), it includes all the information we need to track down the issue.
Help us to maximize the effort we can spend fixing issues and adding new features, by not reporting duplicate issues.
[template]: https://github.com/saenzramiro/rambox/blob/master/.github/ISSUE_TEMPLATE.md
## Share your Custom Services
If you consider there are other users that can use your Custom Service, we have a repo for this: [Rambox Services Contrib][rambox-services-contrib].
[rambox-services-contrib]: https://github.com/saenzramiro/rambox-services-contrib
If you consider there are other users that can use your Custom Service, we have a repo for this: [Rambox Services Contrib](https://github.com/saenzramiro/rambox-services-contrib)
## Ask for help
We have a great community in [Gitter][gitter] that can help you with any doubt or problem.
[gitter]: https://gitter.im/saenzramiro/rambox
We have a great community in [Slack (Prefered)](https://rambox.typeform.com/to/t7jc4C) or [Gitter](https://gitter.im/saenzramiro/rambox) (Gitter channel is mirroring into Slack `general` room) that can help you with any doubt or problem.
## Contributing to Source Code
Feel free to create pull requests to help us offer a great and complete software. :wink:
## Translations
Please submit translations via [Transifex][transifex].
[transifex]: https://www.transifex.com/rambox/rambox-app/
Please submit translations via [Crowdin](https://crowdin.com/project/rambox/).

3
.github/FUNDING.yml

@ -0,0 +1,3 @@
# These are supported funding model platforms
custom: ['https://rambox.app/donate.html']

25
.github/config.yml

@ -0,0 +1,25 @@
# Configuration for new-issue-welcome - https://github.com/behaviorbot/new-issue-welcome
# Comment to be posted to on first time issues
newIssueWelcomeComment: >
Thanks for opening your first issue here! Be sure to follow the issue template!
# Configuration for new-pr-welcome - https://github.com/behaviorbot/new-pr-welcome
# Comment to be posted to on PRs from first time contributors in your repository
newPRWelcomeComment: >
Thanks for opening this pull request! Please check out our contributing guidelines.
# Configuration for first-pr-merge - https://github.com/behaviorbot/first-pr-merge
# Comment to be posted to on pull requests merged by a first time user
firstPRMergeComment: >
Congrats on merging your first pull request! We here at Rambox are proud of you!
# Configuration for request-info - https://github.com/behaviorbot/request-info
# *Required* Comment to reply with
requestInfoReplyComment: >
We would appreciate it if you could provide us with more info about this issue/pr!
# *OPTIONAL* Label to be added to Issues and Pull Requests with insufficient information given
requestInfoLabelToAdd: more-information-needed

35
.github/lock.yml

@ -0,0 +1,35 @@
# Configuration for lock-threads - https://github.com/dessant/lock-threads
# Number of days of inactivity before a closed issue or pull request is locked
daysUntilLock: 30
# Issues and pull requests with these labels will not be locked. Set to `[]` to disable
exemptLabels:
- archive
# Label to add before locking, such as `outdated`. Set to `false` to disable
lockLabel: false
# Comment to post before locking. Set to `false` to disable
lockComment: >
This thread has been automatically locked since there has not been
any recent activity after it was closed. Please open a new issue for
related bugs.
# Assign `resolved` as the reason for locking. Set to `false` to disable
setLockReason: true
# Limit to only `issues` or `pulls`
# only: issues
# Optionally, specify configuration settings just for `issues` or `pulls`
# issues:
# exemptLabels:
# - help-wanted
# lockLabel: outdated
# pulls:
# daysUntilLock: 30
# Repository to extend settings from
# _extends: repo

14
.github/no-response.yml

@ -0,0 +1,14 @@
# Configuration for probot-no-response - https://github.com/probot/no-response
# Number of days of inactivity before an Issue is closed for lack of response
daysUntilClose: 14
# Label requiring a response
responseRequiredLabel: more-information-needed
# Comment to post when closing an Issue for lack of response. Set to `false` to disable
closeComment: >
This issue has been automatically closed because there has been no response
to our request for more information from the original author. With only the
information that is currently in the issue, we don't have enough information
to take action. Please reach out if you have or find the answers we need so
that we can investigate further.

26
.github/stale.yml

@ -0,0 +1,26 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 60
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
# Only issues or pull requests with all of these labels are check if stale. Defaults to `[]` (disabled)
onlyLabels:
- more-information-needed
# Issues with these labels will never be considered stale
exemptLabels:
- bug
- to do
- enhancement
- feature request
- in progress
- investigate
# Label to use when marking an issue as stale
staleLabel: stale
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: >
This issue has been automatically closed since there has not been
any recent activity. Please open a new issue for related bugs.

21
.gitignore vendored

@ -1,10 +1,10 @@
# Sencha (ExtJS)
/build/development
/build/production
/build/temp
build/development/
build/production/
build/temp/
.sass-cache/
.sass_cache/
/dist
dist/
# OS generated files #
######################
@ -18,20 +18,21 @@ Thumbs.db
# IDE generated files #
######################
.project
.idea
.project/
.idea/
# bootstrap files are regenerated by Sencha CMD on every build or refresh
bootstrap.js
bootstrap.css
bootstrap.json
bootstrap.jsonp
# Electron
node_modules
node_modules/
npm-debug.log
# Vagrant
/.vagrant
env.js
rambox_cfg.json
.vagrant/
languages.js
electron/dev-app-update.yml

2
.npmrc

@ -0,0 +1,2 @@
package-lock = false
save-exact = true

82
.sencha/app/Boot.js

@ -537,9 +537,33 @@ Ext.Boot = Ext.Boot || (function (emptyFn) {
init: function () {
var scriptEls = doc.getElementsByTagName('script'),
script = scriptEls[0],
len = scriptEls.length,
re = /\/ext(\-[a-z\-]+)?\.js$/,
entry, script, src, state, baseUrl, key, n, origin;
entry, src, state, baseUrl, key, n, origin;
// No check for script definedness because there always should be at least one
Boot.hasReadyState = ("readyState" in script);
Boot.hasAsync = ("async" in script);
Boot.hasDefer = ("defer" in script);
Boot.hasOnLoad = ("onload" in script);
// Feature detecting IE
Boot.isIE8 = Boot.hasReadyState && !Boot.hasAsync && Boot.hasDefer && !Boot.hasOnLoad;
Boot.isIE9 = Boot.hasReadyState && !Boot.hasAsync && Boot.hasDefer && Boot.hasOnLoad;
Boot.isIE10p = Boot.hasReadyState && Boot.hasAsync && Boot.hasDefer && Boot.hasOnLoad;
if (Boot.isIE8) {
Boot.isIE10 = false;
Boot.isIE10m = true;
}
else {
Boot.isIE10 = (new Function('/*@cc_on return @_jscript_version @*/')()) === 10;
Boot.isIE10m = Boot.isIE10 || Boot.isIE9 || Boot.isIE8;
}
// IE11 does not support conditional compilation so we detect it by exclusion
Boot.isIE11 = Boot.isIE10p && !Boot.isIE10;
// Since we are loading after other scripts, and we needed to gather them
// anyway, we track them in _scripts so we don't have to ask for them all
@ -552,12 +576,8 @@ Ext.Boot = Ext.Boot || (function (emptyFn) {
state = script.readyState || null;
// If we find a script file called "ext-*.js", then the base path is that file's base path.
if (!baseUrl) {
if (re.test(src)) {
Boot.hasReadyState = ("readyState" in script);
Boot.hasAsync = ("async" in script) || !Boot.hasReadyState;
baseUrl = src;
}
if (!baseUrl && re.test(src)) {
baseUrl = src;
}
if (!Boot.scripts[key = Boot.canonicalUrl(src)]) {
@ -578,8 +598,6 @@ Ext.Boot = Ext.Boot || (function (emptyFn) {
if (!baseUrl) {
script = scriptEls[scriptEls.length - 1];
baseUrl = script.src;
Boot.hasReadyState = ('readyState' in script);
Boot.hasAsync = ("async" in script) || !Boot.hasReadyState;
}
Boot.baseUrl = baseUrl.substring(0, baseUrl.lastIndexOf('/') + 1);
@ -1394,27 +1412,36 @@ Ext.Boot = Ext.Boot || (function (emptyFn) {
createLoadElement: function(callback) {
var me = this,
el = me.getElement(),
readyStateChange = function(){
el = me.getElement();
me.preserve = true;
el.onerror = function() {
me.error = true;
if (callback) {
callback();
callback = null;
}
};
if (Boot.isIE10m) {
el.onreadystatechange = function() {
if (this.readyState === 'loaded' || this.readyState === 'complete') {
if(callback) {
if (callback) {
callback();
callback = this.onreadystatechange = this.onerror = null;
}
}
},
errorFn = function() {
me.error = true;
if(callback) {
callback();
}
};
me.preserve = true;
el.onerror = errorFn;
if(Boot.hasReadyState) {
el.onreadystatechange = readyStateChange;
} else {
el.onload = callback;
}
else {
el.onload = function() {
callback();
callback = this.onload = this.onerror = null;
};
}
// IE starts loading here
el[me.prop] = me.getLoadUrl();
},
@ -1541,8 +1568,11 @@ Ext.Boot = Ext.Boot || (function (emptyFn) {
// for async modes, we have some options
if (!sync) {
// if cross domain, just inject the script tag and let the onload
// events drive the progression
if(me.isCrossDomain()) {
// events drive the progression.
// IE10 also needs sequential loading because of a bug that makes it
// fire readystate event prematurely:
// https://connect.microsoft.com/IE/feedback/details/729164/ie10-dynamic-script-element-fires-loaded-readystate-prematurely
if (Boot.isIE10 || me.isCrossDomain()) {
return me.loadCrossDomain();
}
// for IE, use the readyStateChange allows us to load scripts in parallel

17
.sencha/app/Microloader.js

@ -51,15 +51,24 @@ Ext.Microloader = Ext.Microloader || (function () {
? manifest
: manifest + ".json";
Boot.fetch(url, function(result){
manifest = Ext.manifest = JSON.parse(result.content);
Microloader.load(manifest);
});
if (location.href.indexOf('file:/') === 0) {
Boot.load(url + 'p');
}
else {
Boot.fetch(url, function(result){
Microloader.setManifest(JSON.parse(result.content));
});
}
} else {
Microloader.load(manifest);
}
},
setManifest: function(cfg) {
manifest = Ext.manifest = cfg;
Microloader.load(manifest);
},
/**
*
* @param manifestDef

4
.sencha/app/app.defaults.json

@ -135,7 +135,7 @@
*/
"production": {
"compressor": {
"type": "yui"
"type": "cmd"
}
},
@ -170,7 +170,7 @@
* to adjust the base path for all bootstrap objects, or expanded into object form:
*
* "bootstrap": {
* "base": "${app.dir},
* "base": "${app.dir}",
* "manifest": "bootstrap.json",
* "microloader": "bootstrap.js",
* "css": "bootstrap.css"

33
.sencha/app/build-impl.xml

@ -244,9 +244,15 @@ this file in most cases.
<target name="watch"
depends="-watch-init,development,init"
description="Starts Watch to keep your app ready for dev mode">
<local name="watch.lock.file"/>
<condition property="watch.lock.file" value="${build.id}.watch.lock">
<isset property="build.id"/>
</condition>
<property name="watch.lock.file" value="app.watch.lock"/>
<x-ant-call>
<param name="build.id" value="${build.id}"/>
<param name="build.name" value="${build.name}"/>
<param name="watch.lock.file" value="${build.dir}/${watch.lock.file}"/>
<target name="-before-watch"/>
<target name="-watch"/>
<target name="-after-watch"/>
@ -463,6 +469,33 @@ this file in most cases.
depends="init,-before-publish,-publish,-after-publish"
description="Publish app to Sencha Web Application Manager"/>
<!--
===============================================================
Build Dependencies
uses the compiler to build metadata files for all detected
file-to-file dependencies
===============================================================
-->
<target name="build-dependencies" depends="init, -detect-app-build-properties">
<x-compile refid="${compiler.ref.id}">
<![CDATA[
restore
page
and
meta
-infoType=Dependencies
-basePath=${build.dir}
-tpl={0}
-out=${build.dir}/dependencies.json
and
meta
-infoType=AppManifest
-basePath=${build.dir}
-tpl={0}
-out=${build.dir}/bootsequence.json
]]>
</x-compile>
</target>
<!--
===============================================================

74
.sencha/app/defaults.properties

@ -1,7 +1,7 @@
# =============================================================================
# This file defines properties used by build-impl.xml and the associated
# *-impl.xml files (sass-impl.xml, js-impl.xml, etc.), which are the core of
# the applications build process.
# the applications build process.
#
# This file represents the lowest priority file for defining these properties
# as well as the place to look for documentation and learning what properties
@ -48,7 +48,7 @@
# See "sencha help app build" for details.
#
# The corresponding properties files:
# (production.properties, testing.properties, etc.) provide examples of
# (production.properties, testing.properties, etc.) provide examples of
# overriding sets of properties depending on the selected environment
# NOTE: this replaces the deprecated args.environment
app.environment=production
@ -120,6 +120,8 @@ app.output.cache.path=${app.output.cache}
app.output.cache.enable=true
app.output.appCache.enable=${app.output.cache.enable}
app.output.appCache.path=${app.output.cache.path}
app.output.progressive=false
app.output.progressive.enable=${app.output.progressive}
build.out.base.path=${app.output.base}
build.out.page.path=${build.out.base.path}/${app.output.page.path}
@ -236,13 +238,13 @@ build.options=logger:${build.options.logger},debug:${build.options.debug},produc
# This property can be modified to change general build options
# such as excluding files from the set. The format expects newlines
# for each argument, for example:
#
#
# build.operations=\
# exclude\n \
# -namespace=Ext\n
#
# NOTE: modifications to build.operations are intended to be
# placed in an override of the "-after-init" target, where it
# NOTE: modifications to build.operations are intended to be
# placed in an override of the "-after-init" target, where it
# can be calculated based on other
# ant properties
#
@ -268,7 +270,7 @@ build.optimize.enable=\
build.optimize.disable=
build.optimize=${build.optimize.disable}
# enables / disables removing text references from
# enables / disables removing text references from
# package js build files
build.remove.references=true
@ -280,12 +282,12 @@ build.remove.requirement.nodes=true
# like mixin references
build.optimize.string.references=true
# enables / disables yui compression
build.compression.yui=${app.output.js.compress}
# enables / disables cmd compression
build.compression.cmd=${app.output.js.compress}
# enables / disables closure compression
build.compression.closure=0
# enables / disables uglify compression
build.compression.ugilfy=0
@ -296,8 +298,8 @@ build.compile.temp.dir.keep=true
# ------------------------------------------
# DOC ONLY - Do Not Set
# this variable will be set to the appropriate compressor
# option, and is calculated in init-impl.xml, but may be overridded in
# this variable will be set to the appropriate compressor
# option, and is calculated in init-impl.xml, but may be overridded in
# app.properties, <environment>.properties, or via command line
#
# build.compression=
@ -312,8 +314,8 @@ build.compile.temp.dir.keep=true
# markup, or left as a separate resource
build.enable.embedded.microloader=${app.output.microloader.embed}
# whether to include the page's manifest.json code with the
# microloader content. Production.properties files should set this to
# whether to include the page's manifest.json code with the
# microloader content. Production.properties files should set this to
# false to have manifest.json exist as a server resource.
build.enable.embedded.manifest=${app.output.manifest.embed}
@ -348,18 +350,18 @@ app.microloader=${app.microloader.dir}/${app.microloader.name}
app.microloader.path=${app.microloader}
# specifies how to embed the microloader code into the output markup
# {0} is replaced with the content of the microloader file specified
# {0} is replaced with the content of the microloader file specified
# by app.microloader.path
build.microloader.code.tpl={0}
# the template to use when generating a stand-alone json manifest file
build.microloader.json.tpl.standalone={0}
# the template to use when embedding the manifest json directly next to the
# the template to use when embedding the manifest json directly next to the
# microloader in the output microloader content
build.microloader.json.tpl.embedded=Ext.blink({0});
# the template to use in the output microloader content when supplying
# the template to use in the output microloader content when supplying
# the manifest json as a separate server-side resource ('production' builds)
build.microloader.json.tpl.external=Ext.blink('{'id:''${app.id}'''}');
@ -368,7 +370,7 @@ build.microloader.json.tpl.external=Ext.blink('{'id:''${app.id}'''}');
build.embedded.microloader.tpl=<script id="microloader" data-app="${app.id}" type="text/javascript">{0}</script>
# the compressor to use when embedding the microloader into a page
# can be -closure or -yui, or leave empty to disable compression
# can be -closure or -cmd, or leave empty to disable compression
build.embedded.microloader.compressor=
# the path to the microloader content file, if external to the outpout markup
@ -383,7 +385,7 @@ build.external.microloader.markup=<script id="microloader" data-app="${app.id}"
# currently unused : is a placeholder for future microloader interactions
build.microloader.mode=${build.environment}
# the tag name to use when generating the compiler save set for
# the tag name to use when generating the compiler save set for
# the page's js code
build.tag.name=full-page
@ -485,7 +487,7 @@ enable.ext42.themes=false
enable.touch.themes=false
# --------------------
# selector count threshold to use when
# selector count threshold to use when
# splitting a single css file into multiple
# css files (IE selector limit workaround)
#
@ -497,7 +499,7 @@ build.css.selector.limit=${app.output.css.split}
build.css.preprocess=${app.output.css.preprocess}
# sets the css preprocessor options, in the form:
# name1:value1,name2:value2,...
# name1:value1,name2:value2,...
build.css.preprocessor.opts=
# enables / disable css compressor (enable.ext42.themes only)
@ -580,32 +582,32 @@ theme.name=default
# *****************************************************************************
# the resources directory of the application
# note: this property is currently only used for building ext 4.1 style themes
# note: this property is currently only used for building ext 4.1 style themes
# (used by x-build-theme and x-copy-resources in slice-impl.xml)
app.resources.dir=${app.dir}/resources
# the directory containing the slicer widget example page
app.example.dir=${app.dir}/sass/example
# this is the directory used for intermediate build artifacts used
# by the slicer for generating theme images
app.example.build.dir=${build.temp.dir}/slicer-temp
# properties to control the recirect css file that is
# generated for the slicer example page
app.example.css.name=example.css
app.example.css.file=${app.example.dir}/${app.example.css.name}
app.example.css.file=${app.example.build.dir}/${app.example.css.name}
# the base path for generating the bootstrap code for the
# the base path for generating the bootstrap code for the
# slicer page
bootstrap.base.path=${app.example.dir}
bootstrap.base.path=${app.example.build.dir}
# the full file name of the slicer page's bootstrap js file
bootstrap.example.js=${app.example.dir}/bootstrap.js
bootstrap.example.js=${app.example.build.dir}/bootstrap.js
# the full file name of the slicer page's bootstrap js file
bootstrap.example.json.name=bootstrap.json
bootstrap.example.json=${app.example.dir}/${bootstrap.example.json.name}
# this is the directory used for intermediate build artifacts used
# by the slicer for generating theme images
app.example.build.dir=${build.temp.dir}/slicer-temp
bootstrap.example.json=${app.example.build.dir}/${bootstrap.example.json.name}
# the name of the intermediate screenshot file used for image slicing
build.capture.png=${app.example.build.dir}/theme-capture.png
@ -615,8 +617,8 @@ build.capture.json=${app.example.build.dir}/theme-capture.json
# the location of the slicer widget page
app.example.theme.html.name=theme.html
app.example.theme.html=${cmd.dir}/ant/build/slicer/${app.example.theme.html.name}
app.example.fashion.html.name=fashion.html
app.example.theme.html=${app.example.dir}/${app.example.theme.html.name}
app.example.fashion.html=${app.example.dir}/${app.example.fashion.html.name}
# a name prefix used for slicer page temporary artifacts
@ -644,7 +646,7 @@ build.slice.options=
# *****************************************************************************
# Packager
# these properties control features of the native packaging phase of the
# these properties control features of the native packaging phase of the
# build process
# *****************************************************************************
@ -655,13 +657,13 @@ enable.desktop.packager=false
# skips packaging the built application with cordova/phonegap
skip.native-package=false
# a property that controls whether a standalone manifest.json file will be
# a property that controls whether a standalone manifest.json file will be
# generated for the native packaged application
enable.standalone.manifest=false
# *****************************************************************************
# Resolve
# these properties control aspects of the dynamic dependency resolver, which
# these properties control aspects of the dynamic dependency resolver, which
# uses phantomjs to load the application and extract Ext.Loader class load
# history.
# *****************************************************************************
@ -691,7 +693,7 @@ build.resolve.mode=references
# the output file for the detected dynamic dependencies
build.resolve.file=${build.temp.dir}/resolve.json
# controls whether unmatched external references in the specified file will
# controls whether unmatched external references in the specified file will
# generate build warnings or build failures
build.resolve.allow.unmatched=true
@ -704,4 +706,4 @@ build.resolve.allow.unmatched=true
build.trigger.targets=refresh,resources,sass
# the watcher targets to run that monitor for code changes
build.watcher.targets=-watch-compiler
build.watcher.targets=-watch-fashion,-watch-compiler

65
.sencha/app/init-impl.xml

@ -19,11 +19,13 @@
<script language="javascript">
<![CDATA[
var f = new java.io.File(project.getProperty("basedir"));
var sub = ".sencha/workspace/sencha.cfg";
var sub = ".sencha/workspace/sencha.cfg"
var sub2 = "workspace.json";
for (var p = f; p; p = p.getParentFile()) {
var t = new java.io.File(p, sub);
if (t.exists()) {
var t2 = new java.io.File(p, sub2);
if (t.exists() || t2.exists()) {
// we found the workspace folder!
t = new java.io.File(p, "local.properties");
@ -87,13 +89,20 @@
<!--
calculate the appropriate build.compression value
-->
<condition property="build.compression" value="-yui">
<condition property="build.compression" value="-cmd">
<or>
<x-is-true value="${build.compression.yui}"/>
<equals arg1="yui" arg2="${app.compressor.type}"/>
</or>
</condition>
<condition property="build.compression" value="-cmd">
<or>
<x-is-true value="${build.compression.cmd}"/>
<equals arg1="cmd" arg2="${app.compressor.type}"/>
</or>
</condition>
<condition property="build.compression" value="-closure">
<or>
<x-is-true value="${build.compression.closure}"/>
@ -144,6 +153,8 @@
<property name="app.sass.fashion" value="false"/>
<property name="app.sass.rhino" value="false"/>
<property name="app.sass.dynamic" value="false"/>
<property name="app.sass.generated.var" value="${app.sass.save}"/>
</target>
<target name="-after-init"/>
@ -219,6 +230,23 @@
</else>
</if>
<if>
<or>
<equals arg1="${app.output.js.filter}" arg2="all"/>
<equals arg1="${app.output.js.filter}" arg2="minimum"/>
</or>
<then>
<property name="enable.used.deps" value="false"/>
</then>
</if>
<if>
<equals arg1="${app.output.js.filter}" arg2="used"/>
<then>
<property name="enable.used.deps" value="true"/>
</then>
</if>
<if>
<equals arg1="${app.toolkit}" arg2="modern"/>
<then>
@ -239,6 +267,18 @@
</then>
</if>
<if>
<or>
<x-is-false value="${app.output.progressive.enable}"/>
<not>
<isset property="${app.output.progressive.enable}"/>
</not>
</or>
<then>
<property name="${skip.progressive}" value="1"/>
</then>
</if>
<if>
<!--If Deltas are FALSE, deltas do not exist, or caching is disabled then skip delta patching-->
<or>
@ -340,6 +380,19 @@
</condition>
<property name="enable.split.framework" value="false"/>
<if>
<equals arg1="${app.output.js.filter}" arg2="used"/>
<then>
<property name="include.used.package.deps">
include
-usedPackagesDeps
and
</property>
</then>
</if>
<property name="include.used.package.deps">
# no-op
</property>
<x-compile refid="${compiler.ref.id}"
dir="${app.dir}"
@ -372,6 +425,7 @@
${build.operations}
and
${exclude.boot}
${include.used.package.deps}
save
page
]]>
@ -391,6 +445,7 @@
${build.operations}
and
${exclude.boot}
${include.used.package.deps}
save
page
]]>
@ -403,7 +458,9 @@
defaultSassFile="${app.out.scss}"
defaultCssFile="${app.out.css}"
refid="app.web.server"
saveVariablesProp="app.sass.save"
saveVariablesProp="app.sass.generated.var"
uiDirProp="app.sass.generated.src"
sassNamespaceProp="app.sass.namespace"
j2eeMode="${use.webxml}">
<mapping name="~cmd" path="${cmd.dir}"/>
<mapping name="" path="${build.web.root}"/>

115
.sencha/app/js-impl.xml

@ -10,18 +10,121 @@
splitModePropName="enable.split.mode"
pageModePropName="app.page.mode"
hasJsSdkPropName="app.has.js.sdk"
hasCssSdkPropName="app.has.css.sdk"/>
hasCssSdkPropName="app.has.css.sdk"
hasUsesPackagesPropName="app.has.uses" />
</target>
<!--
this is the standard js compile target that builds the output js file(s)
-->
<target name="-compile-js" depends="-detect-app-build-properties">
<property name="app.output.framework.include"
value="package-sencha-core,framework,toolkit,package-core"/>
<property name="enable.used.deps" value="${app.has.uses}"/>
<if>
<x-is-true value="${enable.used.deps}"/>
<then>
<x-compile refid="${compiler.ref.id}">
# determine the base set of framework files
exclude
-all
and
include
-tag=${app.output.framework.include}
and
save
allframework
</x-compile>
<for param="file">
<fileset dir="${workspace.build.dir}/temp" includes="**/deps.json"/>
<sequential>
<x-compile refid="${compiler.ref.id}">
# now load the transitive set based on the json data
exclude
-all
and
include
-json-data=@{file}
-r
and
save
deps
and
# add any needed deps to the page save set
include
-set=page
and
save
page
</x-compile>
</sequential>
</for>
</then>
<else>
<if>
<equals arg1="${app.output.js.filter}" arg2="all"/>
<then>
<x-compile refid="${compiler.ref.id}">
# if filtering requirements is configured for 'all'
# then just include all js content on the classpath to
# ensure all dependencies are provided for the used packages
include
-all
and
save
page
</x-compile>
</then>
</if>
</else>
</if>
<if>
<x-is-true value="${enable.split.mode}"/>
<then>
<property name="app.output.framework.include"
value="package-sencha-core,framework,toolkit,package-core"/>
<local name="build.js.framework.fwset" />
<local name="build.js.framework.rtl" />
<if>
<or>
<x-is-true value="${app.output.framework.all}" />
<isset property="app.has.uses" />
</or>
<then>
<property name="build.include.all.scss" value="true" />
<property name="build.js.framework.fwset"> </property>
<if>
<x-is-false value="${app.output.framework.rtl}" />
<then>
<property name="build.js.framework.rtl">
<![CDATA[
exclude
-namespace=Ext.rtl
and
]]>
</property>
</then>
<else>
<property name="build.js.framework.rtl"> </property>
</else>
</if>
</then>
<else>
<property name="build.js.framework.fwset">
<![CDATA[
intersect
-set=page,allframework
and
]]>
</property>
<property name="build.js.framework.rtl"> </property>
</else>
</if>
<x-compile refid="${compiler.ref.id}">
<![CDATA[
@ -40,12 +143,11 @@
save
allframework
and
intersect
-set=page,allframework
and
${build.js.framework.fwset}
save
frameworkdeps
and
${build.js.framework.rtl}
include
-tag=Ext.cmd.derive
and
@ -80,6 +182,7 @@
</x-compile>
</then>
<else>
<local name="framework.include.filter"/>
<x-compile refid="${compiler.ref.id}">
<![CDATA[
# build an all-classes.js file that contains

4
.sencha/app/native.defaults.properties

@ -18,8 +18,8 @@ build.options.logger=no
build.options.debug=false
# enable yui compression
build.compression.yui=1
# enable cmd compression
build.compression.cmd=1
enable.standalone.manifest=true

4
.sencha/app/package.defaults.properties

@ -21,7 +21,7 @@ build.options.logger=no
build.options.debug=false
# enable yui compression
build.compression.yui=1
# enable cmd compression
build.compression.cmd=1
app.microloader.name=testing.js

62
.sencha/app/page-impl.xml

@ -2,15 +2,22 @@
<macrodef name="x-build-microload-markup">
<sequential>
<x-sencha-command dir="${app.dir}" inheritall="true">
<![CDATA[
fs
minify
${build.embedded.microloader.compressor}
-from=${build.microloader.path}
-to=${build.microloader.path}
]]>
</x-sencha-command>
<if>
<not>
<equals arg1="${build.compression}" arg2=""/>
</not>
<then>
<x-sencha-command dir="${app.dir}" inheritall="true">
<![CDATA[
fs
minify
${build.embedded.microloader.compressor}
-from=${build.microloader.path}
-to=${build.microloader.path}
]]>
</x-sencha-command>
</then>
</if>
<if>
<x-is-true value="${build.enable.embedded.microloader}"/>
<then>
@ -55,6 +62,7 @@
# generate json file
microload
-operation=manifest
-jsonp=Ext.Microloader.setManifest
-fashion=${use.fashion}
-tpl=${build.microloader.json.tpl.embedded}
-out=${build.microloader.path}
@ -77,6 +85,7 @@
# generate json file
microload
-operation=manifest
-jsonp=Ext.Microloader.setManifest
-fashion=${use.fashion}
-tpl=${build.microloader.json.tpl.standalone}
-out=${build.out.json.path}
@ -307,11 +316,44 @@
value="&lt;html"/>
</target>
<target name="-generate-progressive-webapp" depends="-init-compiler">
<if>
<x-is-false value="${skip.progressive}"/>
<then>
<x-compile refid="${compiler.ref.id}">
<![CDATA[
progressive-webapp
-buildDir=${build.out.base.path}
]]>
</x-compile>
</then>
</if>
</target>
<target name="-generate-service-worker" depends="-init-compiler">
<if>
<x-is-false value="${skip.progressive}"/>
<then>
<x-compile refid="${compiler.ref.id}">
<![CDATA[
progressive-webapp
-buildDir=${build.out.base.path}
+serviceWorker
]]>
</x-compile>
</then>
</if>
</target>
<target name="-before-page"/>
<target name="-page"
depends="-copy-app-resources,
-generate-progressive-webapp,
-generate-deltas,
-build-output-page,
-generate-cache-manifest"/>
-generate-cache-manifest,
-generate-service-worker"/>
<target name="-after-page"/>
</project>

29
.sencha/app/refresh-impl.xml

@ -19,6 +19,9 @@
<not>
<isset property="app.watch.enabled"/>
</not>
<not>
<isset property="app.uses"/>
</not>
</and>
</condition>
<property name="manifest.root.excludes" value=""/>
@ -41,6 +44,9 @@
exclude
-tag=${refresh.file.filter}
and
exclude
-file=Boot.js
and
save
bootstrap
]]>
@ -52,6 +58,9 @@
include
-all
and
exclude
-file=Boot.js
and
save
bootstrap
]]>
@ -63,9 +72,9 @@
to="${build.json.bootstrap.path}"
property="build.json.bootstrap.rel.path"/>
<echo file="${app.bootstrap.js}">var Ext = Ext || {};
<x-file-write file="${app.bootstrap.js}">var Ext = Ext || {};
Ext.manifest = Ext.manifest || "${build.json.bootstrap.rel.path}";
</echo>
</x-file-write>
<x-compile refid="${compiler.ref.id}">
<![CDATA[
@ -78,6 +87,7 @@ Ext.manifest = Ext.manifest || "${build.json.bootstrap.rel.path}";
and
microload
-operation=manifest
-jsonp=Ext.Microloader.setManifest
-fashion=${use.fashion}
-bootstrap
+ignoreDisabled
@ -104,13 +114,13 @@ Ext.manifest = Ext.manifest || "${build.json.bootstrap.rel.path}";
by the default development.js microloader
-->
<echo file="${build.json.bootstrap.path}">
<x-file-write file="${build.json.bootstrap.path}">
/**
* This file is generated by Sencha Cmd and should NOT be edited. It is a
* combination of content from app.json, and all required package's package.json
* files. Customizations should be placed in app.json.
*/
</echo>
</x-file-write>
<x-compile refid="${compiler.ref.id}">
<![CDATA[
microload
@ -129,9 +139,14 @@ Ext.manifest = Ext.manifest || "${build.json.bootstrap.rel.path}";
'-detect-app-build-properties' is defined in js-impl.xml
-->
<target name="-refresh-app"
depends="-detect-app-build-properties,
-refresh-app-manifest,
-refresh-app-bootstrap"/>
depends="-detect-app-build-properties">
<if>
<equals arg1="development" arg2="${build.environment}"/>
<then>
<x-ant-call target="-refresh-app-manifest,-refresh-app-bootstrap"/>
</then>
</if>
</target>
<!--
Refresh app

205
.sencha/app/sass-impl.xml

@ -15,7 +15,10 @@
property="image.search.path"/>
<if>
<x-is-true value="${build.include.all.scss}"/>
<or>
<x-is-true value="${app.has.uses}" />
<x-is-true value="${build.include.all.scss}"/>
</or>
<then>
<property name="sass.name.filter">
include
@ -107,18 +110,21 @@
<copy file="${app.out.scss.tmp}" tofile="${app.out.scss}" overwrite="true"/>
</then>
</if>
<!--
app.out.css.path is relative to the app output index.html file
-->
<x-get-relative-path
from="${app.dir}"
to="${app.out.css}"
property="app.out.css.path"
/>
<if>
<equals arg1="development" arg2="${build.environment}"/>
<then>
<!--
app.out.css.path is relative to the app output index.html file
-->
<x-get-relative-path
from="${app.dir}"
to="${app.out.css}"
property="app.out.css.path"
/>
<!--update the application's bootstrap.css file to point to the build output-->
<echo file="${build.bootstrap.css.path}">
<x-file-write file="${build.bootstrap.css.path}">
<![CDATA[
/*
* This file is generated by Sencha Cmd and should NOT be edited. It redirects
@ -127,7 +133,9 @@
*/
@import '${app.out.css.path}';
]]>
</echo>
</x-file-write>
</then>
</if>
</target>
<!--
@ -186,73 +194,130 @@
scss file, then running compass with the css, sass, and config options set
-->
<target name="-compass-compile-theme-package" depends="-load-sass-page">
<x-run-if-true value="${enable.ext42.themes}">
<local name="compress.uptodate"/>
<x-ant-call target="-compile-sass"/>
<if>
<x-is-true value="${skip.sass.rebuild}"/>
<then>
<x-run-if-true value="${enable.ext42.themes}">
<x-ant-call target="-compile-sass"/>
</x-run-if-true>
</then>
<else>
<x-run-if-true value="${enable.ext42.themes}">
<local name="compress.uptodate"/>
<x-ant-call target="-compile-sass"/>
<if>
<x-is-true value="${app.sass.fashion}"/>
<then>
<if>
<x-is-true value="${app.sass.rhino}"/>
<x-is-true value="${app.sass.fashion}"/>
<then>
<x-fashion-compile
file="${app.out.scss}"
toFile="${app.out.css}"/>
</then>
<else>
<x-fashion-live-update input="${app.out.scss}"
output="${app.out.css}"
refId="app.web.server"
split="${build.css.selector.limit}"
compress="${build.css.compress}"
compilerRefId="${compiler.ref.id}"/>
<if>
<x-is-true value="${app.sass.rhino}"/>
<then>
<x-fashion-compile
file="${app.out.scss}"
toFile="${app.out.css}"/>
</then>
<else>
<x-fashion-live-update input="${app.out.scss}"
output="${app.out.css}"
refId="app.web.server"
split="${build.css.selector.limit}"
compress="${build.css.compress}"
compilerRefId="${compiler.ref.id}"/>
<x-sencha-command>
fashion
-compress=${build.css.compress}
-split=${build.css.selector.limit}
-saveFile=${app.dir}/${app.sass.save}
${app.out.scss}
${app.out.css}
</x-sencha-command>
<x-compile refid="${compiler.ref.id}">
<![CDATA[
microload
-operation=manifest
-fashion=false
-tpl=${build.microloader.json.tpl.standalone}
-out=${build.out.json.path}
-resourcePath=${build.out.base.path}
-basePath=${build.out.metadata.dir}
]]>
</x-compile>
<x-update-css-array input="${app.out.css}"
compilerRefId="${compiler.ref.id}"/>
</else>
</if>
</then>
<else>
<x-compass-compile
rubyPath="${build.ruby.path}"
dir="${compass.working.dir}"
trace="${compass.compile.trace}"
boring="${compass.compile.boring}"
force="${compass.compile.force}"
sassdir="${compass.sass.dir}"
cssdir="${compass.css.dir}"
config="${compass.config.file}"/>
<x-sencha-command>
fashion
-config=${build.out.json.path}
-compress=${build.css.compress}
-split=${build.css.selector.limit}
-saveFile=${app.dir}/${app.sass.generated.var}
-slicer=false
${app.out.scss}
${app.out.css}
</x-sencha-command>
<uptodate property="compress.uptodate"
value="true"
srcfile="${app.out.scss}.tmp"
targetfile="${app.out.css}"/>
<x-update-css-array input="${app.out.css}"
compilerRefId="${compiler.ref.id}"/>
<if>
<x-is-true value="${compress.uptodate}"/>
<!--<x-is-true value="true"/>-->
<then>
<x-compress-css-files dir="${build.out.css.dir}"
prefix="${app.out.base.debug}"
outprefix="${app.out.base}"
preprocess="${build.css.preprocess}"
compress="${build.css.compress}"/>
<if>
<and>
<available file="${build.out.css.dir}/css-vars.js"/>
</and>
<then>
<if>
<not>
<equals arg1="${build.compression}" arg2=""/>
</not>
<then>
<x-compress-js srcFile="${build.out.css.dir}/css-vars.js"
outFile="${build.out.css.dir}/css-vars.js"/>
</then>
</if>
<if>
<not>
<equals arg1="${build.environment}" arg2="development"/>
</not>
<then>
<concat destfile="${build.out.js.path}" append="true">
<fileset dir="${build.out.css.dir}">
<include name="css-vars.js"/>
</fileset>
</concat>
</then>
</if>
</then>
</if>
</else>
</if>
</then>
<else>
<x-compass-compile
rubyPath="${build.ruby.path}"
dir="${compass.working.dir}"
trace="${compass.compile.trace}"
boring="${compass.compile.boring}"
force="${compass.compile.force}"
sassdir="${compass.sass.dir}"
cssdir="${compass.css.dir}"
config="${compass.config.file}"/>
<uptodate property="compress.uptodate"
value="true"
srcfile="${app.out.scss}.tmp"
targetfile="${app.out.css}"/>
<if>
<x-is-true value="${compress.uptodate}"/>
<!--<x-is-true value="true"/>-->
<then>
<x-compress-css-files dir="${build.out.css.dir}"
prefix="${app.out.base.debug}"
outprefix="${app.out.base}"
preprocess="${build.css.preprocess}"
compress="${build.css.compress}"/>
</then>
</if>
</else>
</if>
</else>
</if>
</x-run-if-true>
</x-run-if-true>
</else>
</if>
</target>
<!--

3
.sencha/app/sencha.cfg

@ -42,4 +42,5 @@ app.resource.paths=${app.dir}/resources
app.framework.version=5.1.1.451
app.cmd.version=6.1.2.15
app.cmd.version=6.6.0.13

35
.sencha/app/slice-impl.xml

@ -40,6 +40,7 @@
-all
and
sass
+skipWatch
+class-name-vars
+etc
+vars
@ -54,6 +55,7 @@
page
and
sass
+skipWatch
+ruby
-output=${app.example.out.ruby}
]]>
@ -68,7 +70,7 @@
</then>
</if>
<x-get-relative-path from="${app.example.dir}"
<x-get-relative-path from="${app.example.build.dir}"
to="${app.example.css}"
property="app.example.css.path"/>
@ -97,12 +99,15 @@
<x-is-true value="${app.sass.rhino}"/>
<then>
<x-fashion-compile
slicer="true"
file="${app.example.build.dir}"
toFile="${app.example.build.dir}"/>
</then>
<else>
<x-sencha-command>
fashion
-config=${app.dir}/app.json
-slicer=true
-compress=${build.css.compress}
-split=${build.css.selector.limit}
${app.example.build.dir}
@ -127,10 +132,22 @@
<!-- Produces a bootstrap.js file for ext 4.2 slicer pages -->
<target name="-generate-slicer-bootstrap" unless="framework.isV5">
<local name="relpath"/>
<local name="cmd.dir.normalized"/>
<x-get-relative-path from="${bootstrap.base.path}"
to="${framework.packages.dir}"
property="relpath"/>
<script language="javascript">
<![CDATA[
var dir = project.getProperty("cmd.dir") + '';
dir = dir.replace(/\\/g, '/');
if (dir.indexOf('/') !== 0) {
dir = '/' + dir;
}
project.setProperty("cmd.dir.normalized", dir);
]]>
</script>
<x-bootstrap file="${bootstrap.example.js}"
basedir="${bootstrap.base.path}"
includeBoot="true"
@ -140,7 +157,7 @@
overrideExcludeTags="">
<![CDATA[
Ext.Boot.loadSync([
"render.js",
"${cmd.dir.normalized}/ant/build/slicer/render.js",
"${relpath}/ext-theme-base/sass/example/manifest.js",
"${relpath}/ext-theme-base/sass/example/shortcuts.js",
"custom.js"
@ -182,6 +199,7 @@ Ext.Boot.loadSync([
<![CDATA[
slicer-manifest
-exclude=${manifest.root.excludes}
-jsonp=Ext.Microloader.setManifest
-removeBootstrapCssEntries=${remove.slicer.css.bootstrap.entries}
+ignoreDisabled
-basePath=${bootstrap.base.path}
@ -201,12 +219,13 @@ Ext.Boot.loadSync([
<echo>Capture theme image to ${build.capture.png}</echo>
<x-sencha-command>
<![CDATA[
theme
capture
-page=${app.example.theme.html}
-image=${build.capture.png}
-manifest=${build.capture.json}
]]>
theme
capture
-base=${app.example.build.dir}
-page=${app.example.theme.html}
-image=${build.capture.png}
-manifest=${build.capture.json}
]]>
</x-sencha-command>
</target>

59
.sencha/app/watch-impl.xml

@ -27,6 +27,24 @@
fork="true"/>
</target>
<target name="-watch-fashion" if="framework.isV6">
<x-fashion-watch
refName="fashion-watch"
inputFile="${app.out.scss}"
outputFile="${app.out.css}"
split="${build.css.selector.limit}"
compress="${build.css.compress}"
configFile="${build.out.json.path}"
saveFile="${app.dir}/${app.sass.generated.var}"
fork="true"/>
</target>
<target name="-stop-fashion-watch">
<x-fashion-watch
refName="fashion-watch"
stop="true"/>
</target>
<macrodef name="x-run-compass-watch">
<attribute name="directory"/>
<sequential>
@ -58,18 +76,35 @@
<target name="-before-watch"/>
<target name="-watch" depends="-init-web-server">
<x-ant-call target="${build.trigger.targets}"/>
<x-ant-call target="web-start" unless="skip.web.start">
<param name="enable.background.server" value="true"/>
</x-ant-call>
<x-ant-call target="${build.watcher.targets}">
<param name="build.id" value="${build.id}"/>
<param name="build.name" value="${build.name}"/>
</x-ant-call>
<x-ant-call target="web-stop" unless="skip.web.start">
<param name="enable.background.server" value="true"/>
</x-ant-call>
<x-ant-call target="-stop-compass-watch"/>
<local name="skip.sass.rebuild"/>
<condition property="skip.sass.rebuild" value="true">
<isset property="framework.isV6"/>
</condition>
<property name="skip.sass.rebuild" value="false"/>
<if>
<x-lock-file file="${watch.lock.file}" refId="lock.ref"/>
<then>
<x-ant-call target="${build.trigger.targets}"/>
<x-ant-call target="web-start" unless="skip.web.start">
<param name="enable.background.server" value="true"/>
</x-ant-call>
<x-ant-call target="${build.watcher.targets}">
<param name="build.id" value="${build.id}"/>
<param name="build.name" value="${build.name}"/>
<param name="skip.sass.rebuild" value="${skip.sass.rebuild}"/>
</x-ant-call>
<x-ant-call target="web-stop" unless="skip.web.start">
<param name="enable.background.server" value="true"/>
</x-ant-call>
<x-ant-call target="-stop-compass-watch"/>
<x-ant-call target="-stop-fashion-watch"/>
<x-unlock-file refId="lock.ref"/>
</then>
<else>
<echo level="error"
message="App watch is already running for this build profile."/>
</else>
</if>
</target>
<target name="-after-watch" depends="init"/>
</project>

106
.travis.yml

@ -1,81 +1,49 @@
sudo: required
language: node_js
node_js:
- "8"
matrix:
include:
- os: osx
osx_image: xcode12.4
language: node_js
node_js: "14.16.1"
env:
- ELECTRON_CACHE=$HOME/.cache/electron
- ELECTRON_BUILDER_CACHE=$HOME/.cache/electron-builder
- os: linux
sudo: required
services: docker
language: generic
branches:
only:
- master
os:
- linux
- osx
cache:
directories:
- node_modules
- $HOME/.electron
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-4.8
- node_modules
- $HOME/.cache/electron
- $HOME/.cache/electron-builder
before_install:
# native dependencies
- if [ $TRAVIS_OS_NAME == "linux" ]; then
sudo apt-get update -qq;
sudo apt-get install -qq libxml2-dev;
sudo apt-get install -qq libappindicator1;
sudo apt-get install -qq rpm;
- |
if [ "$TRAVIS_OS_NAME" == "osx" ]; then
mkdir -p /tmp/git-lfs && curl -L https://github.com/github/git-lfs/releases/download/v2.3.1/git-lfs-$([ "$TRAVIS_OS_NAME" == "linux" ] && echo "linux" || echo "darwin")-amd64-2.3.1.tar.gz | tar -xz -C /tmp/git-lfs --strip-components 1
export PATH="/tmp/git-lfs:$PATH"
fi
install:
- git config --global core.autocrlf input
- git reset --hard HEAD
- npm run sencha:clean
- git clone https://github.com/saenzramiro/rambox-build.git $TRAVIS_BUILD_DIR/build/production/Rambox/
- npm install
- npm uninstall electron-prebuilt
- npm i electron@$ELECTRON
- npm --prefix $TRAVIS_BUILD_DIR/build/production/Rambox/ install $TRAVIS_BUILD_DIR/build/production/Rambox/
before_script:
- git lfs pull
script:
- echo $TRAVIS_OS_NAME
- node --version
- npm --version
- npm run build:$TRAVIS_OS_NAME
deploy:
provider: releases
api_key:
secure: F7z4j9xzhpVyfovrf33jbVdW9dwgpIgbn85dxe8y/kZbQ9sAVU8LzoBZ3PlfeXmoV5CnSUa5j/fe8BmPKiG31kgAH7cktsCOgyOLggO1Sy+vnx7RQwwE/jzb7PzEqI2BP6TG/eOfylBxGBInWeaoSRfK3IRAvLHvvxY1eL4Wq/KRaanzMvh+JdCaStIKJSnI/rc9noI7vtOtgHot+F162s1G1k5/UcdbsfXWzotMVsonhlGgB/Jz9srnJpMpxYxaknR8UFPVRzOM5UzzMo64hXRUDnCFlYcTHcSAkvgKHI0SIPIS3kOdvgrYGavPLK2CAteQk7Dy1lHnEixmKPxG7eVAFwleUo8ePR82WXFkv5gacCvcrGrRLQ9nC/ygeMVgC5XxcHq3ykkcrstu5yjC1yEYFs23gA1Z4DIctwq1diyO72/FNxghV5ckN5WtJQs1QTT+Ec2NjLrWgFYuaEHYgAGopzTPN8gT9fyIv/lAq1S/l4P/z3EDS42UL+UTM77gyXSYShCKneDnFC34ATlYNDhJFRzLZ6qJG5UlOwrfXxUYeGUpQZlV41jg+VFWmPDAeQTMjGP5fRA3w1hFobBotBVyrtbcovTb4TFVTKJWOC/0wyiwku7YTY/nqMU/hR4IluTyRh9Z4NMn5xT5UW63OZd4DJvE573JxmJmnPc0fbo=
file_glob: true
file:
- "dist/*.zip"
- "dist/*.deb"
- "dist/*.tar.gz"
- "dist/*.AppImage"
- "dist/*.rpm"
- "dist/mac/*.zip"
- "dist/mac/*.dmg"
skip_cleanup: true
overwrite: true
prerelease: true
on:
repo: saenzramiro/rambox
tags: true
all_branches: true
notifications:
email:
recipients:
- rambox@protonmail.com
on_success: always
on_failure: always
webhooks:
urls:
- https://webhooks.gitter.im/e/0f214eb0d0017d3c5561
on_success: always # options: [always|never|change] default: always
on_failure: always # options: [always|never|change] default: always
on_start: never # options: [always|never|change] default: always
- |
if [ "$TRAVIS_OS_NAME" == "linux" ]; then
docker run --rm -ti \
--env-file <(env | grep -vE '\r|\n' | grep -iE 'DEBUG|NODE_|ELECTRON_|YARN_|NPM_|CI|CIRCLE|APPVEYOR_|CSC_|_TOKEN|_KEY|AWS_|STRIP|BUILD_') \
-v ${PWD}/build/production/Rambox/:/project \
-v ~/.cache/electron:/root/.cache/electron \
-v ~/.cache/electron-builder:/root/.cache/electron-builder \
electronuserland/builder \
/bin/bash -c "npm i && npm run build:linux"
else
cd $TRAVIS_BUILD_DIR/build/production/Rambox/
npm i
npm i cli-truncate
npm run build:osx
fi

6
Backers.md

@ -1,6 +0,0 @@
# Monthly Donators
[Martin Grünbaum](https://github.com/alathon)
Ivan Toshkov
[Simon Joda Stößer](https://github.com/SimJoSt)

216
CONTRIBUTING.md

@ -0,0 +1,216 @@
# Contributor's Guide
We welcome pull requests! Follow these steps to contribute:
1. Find an [issue](https://github.com/ramboxapp/community-edition/issues) that needs assistance.
1. Let us know you are working on it by posting a comment on the issue.
1. Follow the [Contribution Guidelines](#contribution-guidelines) to start working on the issue.
Working on your first Pull Request? You can learn how from this *free* series [How to Contribute to an Open Source Project on GitHub](https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github)
##### If you've found a bug that is not on the board, [follow these steps](README.md#found-a-bug).
---
## Contribution Guidelines
### Setup
- [Prerequisites](#prerequisites)
- [Forking the Project](#forking-the-project)
- [Create a Branch](#create-a-branch)
- [Set Up rambox](#set-up-rambox)
### Create
- [Make Changes](#make-changes)
- [Run The Test Suite](#run-the-test-suite)
### Submit
- [Creating a Pull Request](#creating-a-pull-request)
- [Common Steps](#common-steps)
- [How We Review and Merge Pull Requests](#how-we-review-and-merge-pull-requests)
- [How We Close Stale Issues](#how-we-close-stale-issues)
- [Next Steps](#next-steps)
- [Other Resources](#other-resources)
### Prerequisites
| Prerequisite | Version |
| ------------------------------------------------------------- | ------- |
| [Sencha](https://www.sencha.com/products/extjs/cmd-download/) | `=6.6.0.13` |
| [Ruby](https://www.ruby-lang.org/en/downloads/) | `=2.3` |
| [Node.js](https://nodejs.org) | `~ ^4.0.0` |
| npm (comes with Node) | `~ ^3.8.7` |
> _Updating to the latest releases is recommended_.
If Node.js, ruby, or sencha cmd is already installed on your machine, run the following commands to validate the versions:
```shell
node -v
ruby -v
sencha
```
If your versions are lower than the prerequisite versions, you should update.
### Forking the Project
#### Setting Up Your System
1. Install [Git](https://git-scm.com/) or your favorite Git client.
1. (Optional) [Setup an SSH Key](https://help.github.com/articles/generating-an-ssh-key/) for GitHub.
#### Forking rambox
1. Go to the top level rambox repository: <https://github.com/ramboxapp/community-edition>
1. Click the "Fork" Button in the upper right hand corner of the interface ([More Details Here](https://help.github.com/articles/fork-a-repo/))
1. After the repository (repo) has been forked, you will be taken to your copy of the rambox repo at <https://github.com/yourUsername/community-edition>
#### Cloning Your Fork
1. Open a Terminal / Command Line / Bash Shell in your projects directory (_i.e.: `/yourprojectdirectory/`_)
1. Clone your fork of rambox
- `git clone https://github.com/yourUsername/community-edition.git`
**(make sure to replace `yourUsername` with your GitHub username)**
This will download the entire rambox repo to your projects directory.
#### Setup Your Upstream
1. Change directory to the new rambox directory (`cd community-edition`)
1. Add a remote to the official rambox repo:
- `git remote add upstream https://github.com/ramboxapp/community-edition.git`
Congratulations, you now have a local copy of the rambox repo! :tada:
### Create a Branch
Before you start working, you will need to create a separate branch specific to the issue / feature you're working on. You will push your work to this branch.
#### Naming Your Branch
Name the branch something like `fix/xxx` or `feature/xxx` where `xxx` is a short description of the changes or feature you are attempting to add. For example
`fix/email-login` would be a branch where you fix something specific to email login.
#### Adding Your Branch
To create a branch on your local machine (and switch to this branch):
```shell
git checkout -b [name_of_your_new_branch]
```
and to push to GitHub:
```shell
git push origin [name_of_your_new_branch]
```
**If you need more help with branching, take a look at [this](https://github.com/Kunena/Kunena-Forum/wiki/Create-a-new-branch-with-git-and-manage-branches).**
### Set Up rambox
Once you have rambox cloned, before you start the application, you first need to install all of the dependencies:
```bash
# Install NPM dependencies
npm install
```
```bash
# Compile the files...
sencha app watch
npm start # in a new terminal
```
### Make Changes
This bit is up to you!
#### How to find the code in the rambox codebase to fix/edit
The best way to find out any code you wish to change/add or remove is using the GitHub search bar at the top of the repository page.
For example, you could search for a challenge name and the results will display all the files along with line numbers.
Then you can proceed to the files and verify this is the area that you were looking forward to edit.
Always feel free to reach out to the chat room when you are not certain of any thing specific in the code.
#### Adding or Editing Services
The services are stored inside the file `./api/services.json` in the `gh-pages` branch:
https://github.com/ramboxapp/community-edition/blob/gh-pages/api/services.json
Add your service to the *BOTTOM* of the array.
To see these changes you'll need to stop your `npm start` and `sencha app watch`, and then rerun those.
### Creating a Pull Request
#### What is a Pull Request?
A pull request (PR) is a method of submitting proposed changes to the rambox repo (or any repo, for that matter).
You will make changes to copies of thefiles which make up rambox in a personal fork, then apply to have them accepted by rambox proper.
#### Important: ALWAYS EDIT ON A BRANCH
Take away only one thing from this document: Never, **EVER** make edits to the `master` branch.
ALWAYS make a new branch BEFORE you edit files.
This is critical, because your copy of `master` will be forever sullied and the only way to fix it is a difficult hard-reset and force-push process, or deleting your fork and re-forking.
### Common Steps
1. Once the edits have been committed, you will be prompted to create a pull request on your fork's GitHub Page.
1. By default, all pull requests should be against the rambox main repo, `master` branch.
- **Make sure that your Base Fork is set to ramboxapp/community-edition when raising a Pull Request.**
1. Submit a pull request.
1. The title (also called the subject) of your PR should be descriptive of your changes and succinctly indicates what is being fixed.
- **Do not add the issue number in the PR title or commit message.**
- Examples: `Added Service servicename` `Correct typo in menu`
1. In the body of your PR include a more detailed summary of the changes you made and why.
- If the PR is meant to fix an existing bug/issue then, at the end of your PR's description, append the keyword `closes` and #xxxx (where xxxx is the issue number).
- Example: `closes #1337`. This tells GitHub to automatically close the existing issue, if the PR is merged.
1. Indicate if you have tested on a local copy of the site or not.
### How We Review and Merge Pull Requests
Rambox has a team of volunteer Issue Moderators. These Issue Moderators routinely go through open pull requests in a process called [Quality Assurance](https://en.wikipedia.org/wiki/Quality_assurance) (QA).
1. If an Issue Moderator QA's a pull request and confirms that the new code does what it is supposed without seeming to introduce any new bugs, they will comment: `"LGTM" which means "Looks good to me."`
1. Another Issue Moderator will QA the same pull request.
- Once they have also confirmed that the new code does what it is supposed to without seeming to introduce any new bugs, they will merge the pull request.
If you would like to apply to join our Issue Moderator team - which is a Core Team position - message [@BerkeleyTrue](https://gitter.im/berkeleytrue) with links to 5 of your pull requests that have been accepted and 5 issues where you have helped someone else through commenting or QA'ing.
### How We Close Stale Issues
We will close any issues or pull requests that have been inactive for more than 15 days, except those that match the following criteria:
- Bugs that are confirmed
- Pull requests that are waiting on other pull requests to be merged
- Features that are a part of a GitHub project
### Next Steps
#### If your PR is accepted
Once your PR is accepted, you may delete the branch you created to submit it.
This keeps your working fork clean.
You can do this with a press of a button on the GitHub PR interface. You can delete the local copy of the branch with: `git branch -D branch/to-delete-name`
#### If your PR is rejected
Don't despair! You should receive solid feedback as to why it was rejected and what changes are needed.
Many Pull Requests, especially first Pull Requests, require correction or updating.
If you have used the GitHub interface to create your PR, you will need to close your PR, create a new branch, and re-submit.
If you have a local copy of the repo, you can make the requested changes and amend your commit with: `git commit --amend`
This will update your existing commit.
When you push it to your fork you will need to do a force push to overwrite your old commit: `git push --force`
Be sure to post in the PR conversation that you have made the requested changes.

283
README.md

@ -1,166 +1,72 @@
<h1 align="center">
<br>
<a href="http://rambox.pro"><img src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/Icon.png" width="256px" alt="Rambox"></a>
<br>
Rambox
<br>
<br>
</h1>
<h4 align="center">Free, Open Source and Cross Platform messaging and emailing app that combines common web applications into one.</h4>
<p align="center">
<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=WU75QWS7LH2CA" target="_blank"><img src="https://img.shields.io/badge/Donate-PayPal-green.svg" alt="Donate with PayPal"></a>
<a href="https://www.gnu.org/licenses/gpl-3.0.en.html" target="_blank"><img src="https://img.shields.io/github/license/saenzramiro/rambox.svg" alt="GNU GPL v3"></a>
<a href="https://gitter.im/saenzramiro/rambox" target="_blank"><img src="https://badges.gitter.im/saenzramiro/rambox.svg" alt="Gitter"></a>
<a href="https://github.com/saenzramiro/rambox/releases/latest" target="_blank"><img src="https://img.shields.io/github/release/saenzramiro/rambox.svg" alt="Release"></a>
<a target="_blank" href="https://crowdin.com/project/rambox"><img src="https://d322cqt584bo4o.cloudfront.net/rambox/localized.svg"></a>
</p>
<p align="center">
<a href="https://travis-ci.org/saenzramiro/rambox" target="_blank"><img src="https://travis-ci.org/saenzramiro/rambox.svg?branch=master" alt="Travis CI"></a>
<a href="https://ci.appveyor.com/project/saenzramiro/rambox" target="_blank"><img src="https://ci.appveyor.com/api/projects/status/3kk9ixjgxwrh7yfy?svg=true" alt="AppVeyor CI"></a>
<a href="https://david-dm.org/saenzramiro/rambox" title="Dependency status"><img src="https://david-dm.org/saenzramiro/rambox.svg"/></a>
<a href="https://david-dm.org/saenzramiro/rambox#info=devDependencies" title="devDependency status"><img src="https://david-dm.org/saenzramiro/rambox/dev-status.svg"/></a>
</p>
<h5 align="center">Available for Windows, Mac and Linux.</h5>
<h5 align="center"><a href="http://rambox.pro/#download" target="_blank"><img src="https://cdn.rawgit.com/saenzramiro/rambox/gh-pages/images/img-download.svg" width="250" alt="DOWNLOAD HERE"></a></h5>
<h6 align="center">Logo designed by <a href="http://andyur.com/" target="_blank">Andriy Yurchenko</a></h6>
----------
# EOL
The Community Edition of Rambox is no longer maintained. We highly recommend that you update to the new version of Rambox, which has a FREE plan with all the features you already use and much more!
Visit: https://rambox.app/download
Thank you so much for all the users who contribute to this project all these years.
[Read our blog post to know more about our new Rambox.](https://rambox.medium.com/hello-2022-hello-new-rambox-4bdef5d6c3b8)
---
<div align="center">
<h1>
<br />
<a href="https://rambox.pro"><img src="./resources/Icon.png" width="256px" alt="Rambox" /></a><br />
Rambox CE
<br /><br/>
</h1>
<h4>Free, Open Source and Cross Platform messaging and emailing app that combines common web applications into one.</h4>
<p>
<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=WU75QWS7LH2CA" target="_blank"><img src="https://img.shields.io/badge/Donate-PayPal-green.svg" alt="Donate with PayPal" /></a>
<a href="https://www.gnu.org/licenses/gpl-3.0.en.html" target="_blank"><img src="https://img.shields.io/github/license/saenzramiro/rambox.svg" alt="GNU GPL v3" /></a>
<a href="https://gitter.im/saenzramiro/rambox" target="_blank"><img src="https://badges.gitter.im/saenzramiro/rambox.svg" alt="Gitter" /></a>
<a href="https://github.com/saenzramiro/rambox/releases/latest" target="_blank">
<img src="https://img.shields.io/github/release/saenzramiro/rambox.svg" alt="Release" />
</a>
<a target="_blank" href="https://crowdin.com/project/rambox"><img src="https://d322cqt584bo4o.cloudfront.net/rambox/localized.svg" /></a>
</p>
<p>
<a href="https://travis-ci.org/saenzramiro/rambox" target="_blank"><img src="https://travis-ci.org/saenzramiro/rambox.svg?branch=master" alt="Travis CI" /></a>
<a href="https://ci.appveyor.com/project/saenzramiro/rambox" target="_blank"><img src="https://ci.appveyor.com/api/projects/status/3kk9ixjgxwrh7yfy?svg=true" alt="AppVeyor CI" /></a>
<a href="https://david-dm.org/saenzramiro/rambox" title="Dependency status"><img src="https://david-dm.org/saenzramiro/rambox.svg" /></a>
<a href="https://david-dm.org/saenzramiro/rambox#info=devDependencies" title="devDependency status"><img src="https://david-dm.org/saenzramiro/rambox/dev-status.svg" /></a>
</p>
<h5>Available for Windows, Mac and Linux.</h5>
<h5><a href="https://rambox.pro/#ce" target="_blank"><img src="https://cdn.rawgit.com/saenzramiro/rambox/gh-pages/images/img-download.svg" width="250" alt="DOWNLOAD HERE" /></a></h5>
<h6>Logo designed by <a href="https://www.linkedin.com/in/andriyyurchenko/" target="_blank">Andriy Yurchenko</a></h6>
</div>
---
## Table of Contents
- [Screenshot](#screenshot)
- [Services available - 89](#services-available---95)
- [Apps available](#apps-available)
- [Features](#features)
- [Privacy](#privacy)
- [Donations](#donations)
- [Translations](#translations)
- [Install on Linux - Steps](#install-on-linux---steps)
- [To Do](#to-do)
- [Getting Involved](#getting-involved)
- [Getting Started](#getting-started)
- [Technologies](#technologies)
- [Environment](#environment)
- [Quickstart](#quickstart)
- [Compile on Ubuntu](#compile-on-ubuntu)
- [Contributing](#contributing)
- [Quickstart](#quickstart)
- [Disclosure](#disclosure)
- [Licence](#licence)
----------
---
## Screenshot
![Rambox](https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/screenshots/mac.png)
## Services available - 96
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/whatsapp.png" alt="WhatsApp" title="WhatsApp">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/messenger.png" alt="Messenger" title="Messenger">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/skype.png" alt="Skype" title="Skype">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/slack.png" alt="Slack" title="Slack">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/hangouts.png" alt="Hangouts" title="Hangouts">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/telegram.png" alt="Telegram" title="Telegram">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/wechat.png" alt="WeChat" title="WeChat">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/gmail.png" alt="Gmail" title="Gmail">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/inbox.png" alt="Inbox" title="Inbox">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/hipchat.png" alt="HipChat" title="HipChat">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/allo.png" alt="Allo" title="Allo">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/chatwork.png" alt="ChatWork" title="ChatWork">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/groupme.png" alt="GroupMe" title="GroupMe">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/grape.png" alt="Grape" title="Grape">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/gitter.png" alt="Gitter" title="Gitter">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/steam.png" alt="Steam" title="Steam">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/discord.png" alt="Discord" title="Discord">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/noysi.png" alt="Noysi" title="Noysi">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/outlook.png" alt="Outlook" title="Outlook">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/outlook365.png" alt="Outlook 365" title="Outlook 365">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/tutanota.png" alt="TutaNota" title="TutaNota">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/hushmail.png" alt="Hushmail" title="Hushmail">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/bearychat.png" alt="BearyChat" title="BearyChat">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/aol.png" alt="Aol" title="Aol">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/sync.png" alt="Sync" title="Sync">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/wire.png" alt="Wire" title="Wire">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/rocketchat.png" alt="Rocket Chat" title="Rocket Chat">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/missive.png" alt="Missive" title="Missive">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/yahoo.png" alt="Yahoo! Mail" title="Yahoo! Mail">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/ryver.png" alt="Ryver" title="Ryver">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/yandex.png" alt="Yandex Mail" title="Yandex Mail">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/dasher.png" alt="Dasher" title="Dasher">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/dingtalk.png" alt="DingTalk" title="DingTalk">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/flowdock.png" alt="FlowDock" title="FlowDock">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/mattermost.png" alt="Mattermost" title="Mattermost">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/voxer.png" alt="Voxer" title="Voxer">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/glip.png" alt="Glip" title="Glip">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/yahoomessenger.png" alt="Yahoo! Messenger" title="Yahoo! Messenger">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/mysms.png" alt="mysms" title="mysms">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/icq.png" alt="ICQ" title="ICQ">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/tweetdeck.png" alt="TweetDeck" title="TweetDeck">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/zinc.png" alt="Zinc" title="Zinc">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/freenode.png" alt="FreeNode" title="FreeNode">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/mightytext.png" alt="MightyText" title="MightyText">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/zohoemail.png" alt="Zoho Email" title="Zoho Email">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/zohochat.png" alt="Zoho Chat" title="Zoho Chat">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/roundcube.png" alt="Roundcube" title="Roundcube">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/horde.png" alt="Horde" title="Horde">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/squirrelmail.png" alt="SquirrelMail" title="SquirrelMail">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/zimbra.png" alt="Zimbra" title="Zimbra">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/hootsuite.png" alt="Hootsuite" title="Hootsuite">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/amium.png" alt="Amium" title="Amium">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/rainloop.png" alt="RainLoop" title="RainLoop">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/icloud.png" alt="iCloud Mail" title="iCloud Mail">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/irccloud.png" alt="IRC Cloud" title="IRC Cloud">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/kiwi.png" alt="Kiwi IRC" title="Kiwi IRC">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/smooch.png" alt="Smooch" title="Smooch">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/crisp.png" alt="Crisp" title="Crisp">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/flock.png" alt="Flock" title="Flock">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/openmailbox.png" alt="Openmailbox" title="Openmailbox">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/typetalk.png" alt="Typetalk" title="Typetalk">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/drift.png" alt="Drift" title="Drift">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/spark.png" alt="Cisco Spark" title="Cisco Spark">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/fleep.png" alt="Fleep" title="Fleep">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/socialcast.png" alt="Socialcast" title="Socialcast">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/riot.png" alt="Riot" title="Riot">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/pushbullet.png" alt="Pushbullet" title="Pushbullet">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/movim.png" alt="Movim" title="Movim">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/kaiwa.png" alt="Kaiwa" title="Kaiwa">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/zyptonite.png" alt="Zyptonite" title="Zyptonite">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/linkedin.png" alt="LinkedIn" title="LinkedIn">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/lounge.png" alt="The Lounge" title="The Lounge">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/kezmo.png" alt="Kezmo" title="Kezmo">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/teams.png" alt="Teams" title="Teams">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/xing.png" alt="Xing" title="Xing">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/workplace.png" alt="Workplace" title="Workplace">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/fastmail.png" alt="FastMail" title="FastMail">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/hibox.png" alt="Hibox" title="Hibox">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/jandi.png" alt="Jandi" title="Jandi">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/threema.png" alt="Threema" title="Threema">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/messengerpages.png" alt="Messenger for Pages" title="Messenger for Pages">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/vk.png" alt="VK Messenger" title="VK Messenger">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/mastodon.png" alt="Mastodon" title="Mastodon">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/teamworkchat.png" alt="Teamwork Chat" title="Teamwork Chat">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/clocktweets.png" alt="ClockTweets" title="ClockTweets">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/intercom.png" alt="Intercom" title="Intercom">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/googlevoice.png" alt="Voice" title="Voice">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/sandstorm.png" alt="Sandstorm" title="Sandstorm">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/gadugadu.png" alt="Gadu-Gadu" title="Gadu-Gadu">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/mailru.png" alt="Mail.Ru" title="Mail.Ru">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/kune.png" alt="Kune" title="Kune">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/zulip.png" alt="Zulip" title="Zulip">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/stride.png" alt="Stride" title="Stride">
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
![Rambox](./resources/screenshots/mac.png)
## Apps available
Visit our website https://rambox.app/#apps and select the "Community-Edition" filter to see all the apps available.
## Features
@ -179,80 +85,55 @@
- [x] Custom Code Injection.
- [x] Keyboard Shortcuts.
- [x] Proxy.
- [x] Switch from horizontal to vertical tab bar.
## Privacy
No personal information will be saved
Sessions will persist using the [partition:persist](http://electron.atom.io/docs/api/web-view-tag/#partition) attribute for Webviews. So every time you open Rambox, your sessions will keep alive until you remove the service.
Sessions will persist using the [partition:persist](https://electronjs.org/docs/api/webview-tag#partition) attribute for Webviews.
So every time you open Rambox, your sessions will keep alive until you remove the service.
Sync feature use Auth0 for Single Sign On & Token Based Authentication and to store the services that user is using (and the configuration for each service). You are always welcome to check the code! ;)
Sync feature use Auth0 for Single Sign On & Token Based Authentication and to store the services that user is using (and the configuration for each service).
You are always welcome to check the code! ;)
## Donations
| Type | URL/Wallet |
|--------------------|:------------------------------------------------------------------------------------------:|
| PayPal | [HERE](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=WU75QWS7LH2CA) |
| Cryptocurrencies | [HERE](https://www.vaulty.io/v/b6480279-af28-4855-868c-17e5cb0ae7fa) |
| Type | URL/Wallet |
| ---------------- | :----------------------------------------------------------------------------------------: |
| Credit Cards | [HERE](https://rambox.app/donate.html) |
| Cryptocurrencies | [HERE](https://www.vaulty.io/v/b6480279-af28-4855-868c-17e5cb0ae7fa) |
## Translations
Help us translate Rambox on https://crowdin.com/project/rambox/invite.
## [Install on Linux - Steps](https://github.com/saenzramiro/rambox/wiki/Install-on-Linux)
## [To Do](https://github.com/saenzramiro/rambox/blob/master/TODO.md)
## Getting Involved
Want to report a bug, request a feature, contribute to or translate Rambox? We need all the help we can get! Fork and work!
## Getting Started
If you're comfortable getting up and running from a `git clone`, this method is for you.
#### Technologies:
* Sencha Ext JS 5.1.1.451
* Electron
* Node JS
#### Environment:
Help us translate Rambox on <https://crowdin.com/project/rambox/invite>.
* Sencha Cmd 6.1.2.15 (make sure to check "Compass extension" during install if you don't have installed yet)
* Ruby 2.3
* NPM 3.8.7
* Node.js 4.0.0
## [Install on Linux - Steps](https://github.com/ramboxapp/community-edition/wiki/Install-on-Linux)
#### Quickstart:
## [Contributing](./CONTRIBUTING.md)
1. `git clone https://github.com/saenzramiro/rambox.git`
2. `npm install`
3. Configure `env-sample.js` and rename it to `env.js`.
4. `npm run sencha:compile`
5. `npm start`
Want to report a bug, request a feature, contribute to or translate Rambox?
We need all the help we can get!
Fork and work!
#### Compile on Ubuntu:
### Quickstart
These instructions were tested with Ubuntu 17.04.
1. Install dependencies: `sudo apt install nodejs-legacy npm git`
2. Build and install electron: `sudo npm install electron-prebuilt -g`
3. Install Sencha Cmd (non-free): https://www.sencha.com/products/extjs/cmd-download/
4. Clone repository: `git clone https://github.com/saenzramiro/rambox.git`
5. Install npm dependencies: `npm install`
6. Configure `env-sample.js` and rename it to `env.js`.
7. Compile: `npm run sencha:compile`
8. Start program: `npm start`
```shell
git clone https://github.com/saenzramiro/rambox.git
cd rambox
npm install
sencha app watch
npm start
```
See [Contributing.md](./CONTRIBUTING.md) for more detailed information about getting set up.
-------------------
---
Disclosure
-------------------
## Disclosure
Rambox is not affiliated with any of the messaging apps offered.
Licence
-------------------
## Licence
[GNU GPL v3](https://github.com/saenzramiro/rambox/LICENSE)
[GNU GPL v3](https://github.com/ramboxapp/community-edition/blob/master/LICENSE)

6
TODO.md

@ -1,6 +0,0 @@
## To Do
- Change theme.
- Deeplink to add new service.
- Dock Menu (http://electron.atom.io/docs/tutorial/desktop-environment-integration/#custom-dock-menu-os-x)
- Crash Reporter.

53
app.js

@ -15,12 +15,23 @@ Ext.application({
// auto update logic
const ipc = require('electron').ipcRenderer;
const { ContextMenuBuilder, ContextMenuListener } = require('electron-contextmenu-wrapper');
const contextMenuBuilder = new ContextMenuBuilder();
const contextMenuListener = new ContextMenuListener(function(event, info) {
contextMenuBuilder.showPopupMenu(info);
});
ipc.on('showAbout', function(event, message) {
!Ext.cq1('about') ? Ext.create('Rambox.view.main.About') : '';
});
ipc.on('showPreferences', function(event, message) {
!Ext.cq1('preferences') ? Ext.create('Rambox.view.preferences.Preferences').show() : '';
});
ipc.on('grantPermissions', async function() {
await require('electron').remote.systemPreferences.askForMediaAccess('microphone');
await require('electron').remote.systemPreferences.askForMediaAccess('camera');
});
ipc.on('autoUpdater:check-update', function() {
Rambox.app.checkUpdate();
});
@ -40,7 +51,8 @@ ipc.on('autoUpdater:update-available', function() {
,buttons: Ext.Msg.OK
});
});
ipc.on('autoUpdater:update-downloaded', function(e, releaseNotes, releaseName, releaseDate, updateURL) {
ipc.on('autoUpdater:update-downloaded', function(e, info) {
console.log('Update downloaded!', info);
Ext.cq1('app-main').addDocked({
xtype: 'toolbar'
,dock: 'top'
@ -49,18 +61,18 @@ ipc.on('autoUpdater:update-downloaded', function(e, releaseNotes, releaseName, r
'->'
,{
xtype: 'label'
,html: '<b>New version ready to install ('+releaseName+')!</b> It will be installed the next time Rambox is relaunched.'
,html: '<b>New version is ready to be installed ('+info.version+')!</b> Click the following button to install it now.'
}
,{
xtype: 'button'
,text: 'Relaunch Now'
,text: 'Install now'
,handler: function(btn) { ipc.send('autoUpdater:quit-and-install'); }
}
,{
xtype: 'button'
,text: 'Changelog'
,ui: 'decline'
,href: 'https://github.com/saenzramiro/rambox/releases/tag/'+releaseName
,href: 'https://github.com/ramboxapp/download/releases/latest'
}
,'->'
,{
@ -127,7 +139,40 @@ ipc.on('reloadCurrentService', function(e) {
var tab = Ext.cq1('app-main').getActiveTab();
if ( tab.id !== 'ramboxTab' ) tab.reloadService();
});
// Toggle Status Bar
ipc.on('toggleStatusBar', function() {
var tab = Ext.cq1('app-main').getActiveTab();
if ( tab.id !== 'ramboxTab' ) {
tab.down('statusbar').closed ? tab.setStatusBar(tab.record.get('statusbar')) : tab.closeStatusBar();
}
});
// Focus the current service when Alt + Tab or click in webviews textfields
window.addEventListener('focus', function() {
if(Ext.cq1("app-main")) Ext.cq1("app-main").getActiveTab().down('component').el.dom.focus();
});
// Handles zoom from menu
ipc.on('resetzoom-webview', function() {
var tabPanel = Ext.cq1('app-main');
if ( tabPanel.items.indexOf(tabPanel.getActiveTab()) === 0 ) return false;
tabPanel.getActiveTab().resetZoom();
});
ipc.on('zoomin-webview', function() {
var tabPanel = Ext.cq1('app-main');
if ( tabPanel.items.indexOf(tabPanel.getActiveTab()) === 0 ) return false;
tabPanel.getActiveTab().zoomIn();
});
ipc.on('zoomout-webview', function() {
var tabPanel = Ext.cq1('app-main');
if ( tabPanel.items.indexOf(tabPanel.getActiveTab()) === 0 ) return false;
tabPanel.getActiveTab().zoomOut();
});
ipc.on('shortcut:tab', function(e, arg) {
var tabPanel = Ext.cq1('app-main');
if ( arg >= tabPanel.items.indexOf(Ext.getCmp('tbfill')) ) arg++;
tabPanel.setActiveTab(arg);
});

10
app.json

@ -109,9 +109,6 @@
{
"path": "resources/js/loadscreen.js"
},
{
"path": "env.js"
},
{
"path": "app.js",
"bundle": true
@ -254,7 +251,7 @@
*
*/
"output": {
"base": "${workspace.build.dir}/${build.environment}/${app.name}",
"base": "../rambox-build",
"appCache": {
"enable": true
}
@ -290,7 +287,10 @@
*/
"resources": [
"electron",
"masterpassword.html"
"package.json",
"package-lock.json",
"masterpassword.html",
"screenselector.html"
],
/**

416
app/Application.js

@ -4,8 +4,7 @@ Ext.define('Rambox.Application', {
,name: 'Rambox'
,requires: [
'Rambox.ux.Auth0'
,'Rambox.util.MD5'
'Rambox.util.MD5'
,'Ext.window.Toast'
,'Ext.util.Cookies'
]
@ -23,190 +22,211 @@ Ext.define('Rambox.Application', {
,config: {
totalServicesLoaded: 0
,totalNotifications: 0
,googleURLs: []
}
,launch: function () {
// 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());
// 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')});
// Initialize Auth0
if ( auth0Cfg.clientID !== '' && auth0Cfg.domain !== '' ) Rambox.ux.Auth0.init();
// 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);
// Check for updates
if ( require('electron').remote.process.argv.indexOf('--without-update') === -1 ) Rambox.app.checkUpdate(true);
// Add shortcuts to switch services using CTRL + Number
var map = new Ext.util.KeyMap({
target: document
,binding: [
{
key: "\t"
,ctrl: true
,alt: false
,shift: false
,handler: function(key) {
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);
}
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)
}
,{
key: "\t"
,ctrl: true
,alt: false
,shift: true
,handler: function(key) {
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 );
})
})();
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: '<b>Rambox CE needs permissions to use Microphone and Camera for the apps.</b>'
}
}
,{
key: Ext.event.Event.PAGE_DOWN
,ctrl: true
,alt: false
,shift: false
,handler: function(key) {
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);
,{
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);
}
}
}
,{
key: Ext.event.Event.PAGE_UP
,ctrl: true
,alt: false
,shift: false
,handler: function(key) {
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 );
,{
xtype: 'button'
,text: 'Never ask again'
,ui: 'decline'
,handler: function(btn) {
Ext.cq1('app-main').removeDocked(btn.up('toolbar'), true);
localStorage.setItem('hideMacPermissions', true);
}
}
}
,{
key: [Ext.event.Event.NUM_PLUS, Ext.event.Event.NUM_MINUS, 187, 189]
,ctrl: true
,alt: false
,shift: false
,handler: function(key) {
var tabPanel = Ext.cq1('app-main');
if ( tabPanel.items.indexOf(tabPanel.getActiveTab()) === 0 ) return false;
key === Ext.event.Event.NUM_PLUS || key === 187 ? tabPanel.getActiveTab().zoomIn() : tabPanel.getActiveTab().zoomOut();
,'->'
,{
glyph: 'xf00d@FontAwesome'
,baseCls: ''
,style: 'cursor:pointer;'
,handler: function(btn) { Ext.cq1('app-main').removeDocked(btn.up('toolbar'), true); }
}
}
,{
key: [Ext.event.Event.NUM_ZERO, '0']
,ctrl: true
,alt: false
,shift: false
,handler: function(key) {
var tabPanel = Ext.cq1('app-main');
if ( tabPanel.items.indexOf(tabPanel.getActiveTab()) === 0 ) return false;
]
});
}
tabPanel.getActiveTab().resetZoom();
}
}
,{
key: "123456789"
,ctrl: true
,alt: false
,handler: function(key) {
key = key - 48;
if ( key >= Ext.cq1('app-main').items.indexOf(Ext.getCmp('tbfill')) ) key++;
Ext.cq1('app-main').setActiveTab(key);
}
}
,{
key: 188 // comma
,ctrl: true
,alt: false
,handler: function(key) {
Ext.cq1('app-main').setActiveTab(0);
}
}
,{
key: Ext.event.Event.F1
,ctrl: false
,alt: false
,shift: false
,handler: function(key) {
var btn = Ext.getCmp('disturbBtn');
btn.toggle();
Ext.cq1('app-main').getController().dontDisturb(btn, true);
}
}
,{
key: Ext.event.Event.F2
,ctrl: false
,alt: false
,shift: false
,handler: function(key) {
var btn = Ext.getCmp('lockRamboxBtn');
Ext.cq1('app-main').getController().lockRambox(btn);
}
}
]
});
// Mouse Wheel zooming
document.addEventListener('mousewheel', function(e) {
if( e.ctrlKey ) {
var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
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: '<b>Services couldn\'t be loaded, some Rambox features will not be available.</b>'
}
,{
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); }
}
]
});
}
// 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-extjs') || 'en')});
// Set Google URLs
Rambox.app.config.googleURLs = [
"accounts.google.com/ServiceLogin",
"accounts.google.com/signin",
"accounts.google.com/_/lookup/accountlookup",
"accounts.google.com/o/oauth2",
"accounts.google.com/_/signin",
"accounts.google.com/AddSession?",
"accounts.google.com/_/"
];
// 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');
if ( tabPanel.items.indexOf(tabPanel.getActiveTab()) === 0 ) return false;
if ( delta === 1 ) { // Zoom In
tabPanel.getActiveTab().zoomIn();
} else { // Zoom Out
tabPanel.getActiveTab().zoomOut();
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);
});
// Mouse Wheel zooming
document.addEventListener('mousewheel', function(e) {
if( e.ctrlKey ) {
var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
var tabPanel = Ext.cq1('app-main');
if ( tabPanel.items.indexOf(tabPanel.getActiveTab()) === 0 ) return false;
if ( delta === 1 ) { // Zoom In
tabPanel.getActiveTab().zoomIn();
} else { // Zoom Out
tabPanel.getActiveTab().zoomOut();
}
}
}
});
// Define default value
if ( localStorage.getItem('dontDisturb') === null ) localStorage.setItem('dontDisturb', false);
ipc.send('setDontDisturb', localStorage.getItem('dontDisturb')); // We store it in config
});
if ( localStorage.getItem('locked') ) {
console.info('Lock Rambox:', 'Enabled');
Ext.cq1('app-main').getController().showLockWindow();
}
// Define default value
if ( localStorage.getItem('dontDisturb') === null ) localStorage.setItem('dontDisturb', false);
ipc.send('setDontDisturb', localStorage.getItem('dontDisturb')); // We store it in config
// Remove spinner
Ext.get('spinner').destroy();
if ( localStorage.getItem('locked') ) {
console.info('Lock Rambox:', 'Enabled');
Ext.cq1('app-main').getController().showLockWindow();
}
Ext.getStore('Services').load();
});
}
,updateTotalNotifications: function( newValue, oldValue ) {
@ -227,60 +247,6 @@ Ext.define('Rambox.Application', {
}
,checkUpdate: function(silence) {
console.info('Checking for updates...');
Ext.Ajax.request({
url: 'http://rambox.pro/api/latestversion.json'
,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.version) ) {
console.info('New version is available', json.version);
Ext.cq1('app-main').addDocked({
xtype: 'toolbar'
,dock: 'top'
,ui: 'newversion'
,items: [
'->'
,{
xtype: 'label'
,html: '<b>'+locale['app.update[0]']+'</b> ('+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/saenzramiro/rambox/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/saenzramiro/rambox/releases/tag/'+json.version
}
,'->'
,{
glyph: 'xf00d@FontAwesome'
,baseCls: ''
,style: 'cursor:pointer;'
,handler: function(btn) { Ext.cq1('app-main').removeDocked(btn.up('toolbar'), true); }
}
]
});
if ( process.platform === 'win32' ) 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.');
}
});
ipc.send('autoUpdater:check-for-updates');
}
});

29
app/README.md

@ -0,0 +1,29 @@
# ./controller
This folder contains the application's global controllers.
ViewControllers are located alongside their respective view class in `./view`.
These controllers are used for routing and other activities that span all views.
# ./model
This folder contains the application's (data) Model classes.
# ./view
This folder contains the views as well as ViewModels and ViewControllers depending on the application's architecture.
Pure MVC applications may not have ViewModels, for example.
For MVCVM applications or MVC applications that use ViewControllers, the following directory structure is recommended:
```text
./view/
foo/ # Some meaningful grouping of one or more views
Foo.js # The view class
FooController.js # The controller for Foo (a ViewController)
FooModel.js # The ViewModel for Foo
```
This structure helps keep these closely related classes together and easily identifiable in most tabbed IDE's or text editors.
# ./store
This folder contains any number of store instances or types that can then be reused in the application.

30
app/Readme.md

@ -1,30 +0,0 @@
# ./controller
This folder contains the application's global controllers. ViewControllers are located
alongside their respective view class in `"./view"`. These controllers are used for routing
and other activities that span all views.
# ./model
This folder contains the application's (data) Model classes.
# ./view
This folder contains the views as well as ViewModels and ViewControllers depending on the
application's architecture. Pure MVC applications may not have ViewModels, for example. For
MVCVM applications or MVC applications that use ViewControllers, the following directory
structure is recommended:
./view/
foo/ # Some meaningful grouping of one or more views
Foo.js # The view class
FooController.js # The controller for Foo (a ViewController)
FooModel.js # The ViewModel for Foo
This structure helps keep these closely related classes together and easily identifiable in
most tabbed IDE's or text editors.
# ./store
This folder contains any number of store instances or types that can then be reused in the
application.

5
app/model/Readme.md → app/model/README.md

@ -15,13 +15,10 @@ Structure of a service entry:
|note|Additional info to display when adding the service.|no|
|manual_notifications|Set to `true` to let Rambox trigger notifications. Can be used for services that doesn't support browser notifications.|no|
|js_unread|JavaScript code for setting the unread count (see below).|no|
|dont_update_unread_from_title|Set to `true` to prevent updating the unread count from the window title (see below).|no|
### Setting the unread count
While there is also a way to set the unread count by adding ` (COUNT)` to the window title, this describes the preferred way of doing it:
First set `dont_update_unread_from_title` in the service config to `true`.
While by default the unread count is determined by looking for ` (COUNT)` to the window title, this describes the preferred way of doing it:
Code provided by `js_unread` will be injected into the service website.
You can retrieve the unread count in this JavaScript code e.g. by parsing elements.

4
app/model/ServiceList.js

@ -48,9 +48,5 @@ Ext.define('Rambox.model.ServiceList', {
name: 'custom_domain'
,type: 'boolean'
,defaultValue: false
},{
name: 'dont_update_unread_from_title'
,type: 'boolean'
,defaultValue: false
}]
});

42
app/package.json

@ -1,42 +0,0 @@
{
"name": "Rambox",
"productName": "Rambox",
"version": "0.5.16",
"description": "Rambox",
"main": "electron/main.js",
"private": true,
"repository": {
"type": "git",
"url": "https://github.com/saenzramiro/rambox.git"
},
"bugs": {
"url": "https://github.com/saenzramiro/rambox/issues"
},
"homepage": "http://rambox.pro",
"keywords": [
"Rambox",
"messaging",
"app",
"slack",
"whatsapp",
"facebook",
"messenger",
"telegram",
"google",
"hangouts",
"skype"
],
"author": "Ramiro Saenz <saenzramiro@gmail.com>",
"license": "GPL-3.0",
"dependencies": {
"@exponent/electron-cookies": "2.0.0",
"auth0-js": "^8.10.1",
"auth0-lock": "^10.22.0",
"auto-launch-patched": "5.0.2",
"electron-config": "0.2.1",
"electron-is-dev": "^0.3.0",
"mime": "^1.4.0",
"rimraf": "2.6.1",
"tmp": "0.0.28"
}
}

0
app/store/Readme.md → app/store/README.md

16
app/store/Services.js

@ -8,8 +8,9 @@ Ext.define('Rambox.store.Services', {
,model: 'Rambox.model.Service'
,autoLoad: true
,autoLoad: false
,autoSync: true
,pageSize: 0
,groupField: 'align'
,sorters: [
@ -20,7 +21,7 @@ Ext.define('Rambox.store.Services', {
]
,listeners: {
load: function( store, records, successful ) {
load: function( store, records, successful ) {
Ext.cq1('app-main').suspendEvent('add');
var servicesLeft = [];
@ -29,6 +30,12 @@ Ext.define('Rambox.store.Services', {
// If the service is disabled, we dont add it to tab bar
if ( !service.get('enabled') ) return;
// Rebranded app
if ( service.get('type') === 'spark' ) {
service.set('type', 'webexteams');
service.set('logo', 'webexteams.png');
}
var cfg = {
xtype: 'webview'
,id: 'tab_'+service.get('id')
@ -41,6 +48,7 @@ Ext.define('Rambox.store.Services', {
,displayTabUnreadCounter: service.get('displayTabUnreadCounter')
,enabled: service.get('enabled')
,record: service
,useragent: ipc.sendSync('getConfig').user_agent
,tabConfig: {
service: service
}
@ -68,5 +76,9 @@ Ext.define('Rambox.store.Services', {
store.suspendEvent('load');
Ext.cq1('app-main').resumeEvent('add');
}
,datachanged: function(store, eOpts) {
var isEmpty = store.getCount() > 0 ? false : true;
Ext.cq1('app-main').getViewModel().set('emptyServices', isEmpty);
}
}
});

893
app/store/ServicesList.js

@ -9,9 +9,28 @@ Ext.define('Rambox.store.ServicesList', {
,model: 'Rambox.model.ServiceList'
,proxy: {
type: 'memory'
type: 'ajax',
url: 'resources/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'
@ -20,874 +39,4 @@ Ext.define('Rambox.store.ServicesList', {
,autoLoad: true
,autoSync: true
,pageSize: 100000
,data: [
{
id: 'whatsapp'
,logo: 'whatsapp.png'
,name: 'WhatsApp'
,description: locale['services[0]']
,url: 'https://web.whatsapp.com/'
,type: 'messaging'
,js_unread: 'function checkUnread(){const elements = document.querySelectorAll(\'.CxUIE, .unread\');let count = 0;for (let i = 0; i < elements.length; i++) {if (elements[i].querySelectorAll(\'*[data-icon="muted"]\').length === 0) {count++;}}updateBadge(count);}function updateBadge(count){if(count && count>=1){rambox.setUnreadCount(count);}else{rambox.clearUnreadCount();}}setInterval(checkUnread, 1e3);'
,dont_update_unread_from_title: true
},
{
id: 'slack'
,logo: 'slack.png'
,name: 'Slack'
,description: locale['services[1]']
,url: 'https://___.slack.com/'
,type: 'messaging'
,js_unread: 'function checkUnread(){var e=$(".p-channel_sidebar__channel--unread:not(.p-channel_sidebar__channel--muted)").length,a=0;$(".p-channel_sidebar__badge").each(function(){a+=isNaN(parseInt($(this).html()))?0:parseInt($(this).html())}),updateBadge(e,a)}function updateBadge(e,a){var n=a>0?"("+a+") ":e>0?"(•) ":"";document.title=n+originalTitle}var originalTitle=document.title;setInterval(checkUnread,3e3);'
},
{
id: 'noysi'
,logo: 'noysi.png'
,name: 'Noysi'
,description: locale['services[2]']
,url: 'https://noysi.com/#/identity/sign-in'
,type: 'messaging'
},
{
id: 'messenger'
,logo: 'messenger.png'
,name: 'Messenger'
,description: locale['services[3]']
,url: 'https://www.messenger.com/login/'
,type: 'messaging'
,titleBlink: true
,note: 'To enable desktop notifications, you have to go to Options inside Messenger.'
},
{
id: 'skype'
,logo: 'skype.png'
,name: 'Skype'
,description: locale['services[4]']
,url: 'https://web.skype.com/'
,type: 'messaging'
,userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Safari/537.36 Edge/13.10586'
,note: 'Text and Audio calls are supported only. <a href="https://github.com/saenzramiro/rambox/wiki/Skype" target="_blank">Read more...</a>'
},
{
id: 'hangouts'
,logo: 'hangouts.png'
,name: 'Hangouts'
,description: locale['services[5]']
,url: 'https://hangouts.google.com/'
,type: 'messaging'
,titleBlink: true
,manual_notifications: true
,dont_update_unread_from_title: true
,js_unread: 'function checkUnread(){updateBadge(document.getElementById("hangout-landing-chat").lastChild.contentWindow.document.body.getElementsByClassName("ee").length)}function updateBadge(e){e>=1?rambox.setUnreadCount(e):rambox.clearUnreadCount()}setInterval(checkUnread,3000);'
},
{
id: 'hipchat'
,logo: 'hipchat.png'
,name: 'HipChat'
,description: locale['services[6]']
,url: 'https://___.hipchat.com/chat'
,type: 'messaging'
,js_unread: 'function checkUnread(){var e=document.getElementsByClassName("hc-badge"),t=0;for(i=0;i<e.length;i++)t+=parseInt(e[i].innerHTML.trim());updateBadge(t)}function updateBadge(e){e>=1?document.title="("+e+") "+originalTitle:document.title=originalTitle}var originalTitle=document.title;setInterval(checkUnread,3000);'
,custom_domain: true
},
{
id: 'telegram'
,logo: 'telegram.png'
,name: 'Telegram'
,description: locale['services[7]']
,url: 'https://web.telegram.org/'
,type: 'messaging'
,js_unread: 'function checkUnread(){var e=document.getElementsByClassName("im_dialog_badge badge"),t=0;for(i=0;i<e.length;i++)if(!e[i].classList.contains("im_dialog_badge_muted")){t+=parseInt(e[i].innerHTML.trim())}updateBadge(t)}function updateBadge(e){e>=1?rambox.setUnreadCount(e):rambox.clearUnreadCount()}setInterval(checkUnread,3000);'
,dont_update_unread_from_title: true
},
{
id: 'wechat'
,logo: 'wechat.png'
,name: 'WeChat'
,description: locale['services[8]']
,url: 'https://web.wechat.com/'
,type: 'messaging'
},
{
id: 'gmail'
,logo: 'gmail.png'
,name: 'Gmail'
,description: locale['services[9]']
,url: 'https://mail.google.com/mail/'
,type: 'email'
,allow_popups: true
,js_unread: 'function checkUnread(){var a=document.getElementsByClassName("aim")[0];updateBadge(-1!=a.textContent.indexOf("(")&&(t=parseInt(a.textContent.replace(/[^0-9]/g,""))))}function updateBadge(a){a>=1?rambox.setUnreadCount(a):rambox.clearUnreadCount()}setInterval(checkUnread,3e3);'
,note: 'To enable desktop notifications, you have to go to Settings inside Gmail. <a href="https://support.google.com/mail/answer/1075549?ref_topic=3394466" target="_blank">Read more...</a>'
,dont_update_unread_from_title: true
},
{
id: 'inbox'
,logo: 'inbox.png'
,name: 'Inbox'
,description: locale['services[10]']
,url: 'http://inbox.google.com/?cid=imp'
,type: 'email'
,manual_notifications: true
,js_unread: 'function checkUnread(){updateBadge(document.getElementsByClassName("ss").length)}function updateBadge(a){a>=1?document.title="("+a+") "+originalTitle:document.title=originalTitle}var originalTitle=document.title;setInterval(checkUnread,3e3);'
,note: 'Please be sure to sign out of Hangouts inside Inbox, as it causes problems. <a href="https://github.com/saenzramiro/rambox/wiki/Inbox" target="_blank">Read more...</a>'
},
{
id: 'chatwork'
,logo: 'chatwork.png'
,name: 'ChatWork'
,description: locale['services[11]']
,url: 'https://www.chatwork.com/login.php'
,type: 'messaging'
,note: 'To enable desktop notifications, you have to go to Options inside ChatWork.'
},
{
id: 'groupme'
,logo: 'groupme.png'
,name: 'GroupMe'
,description: locale['services[12]']
,url: 'https://web.groupme.com/signin'
,type: 'messaging'
,note: 'To enable desktop notifications, you have to go to Options inside GroupMe. To count unread messages, be sure to be in Chats.'
,js_unread: 'function checkUnread(){var a=document.querySelectorAll(".badge-count:not(.ng-hide)"),b=0;for(i=0;i<a.length;i++)b+=parseInt(a[i].innerHTML.trim());updateBadge(b)}function updateBadge(a){a>=1?rambox.setUnreadCount(a):rambox.clearUnreadCount()}setInterval(checkUnread,3e3);'
,dont_update_unread_from_title: true
},
{
id: 'grape'
,logo: 'grape.png'
,name: 'Grape'
,description: locale['services[13]']
,url: 'https://chatgrape.com/accounts/login/'
,type: 'messaging'
},
{
id: 'gitter'
,logo: 'gitter.png'
,name: 'Gitter'
,description: locale['services[14]']
,url: 'https://gitter.im/'
,type: 'messaging'
,js_unread: 'function checkUnread(){var e=document.getElementsByClassName("room-item__unread-indicator"),t=0;for(i=0;i<e.length;i++)t+=isNaN(parseInt(e[i].innerHTML.trim())) ? 0 : parseInt(e[i].innerHTML.trim());updateBadge(t)}function updateBadge(e){e>=1?document.title="("+e+") "+originalTitle:document.title=originalTitle}var originalTitle=document.title;setInterval(checkUnread,3000);'
},
{
id: 'steam'
,logo: 'steam.png'
,name: 'Steam Chat'
,description: locale['services[15]']
,url: 'https://steamcommunity.com/chat'
,type: 'messaging'
,note: 'To enable desktop notifications, you have to go to Options inside Steam Chat.'
,js_unread: 'CTitleManager.UpdateTitle = function(){};function checkUnread(){var e=document.getElementsByClassName("unread_message_count_value"),t=0;for(i=0;i<e.length;i++)t+=isNaN(parseInt(e[i].innerHTML.trim())) || e[i].parentNode.style.display === "none" ? 0 : parseInt(e[i].innerHTML.trim());updateBadge(t/2)}function updateBadge(e){e>=1?document.title="("+e+") "+originalTitle:document.title=originalTitle}var originalTitle=document.title;setInterval(checkUnread,3000);'
},
{
id: 'discord'
,logo: 'discord.png'
,name: 'Discord'
,description: locale['services[16]']
,url: 'https://discordapp.com/login'
,type: 'messaging'
,titleBlink: true
,js_unread: 'function checkUnread(){var a=document.getElementsByClassName("guild unread").length,b=0,c=document.getElementsByClassName("badge");for(i=0;i<c.length;i++)b+=parseInt(c[i].innerHTML.trim());updateBadge(a,b)}function updateBadge(a,b){var c=b>0?"("+b+") ":a>0?"(•) ":"";document.title=c+originalTitle}var originalTitle=document.title;setInterval(checkUnread,3e3);'
,note: 'To enable desktop notifications, you have to go to Options inside Discord.'
,dont_update_unread_from_title: true
,userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36'
},
{
id: 'outlook'
,logo: 'outlook.png'
,name: 'Outlook'
,description: locale['services[17]']
,url: 'https://mail.live.com/'
,type: 'email'
,manual_notifications: true
,js_unread: 'function checkUnread(){var a=$(".subfolders [role=treeitem]:first .treeNodeRowElement").siblings().last().text();updateBadge(""===a?0:parseInt(a))}function updateBadge(a){a>=1?document.title="("+a+") "+originalTitle:document.title=originalTitle}var originalTitle=document.title;setInterval(checkUnread,3e3);'
},
{
id: 'outlook365'
,logo: 'outlook365.png'
,name: 'Outlook 365'
,description: locale['services[18]']
,url: 'https://outlook.office.com/owa/'
,type: 'email'
,manual_notifications: true
,js_unread: 'function checkUnread(){var a=$(".subfolders [role=treeitem]:first .treeNodeRowElement").siblings().last().text();updateBadge(""===a?0:parseInt(a))}function updateBadge(a){a>=1?document.title="("+a+") "+originalTitle:document.title=originalTitle}var originalTitle=document.title;setInterval(checkUnread,3e3);'
},
{
id: 'yahoo'
,logo: 'yahoo.png'
,name: 'Yahoo! Mail'
,description: locale['services[19]']
,url: 'https://mail.yahoo.com/'
,type: 'email'
,note: 'To enable desktop notifications, you have to go to Options inside Yahoo! Mail.'
,userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36'
},
{
id: 'protonmail'
,logo: 'protonmail.png'
,name: 'ProtonMail'
,description: locale['services[20]']
,url: 'https://mail.protonmail.com/inbox'
,type: 'email'
},
{
id: 'protonmailch'
,logo: 'protonmail.png'
,name: 'ProtonMail CH'
,description: locale['services[20]']
,url: 'https://app.protonmail.ch/inbox'
,type: 'email'
,note: 'Read <a href="https://protonmail.com/support/knowledge-base/what-is-the-difference-between-protonmail-com-and-protonmail-ch/" target="_blank">HERE</a> to see the differences between protonmail.com and protonmail.ch.'
},
{
id: 'tutanota'
,logo: 'tutanota.png'
,name: 'Tutanota'
,description: locale['services[21]']
,url: 'https://app.tutanota.de/'
,type: 'email'
},
{
id: 'hushmail'
,logo: 'hushmail.png'
,name: 'Hushmail'
,description: locale['services[22]']
,url: 'https://www.hushmail.com/hushmail/index.php'
,type: 'email'
},
{
id: 'missive'
,logo: 'missive.png'
,name: 'Missive'
,description: locale['services[23]']
,url: 'https://mail.missiveapp.com/login'
,type: 'messaging'
,js_unread: 'function checkUnread(){var e=document.getElementsByClassName("unseen-count"),t=0;for(i=0;i<e.length;i++)t+=parseInt(e[i].innerHTML.trim());updateBadge(t)}function updateBadge(e){e>=1?document.title="("+e+") "+originalTitle:document.title=originalTitle}var originalTitle=document.title;setInterval(checkUnread,3000);'
},
{
id: 'rocketchat'
,logo: 'rocketchat.png'
,name: 'Rocket Chat'
,description: locale['services[24]']
,url: '___'
,type: 'messaging'
,note: 'You have to use this service by signing in with your email or username (No SSO allowed yet).'
},
{
id: 'wire'
,logo: 'wire.png'
,name: 'Wire'
,description: locale['services[25]']
,url: 'https://app.wire.com/'
,type: 'messaging'
},
{
id: 'sync'
,logo: 'sync.png'
,name: 'Sync'
,description: locale['services[26]']
,url: 'https://m.wantedly.com/login'
,type: 'messaging'
},
{
id: 'bearychat'
,logo: 'bearychat.png'
,name: 'BearyChat'
,url: 'https://___.bearychat.com/'
,type: 'messaging'
},
{
id: 'yahoomessenger'
,logo: 'yahoomessenger.png'
,name: 'Yahoo! Messenger'
,description: locale['services[28]']
,url: 'https://messenger.yahoo.com/'
,type: 'messaging'
,js_unread: 'function checkUnread(){updateBadge(document.getElementsByClassName("list-item-unread-indicator").length)}function updateBadge(e){e>=1?document.title="("+e+") "+originalTitle:document.title=originalTitle}var originalTitle=document.title;setInterval(checkUnread,3000);'
},
{
id: 'voxer'
,logo: 'voxer.png'
,name: 'Voxer'
,description: locale['services[29]']
,url: 'https://web.voxer.com/'
,type: 'messaging'
},
{
id: 'dasher'
,logo: 'dasher.png'
,name: 'Dasher'
,description: locale['services[30]']
,url: 'https://dasher.im/'
,type: 'messaging'
},
{
id: 'flowdock'
,logo: 'flowdock.png'
,name: 'Flowdock'
,description: locale['services[31]']
,url: 'https://www.flowdock.com/login'
,type: 'messaging'
},
{
id: 'mattermost'
,logo: 'mattermost.png'
,name: 'Mattermost'
,description: locale['services[32]']
,url: '___'
,type: 'messaging'
,js_unread: 'Object.defineProperty(document,"title",{configurable:!0,set:function(a){document.getElementsByTagName("title")[0].innerHTML=a[0]==="*"?"(•) Mattermost":a},get:function(){return document.getElementsByTagName("title")[0].innerHTML}});'
},
{
id: 'dingtalk'
,logo: 'dingtalk.png'
,name: 'DingTalk'
,description: locale['services[33]']
,url: 'https://im.dingtalk.com/'
,type: 'messaging'
},
{
id: 'mysms'
,logo: 'mysms.png'
,name: 'mysms'
,description: locale['services[34]']
,url: 'https://app.mysms.com/'
,type: 'messaging'
,js_unread: 'function checkUnread(){var e=document.getElementsByClassName("unread"),t=0;for(i=0;i<e.length;i++)t+=parseInt(e[i].firstChild.innerHTML.trim());updateBadge(t)}function updateBadge(e){e>=1?document.title="("+e+") "+originalTitle:document.title=originalTitle}"https://app.mysms.com/#login"===document.baseURI&&(document.getElementsByClassName("innerPanel")[0].rows[0].style.display="none",document.getElementsByClassName("innerPanel")[0].rows[1].cells[0].firstElementChild.style.display="none",document.getElementsByClassName("msisdnLoginPanel")[0].style.display="inline");var originalTitle=document.title;setInterval(checkUnread,3000);'
,note: 'You have to use this service by signing in with your mobile number.'
},
{
id: 'icq'
,logo: 'icq.png'
,name: 'ICQ'
,description: locale['services[35]']
,url: 'https://web.icq.com/'
,type: 'messaging'
,js_unread: 'function checkUnread(){updateBadge(parseInt(document.getElementsByClassName("nwa-msg-counter")[0].style.display==="block"?document.getElementsByClassName("nwa-msg-counter")[0].innerHTML.trim():0))}function updateBadge(e){e>=1?document.title="("+e+") "+originalTitle:document.title=originalTitle}var originalTitle=document.title;setInterval(checkUnread,3000);'
,titleBlink: true
},
{
id: 'tweetdeck'
,logo: 'tweetdeck.png'
,name: 'TweetDeck'
,description: locale['services[36]']
,url: 'https://tweetdeck.twitter.com/'
,type: 'messaging'
},
{
id: 'custom'
,logo: 'custom.png'
,name: '_Custom Service'
,description: locale['services[38]']
,url: '___'
,type: 'custom'
,allow_popups: true
},
{
id: 'zinc'
,logo: 'zinc.png'
,name: 'Zinc'
,description: locale['services[39]']
,url: 'https://zinc-app.com/'
,type: 'messaging'
},
{
id: 'freenode'
,logo: 'freenode.png'
,name: 'FreeNode'
,description: locale['services[40]']
,url: 'https://webchat.freenode.net/'
,type: 'messaging'
},
{
id: 'mightytext'
,logo: 'mightytext.png'
,name: 'Mighty Text'
,description: locale['services[41]']
,url: 'https://mightytext.net/web/'
,type: 'messaging'
},
{
id: 'roundcube'
,logo: 'roundcube.png'
,name: 'Roundcube'
,description: locale['services[42]']
,url: '___'
,type: 'email'
},
{
id: 'horde'
,logo: 'horde.png'
,name: 'Horde'
,description: locale['services[43]']
,url: '___'
,type: 'email'
,js_unread: 'function checkUnread(){var e=document.getElementsByClassName("count"),t=0;for(i=0;i<e.length;i++)t+=parseInt(e[i].innerHTML.match(/\d+/g));updateBadge(t)}function updateBadge(e){e>=1?document.title="("+e+") "+originalTitle:document.title=originalTitle}var originalTitle=document.title;setInterval(checkUnread,3000);'
,note: 'To enable desktop notifications and automatic mail check, you have to go to Options inside Horde.'
},
{
id: 'squirrelmail'
,logo: 'squirrelmail.png'
,name: 'SquirrelMail'
,description: locale['services[44]']
,url: '___'
,type: 'email'
,js_unread: 'function checkUnread(){var e=document.getElementsByClassName("leftunseen"),t=0;for(i=0;i<e.length;i++)t+=parseInt(e[i].innerHTML);updateBadge(t)}function updateBadge(e){e>=1?document.title="("+e+") "+originalTitle:document.title=originalTitle}var originalTitle=document.title;setInterval(checkUnread,3000);'
},
{
id: 'zohoemail'
,logo: 'zohoemail.png'
,name: 'Zoho Email'
,description: locale['services[45]']
,url: 'https://mail.zoho.com/'
,type: 'email'
,js_unread: 'zmail.aInfo[zmail.accId].mailId = "a";'
,note: 'To enable desktop notifications, you have to go to Settings inside Zoho Email.'
},
{
id: 'zohochat'
,logo: 'zohochat.png'
,name: 'Zoho Chat'
,description: locale['services[46]']
,url: 'https://chat.zoho.com/'
,type: 'messaging'
,js_unread: 'NotifyByTitle.show = function(){};NotifyByTitle.start = function(){};NotifyByTitle.stop = function(){};function checkUnread(){var t=0;$(".msgnotify").each(function() { t += isNaN(parseInt($(this).html())) ? 0 : parseInt(parseInt($(this).html())) });updateBadge(t)}function updateBadge(e){e>=1?document.title="("+e+") "+originalTitle:document.title=originalTitle}var originalTitle=document.title;setInterval(checkUnread,3000);'
},
{
id: 'aol'
,logo: 'aol.png'
,name: 'Aol'
,description: 'Free and simple (old) webmail service.'
,url: 'https://mail.aol.com/'
,type: 'email'
},
{
id: 'glip'
,logo: 'glip.png'
,name: 'Glip'
,description: 'Glip is fully searchable, real-time group chat & video chat, task management, file sharing, calendars and more.'
,url: 'https://glip.com/'
,type: 'messaging'
,note: 'To enable desktop notifications, you have to go to Options inside Glip.'
},
{
id: 'yandex'
,logo: 'yandex.png'
,name: 'Yandex Mail'
,description: 'Yandex is a free webmail service with unlimited mail storage, protection from viruses and spam, access from web interface, etc.'
,url: 'https://mail.yandex.com/'
,type: 'email'
,js_unread: 'function checkUnread(){var t=parseInt($(".mail-MessagesFilters-Item_unread .mail-LabelList-Item_count").html());updateBadge(isNaN(t)?0:t)}function updateBadge(e){e>=1?document.title="("+e+") "+originalTitle:document.title=originalTitle}var originalTitle=document.title;setInterval(checkUnread,3000);'
},
{
id: 'irccloud'
,logo: 'irccloud.png'
,name: 'IRCCloud'
,description: 'IRCCloud is a modern IRC client that keeps you connected, with none of the baggage.'
,url: 'https://www.irccloud.com/'
,type: 'messaging'
,js_unread: 'function checkUnread(){var t=0;[].map.call(document.querySelectorAll(".bufferBadges > .badge"),n=>n.textContent?parseInt(n.textContent,10):0).reduce((x,y)=>x+y,0);updateBadge(t)}function updateBadge(e){e>=1?document.title="("+e+") "+originalTitle:document.title=originalTitle}var originalTitle=document.title;setInterval(checkUnread,3000);'
,custom_domain: true
},
{
id: 'ryver'
,logo: 'ryver.png'
,name: 'Ryver'
,description: 'Ryver is a team communication tool that organizes team collaboration, chats, files, and even emails into a single location, for any size team, for FREE.'
,url: 'https://___.ryver.com/'
,type: 'messaging'
,js_unread: 'function checkUnread(){updateBadge(parseInt(document.getElementsByClassName("scene-space-tab-button--flash").length))}function updateBadge(a){a>=1?rambox.setUnreadCount(a):rambox.clearUnreadCount()}setInterval(checkUnread,3e3);'
},
{
id: 'kiwi'
,logo: 'kiwi.png'
,name: 'Kiwi IRC'
,description: 'KiwiIRC makes Web IRC easy. A hand-crafted IRC client that you can enjoy. Designed to be used easily and freely.'
,url: 'https://kiwiirc.com/client'
,type: 'messaging'
,js_unread: 'function getUnreadCount(){var a=0;$(".activity").each(function(){a+=parseInt($(this).html())});var b=!1;return $(".panel[style*=\'display:block\'] .msg").each(function(){b?a++:$(this).hasClass("last_seen")&&(b=!0)}),a}function updateTitle(a){count=getUnreadCount(),cleanTitle=a.match(re),null!==cleanTitle&&cleanTitle.length>1?cleanTitle=cleanTitle[1]:cleanTitle=a,a=count>0?"("+getUnreadCount()+") "+cleanTitle:cleanTitle,$("title").text(a)}var re=/\(\d+\)[ ](.*)/;Object.defineProperty(document,"title",{configurable:!0,set:function(a){updateTitle(a)},get:function(){return $("title").text()}}),setInterval(function(){updateTitle(document.title)},3e3);'
,custom_domain: true
},
{
id: 'icloud'
,logo: 'icloud.png'
,name: 'iCloud Mail'
,description: 'iCloud makes sure you always have the latest versions of your most important things — documents, photos, notes, contacts, and more — on all your devices. It can even help you locate a missing iPhone, iPad, iPod touch or Mac.'
,url: 'https://www.icloud.com/#mail'
,type: 'email'
,js_unread: 'function checkUnread(){updateBadge(document.querySelector(".current-app").querySelector(".sb-badge").style.display==="none"?0:parseInt(document.querySelector(".current-app").querySelector(".text").innerHTML.trim()))}function updateBadge(a){a>=1?rambox.setUnreadCount(a):rambox.clearUnreadCount()}setInterval(checkUnread,3e3);'
,dont_update_unread_from_title: true
},
{
id: 'rainloop'
,logo: 'rainloop.png'
,name: 'RainLoop'
,description: 'RainLoop Webmail - Simple, modern & fast web-based email client.'
,url: '___'
,type: 'email'
,js_unread: 'function checkUnread(){var t=document.querySelectorAll(".e-item .e-link:not(.hidden) .badge.pull-right.count"),e=0;for(i=0;i<t.length;i++)parseInt(t[i].textContent.trim())%1==0&&"block"==window.getComputedStyle(t[i]).display&&(count=parseInt(t[i].textContent.trim()),e+=parseInt(t[i].textContent.trim()));updateBadge(e)}function updateBadge(t){document.title=t>=1?"("+t+") "+originalTitle:originalTitle}var originalTitle=document.title;setInterval(checkUnread,1e3);'
},
{
id: 'amium'
,logo: 'amium.png'
,name: 'Amium'
,description: 'Amium turns any file into a real-time activity feed and conversation. So you can work better, together.'
,url: 'https://___.amium.com/'
,type: 'messaging'
},
{
id: 'hootsuite'
,logo: 'hootsuite.png'
,name: 'Hootsuite'
,description: 'Enhance your social media management with Hootsuite, the leading social media dashboard. Manage multiple networks and profiles and measure your campaign results.'
,url: 'https://hootsuite.com/dashboard'
,type: 'messaging'
},
{
id: 'zimbra'
,logo: 'zimbra.png'
,name: 'Zimbra'
,description: 'Over 500 million people rely on Zimbra and enjoy enterprise-class open source email collaboration at the lowest TCO in the industry. Discover the benefits!'
,url: '___'
,type: 'email'
,js_unread: 'function check_unread(){update_badge(appCtxt.getById(ZmFolder.ID_INBOX).numUnread)}function update_badge(a){document.title=a>0?"("+a+") "+original_title:original_title}const original_title=document.title;setInterval(check_unread,3e3);'
},
{
id: 'kaiwa'
,logo: 'kaiwa.png'
,name: 'Kaiwa'
,description: 'A modern and Open Source Web client for XMPP.'
,url: '___'
,type: 'messaging'
,js_unread: 'function check_unread() { let count=0; for (let node of document.getElementsByClassName("unread")){ if (node.innerHTML){ count += parseInt(node.innerHTML); } } update_badge(count);}function update_badge(a) { document.title = a > 0 ? "(" + a + ") " + original_title : original_title}const original_title = document.title;setInterval(check_unread, 3e3);'
},
{
id: 'movim'
,logo: 'movim.png'
,name: 'Movim'
,description: 'Movim is a decentralized social network, written in PHP and HTML5 and based on the XMPP standard protocol.'
,url: 'https://___.movim.eu/'
,type: 'messaging'
,js_unread: 'function checkUnread(){var a=document.getElementsByClassName("color dark"),b=0;for(i=0;i<a.length;i++){var c=a[i].getElementsByClassName("counter");for(ii=0;ii<c.length;ii++)parseInt(c[ii].textContent.trim())%1===0&&(b+=parseInt(c[ii].textContent.trim()))}updateBadge(b)}function updateBadge(a){a>=1?document.title="("+a+") "+originalTitle:document.title=originalTitle}var originalTitle=document.title;setInterval(checkUnread,3e3);'
,custom_domain: true
},
{
id: 'pushbullet'
,logo: 'pushbullet.png'
,name: 'Pushbullet'
,description: 'Pushbullet connects your devices, making them feel like one.'
,url: 'https://www.pushbullet.com/'
,type: 'messaging'
},
{
id: 'riot'
,logo: 'riot.png'
,name: 'Riot'
,description: 'Riot is a simple and elegant collaboration environment that gathers all of your different conversations and app integrations into one single app.'
,url: 'https://riot.im/app/'
,type: 'messaging'
,js_unread: 'function checkUnread(){var a=document.getElementsByClassName("mx_RoomTile_nameContainer"),b=0;for(i=0;i<a.length;i++){var c=a[i].getElementsByClassName("mx_RoomTile_badge");for(ii=0;ii<c.length;ii++)parseInt(c[ii].textContent.trim())%1===0&&(b+=parseInt(c[ii].textContent.trim()))}updateBadge(b)}function updateBadge(a){a>=1?document.title="("+a+") "+originalTitle:document.title=originalTitle}var originalTitle=document.title;setInterval(checkUnread,1e3);'
,custom_domain: true
},
{
id: 'socialcast'
,logo: 'socialcast.png'
,name: 'Socialcast'
,description: 'Socialcast is the premier enterprise social networking platform that connects people to the knowledge, ideas and resources they need to work more effectively.'
,url: 'https://___.socialcast.com/'
,type: 'messaging'
},
{
id: 'fleep'
,logo: 'fleep.png'
,name: 'Fleep'
,description: 'Fleep enables communication within and across organizations - be it your team chats, project communication or 1:1 conversations.'
,url: 'https://fleep.io/chat'
,type: 'messaging'
,js_unread: 'document.getElementsByClassName("google-login-area")[0].remove();document.getElementsByClassName("microsoft-login-area")[0].remove();'
},
{
id: 'spark'
,logo: 'spark.png'
,name: 'Cisco Spark'
,description: 'Cisco Spark is for group chat, video calling, and sharing documents with your team. It’s all backed by Cisco security and reliability.'
,url: 'https://web.ciscospark.com/'
,type: 'messaging'
},
{
id: 'drift'
,logo: 'drift.png'
,name: 'Drift'
,description: 'Drift is a messaging app that makes it easy for businesses to talk to their website visitors and customers in real-time, from anywhere.'
,url: 'https://app.drift.com/'
,type: 'messaging'
},
{
id: 'typetalk'
,logo: 'typetalk.png'
,name: 'Typetalk'
,description: 'Typetalk brings fun and ease to team discussions through instant messaging on desktop and mobile devices.'
,url: 'https://typetalk.in/signin'
,type: 'messaging'
},
{
id: 'openmailbox'
,logo: 'openmailbox.png'
,name: 'Openmailbox'
,description: 'Free mail hosting. Respect your rights and your privacy.'
,url: 'https://app.openmailbox.org/webmail/'
,type: 'email'
},
{
id: 'flock'
,logo: 'flock.png'
,name: 'Flock'
,description: 'Flock is a free enterprise tool for business communication. Packed with tons of productivity features, Flock drives efficiency and boosts speed of execution.'
,url: 'https://web.flock.co/'
,type: 'messaging'
,js_unread: 'function checkUnread(){var a=document.getElementsByClassName("unreadMessages no-unread-mentions has-unread"),b=0;for(i=0;i<a.length;i++)b+=parseInt(a[i].innerHTML.trim());updateBadge(b)}function updateBadge(a){a>=1?rambox.setUnreadCount(a):rambox.clearUnreadCount()}setInterval(checkUnread,3e3);'
,dont_update_unread_from_title: true
},
{
id: 'crisp'
,logo: 'crisp.png'
,name: 'Crisp'
,description: 'Connect your customers to your team.'
,url: 'https://app.crisp.im/inbox'
,type: 'messaging'
},
{
id: 'smooch'
,logo: 'smooch.png'
,name: 'Smooch'
,description: 'Unified multi-channel messaging for businesses, bots and software makers.'
,url: 'https://app.smooch.io/'
,type: 'messaging'
},
{
id: 'xing',
logo: 'xing.png',
name: 'XING',
description: 'Career-oriented social networking',
url: 'https://www.xing.com/messages/conversations',
type: 'messaging',
js_unread: '(function() { let originalTitle = document.title; function checkUnread() { let count = null; let notificationElement = document.querySelector(\'[data-update="unread_conversations"]\'); if (notificationElement && notificationElement.style.display !== \'none\') { count = parseInt(notificationElement.textContent.trim(), 10); } updateBadge(count); } function updateBadge(count) { if (count && count >= 1) { rambox.setUnreadCount(count); } else { rambox.clearUnreadCount(); } } setInterval(checkUnread, 3000); checkUnread(); })();',
dont_update_unread_from_title: true
},
{
id: 'threema',
logo: 'threema.png',
name: 'Threema',
description: 'Seriously secure messaging',
url: 'https://web.threema.ch/',
type: 'messaging',
js_unread: '(function () { let unreadCount = 0; function checkUnread() { let newUnread = 0; try { let webClientService = angular.element(document.documentElement).injector().get(\'WebClientService\'); let conversations = webClientService.conversations.conversations; conversations.forEach(function(conversation) { newUnread += conversation.unreadCount; }); } catch (e) { } if (newUnread !== unreadCount) { unreadCount = newUnread; updateBadge(unreadCount); } } function updateBadge(count) { if (count && count >= 1) { rambox.setUnreadCount(count); } else { rambox.clearUnreadCount(); } } setInterval(checkUnread, 3000); checkUnread(); })();',
dont_update_unread_from_title: true
},
{
id: 'workplace'
,logo: 'workplace.png'
,name: 'Workplace'
,description: 'Connect everyone in your company and turn ideas into action. Through group discussion, a personalised News Feed, and voice and video calling, work together and get more done. Workplace is an ad-free space, separate from your personal Facebook account.'
,url: 'https://___.facebook.com/'
,type: 'messaging'
},
{
id: 'teams'
,logo: 'teams.png'
,name: 'Teams'
,description: 'Microsoft Teams is the chat-based workspace in Office 365 that integrates all the people, content, and tools your team needs to be more engaged and effective.'
,url: 'https://teams.microsoft.com'
,type: 'messaging'
,userAgent: 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.2883.87 Safari/537.36'
},
{
id: 'kezmo'
,logo: 'kezmo.png'
,name: 'Kezmo'
,description: 'Kezmo is an enterprise chat and collaboration tool to help teams get things done. It’s an email alternative for secure team communication.'
,url: 'https://app.kezmo.com/web/'
,type: 'messaging'
},
{
id: 'lounge'
,logo: 'lounge.png'
,name: 'The Lounge'
,description: 'Self-hosted web IRC client.'
,url: '___'
,type: 'messaging'
,js_unread: 'function checkUnread(){var a=document.getElementsByClassName("badge highlight"),b=0;for(i=0;i<a.length;i++)parseInt(a[i].textContent.trim())%1===0&&(b+=parseInt(a[i].textContent.trim()));updateBadge(b)}function updateBadge(a){a>=1?document.title="("+a+") "+originalTitle:document.title=originalTitle}var originalTitle=document.title;setInterval(checkUnread,1e3);'
},
{
id: 'linkedin'
,logo: 'linkedin.png'
,name: 'LinkedIn Messaging'
,description: 'Manage your professional identity. Build and engage with your professional network. Access knowledge, insights and opportunities.'
,url: 'https://www.linkedin.com/messaging'
,type: 'messaging'
},
{
id: 'zyptonite'
,logo: 'zyptonite.png'
,name: 'Zyptonite'
,description: 'Zyptonite is the ultimate cyber secure communication tool for enterprise customers designed to address the need to securely communicate via voice, video, and chat, and transfer files and information across a global mobile workforce.'
,url: 'https://app.zyptonite.com/'
,type: 'messaging'
,js_unread: 'function checkUnread(){var a=document.getElementsByClassName("z-messages"),b=0;for(i=0;i<a.length;i++)b+=parseInt(a[i].innerHTML.trim());updateBadge(b)}function updateBadge(a){a>=1?rambox.setUnreadCount(a):rambox.clearUnreadCount()}setInterval(checkUnread,3e3);'
,dont_update_unread_from_title: true
},
{
id: 'fastmail'
,logo: 'fastmail.png'
,name: 'FastMail'
,description: 'Secure, reliable email hosting for businesses, families and professionals. Premium email with no ads, excellent spam protection and rapid personal support.'
,url: 'https://www.fastmail.com/mail/'
,type: 'mail'
,js_unread: 'function checkUnread(){var e=document.getElementsByClassName("v-FolderSource-badge"),t=0;for(i=0;i<e.length;i++)t+=isNaN(parseInt(e[i].innerHTML.trim())) ? 0 : parseInt(e[i].innerHTML.trim());updateBadge(t)}function updateBadge(e){e>=1?document.title="("+e+")"+originalTitle:document.title=originalTitle}var originalTitle=document.title;setInterval(checkUnread,3000);setTimeout(function(){O.WindowController.openExternal=function(a){var b=document.createElement("a");b.href=a,b.setAttribute("target","_blank"),b.click()};},3000);'
,note: 'To enable desktop notifications, you have to go to Settings inside FastMail.'
},
{
id: 'hibox'
,logo: 'hibox.png'
,name: 'Hibox'
,description: 'Hibox is a secure and private messaging platform for your business.'
,url: 'https://app.hibox.co/'
,type: 'messaging'
},
{
id: 'jandi'
,logo: 'jandi.png'
,name: 'Jandi'
,description: 'Jandi is a group-oriented enterprise messaging platform with an integrated suite of collaboration tools for workplace.'
,url: 'https://___.jandi.com/'
,type: 'messaging'
},
{
id: 'messengerpages'
,logo: 'messengerpages.png'
,name: 'Messenger for Pages'
,description: 'Chat with the people of your Facebook Page.'
,url: 'https://facebook.com/___/inbox/'
,type: 'messaging'
,js_unread: 'function remove(e){var r=document.getElementById(e);return r.parentNode.removeChild(r)}remove("pagelet_bluebar"),remove("pages_manager_top_bar_container");'
},
{
id: 'vk'
,logo: 'vk.png'
,name: 'VK Messenger'
,description: 'Simple and Easy App for Messaging on VK.'
,url: 'https://vk.com/im'
,type: 'messaging'
,js_unread: 'function checkUnread(){updateBadge(parseInt(document.getElementById("l_msg").innerText.replace(/\D+/g,"")))}function updateBadge(e){e>=1?document.title="("+e+") "+originalTitle:document.title=originalTitle}var originalTitle=document.title;setInterval(checkUnread,3000);'
},
{
id: 'mastodon'
,logo: 'mastodon.png'
,name: 'Mastodon'
,description: 'Mastodon is a free, open-source social network server. A decentralized solution to commercial platforms, it avoids the risks of a single company monopolizing your communication. Anyone can run Mastodon and participate in the social network seamlessly.'
,url: 'https://mastodon.social/auth/sign_in'
,type: 'messaging'
,custom_domain: true
,note: '<a href="https://instances.mastodon.xyz/" target="_blank">List of instances</a>'
},
{
id: 'teamworkchat'
,logo: 'teamworkchat.png'
,name: 'Teamwork Chat'
,description: 'Say goodbye to email. Take your online collaboration to the next level with Teamwork Chat and keep all team discussions in one place. Chat to your team in a fun and informal way with Teamwork Chat.'
,url: 'https://___.teamwork.com/chat'
,type: 'messaging'
,js_unread: 'function checkUnread(){updateBadge(parseInt(document.getElementsByClassName("sidebar-notification-indicator").length > 0 ? document.getElementsByClassName("sidebar-notification-indicator")[0].innerHTML : 0))}function updateBadge(a){a>=1?rambox.setUnreadCount(a):rambox.clearUnreadCount()}setInterval(checkUnread,3e3);'
,dont_update_unread_from_title: true
},
{
id: 'clocktweets'
,logo: 'clocktweets.png'
,name: 'ClockTweets'
,description: 'Schedule your Tweets with love. Save time and manage your social media strategy easily.'
,url: 'https://clocktweets.com/dashboard/'
,type: 'messaging'
},
{
id: 'intercom'
,logo: 'intercom.png'
,name: 'Intercom'
,description: 'Intercom makes it easy to communicate with your customers personally, at scale. Designed to feel like the messaging apps you use every day, Intercom lets you talk to consumers almost anywhere: inside your app, on your website, across social media and via email.'
,url: 'https://app.intercom.io'
,type: 'messaging'
,js_unread: 'function checkUnread(){var a=document.getElementsByClassName("unread")[0];updateBadge(t=a===undefined?0:parseInt(a.textContent.replace(/[^0-9]/g,"")))}function updateBadge(a){a>=1?rambox.setUnreadCount(a):rambox.clearUnreadCount()}setInterval(checkUnread,3000);'
,dont_update_unread_from_title: true
},
{
id: 'allo'
,logo: 'allo.png'
,name: 'Allo'
,description: 'Google Allo is a smart messaging app that helps you say more and do more. Express yourself better with stickers, doodles, and HUGE emojis & text. Allo also brings you the Google Assistant.'
,url: 'https://allo.google.com/web'
,type: 'messaging'
,js_unread: 'function checkUnread(){var e=document.querySelectorAll(".hasUnread.conversation_item"),n=0;for(i=0;i<e.length;i++){var r="none"===e[i].querySelector("#muted").style.display?parseInt(e[i].querySelector(".unreadCount").innerHTML.trim()):0;n+=isNaN(r)?0:r}updateBadge(n)}function updateBadge(e){e&&e>=1?rambox.setUnreadCount(e):rambox.clearUnreadCount()}setInterval(checkUnread,3e3);'
,dont_update_unread_from_title: true
},
{
id: 'Kune'
,logo: 'kune.png'
,name: 'Kune'
,description: 'Kune is a web tool, based on Apache Wave, for creating environments of constant inter-communication, collective intelligence, knowledge and shared work.'
,url: 'https://kune.cc'
,type: 'messaging'
},
{
id: 'googlevoice'
,logo: 'googlevoice.png'
,name: 'Google Voice'
,description: 'A free phone number for life. Stay in touch from any screen. Use your free number to text, call, and check voicemail all from one app. Plus, Google Voice works on all of your devices so you can connect and communicate how you want.'
,url: 'https://voice.google.com'
,type: 'messaging'
,js_unread: 'function parseIntOrZero(e){return isNaN(parseInt(e))?0:parseInt(e)}function checkUnread(){var e=document.querySelector(".msgCount"),n=0;e?n=parseIntOrZero(e.innerHTML.replace(/[\(\) ]/gi,"")):["Messages","Calls","Voicemail"].forEach(function(e){var r=document.querySelector(\'gv-nav-button[tooltip="\'+e+\'"] div[aria-label="Unread count"]\');r&&(n+=parseIntOrZero(r.innerHTML))}),updateBadge(n)}function updateBadge(e){var n=e>0?"("+e+") ":"";document.title=n+originalTitle}var originalTitle=document.title;setInterval(checkUnread,3000);'
},
{
id: 'sandstorm'
,logo: 'sandstorm.png'
,name: 'Sandstorm'
,description: 'Sandstorm is a self-hostable web productivity suite.'
,url: 'https://oasis.sandstorm.io/'
,type: 'messaging'
,custom_domain: true
,allow_popups: true
},
{
id: 'gadugadu'
,logo: 'gadugadu.png'
,name: 'Gadu-Gadu'
,description: 'The most popular Polish messenger.'
,url: 'https://www.gg.pl/'
,type: 'messaging'
},
{
id: 'mailru'
,logo: 'mailru.png'
,name: 'Mail.Ru'
,description: 'Free voice and video calls, ICQ support, Odnoklassniki, VKontakte, Facebook, online games, free SMS.'
,url: 'http://webagent.mail.ru/webim/agent/popup.html'
,type: 'email'
},
{
id: 'zulip'
,logo: 'zulip.png'
,name: 'Zulip'
,description: "The world's most productive group chat"
,url: 'https://___.zulipchat.com/'
,type: 'messaging'
,custom_domain: true
},
{
id: 'stride'
,logo: 'stride.png'
,name: 'Stride'
,description: 'Stride is the complete team communication solution with group messaging, video meetings, and built-in collaboration tools.'
,url: 'https://app.stride.com/___'
,type: 'messaging'
,js_unread: 'function checkUnread(){var t=0,e=!1;document.querySelectorAll(".conversations-nav .nav-item .activity-indicator").forEach(function(n){n.classList.contains("has-count")?t+=parseInt(n.innerHTML):e=!0}),updateBadge(t,e)}function updateBadge(t,e){var n=t>0?"("+t+") ":e?"(•) ":"";document.title=n+originalTitle}var originalTitle=document.title;setInterval(checkUnread,3e3);'
}
]
});

17
app/util/IconLoader.js

@ -18,16 +18,15 @@ Ext.define('Rambox.util.IconLoader', {
this.loadServiceIconUrl = function (service, webview) {
switch (service.type) {
case 'slack':
webview.executeJavaScript(
"(()=>{let a=document.querySelector('.team_icon');if(!a){const d=document.querySelector('#team_menu');d&&(d.click(),a=document.querySelector('.team_icon'))}if(!a)return!1;const{style:{backgroundImage:b}}=a,c=document.createEvent('MouseEvents');return c.initEvent('mousedown',!0,!0),document.querySelector('.client_channels_list_container').dispatchEvent(c),b.slice(5,-2)})();",
false,
function (backgroundImage) {
if (backgroundImage) {
service.setTitle('<img src="'+service.icon+'" width="" style="background-color: white;border-radius: 50%;position: absolute;left: 18px;top: 17px;width: 12px;">'+service.title);
service.fireEvent('iconchange', service, backgroundImage, service.icon);
}
webview.executeJavaScript("(a=>window.slackDebug.activeTeam.redux.getState().teams[a].icon.image_44)(window.slackDebug.activeTeamId);")
.then(backgroundImage => {
if (backgroundImage) {
service.setTitle('<img src="'+service.icon+'" width="" style="background-color: white;border-radius: 50%;position: absolute;left: 18px;top: 17px;width: 12px;">'+service.title);
service.fireEvent('iconchange', service, backgroundImage, service.icon);
}
);
}).catch(err => {
console.log(err);
})
break;
default:
break;

259
app/ux/Auth0.js

@ -1,259 +0,0 @@
Ext.define('Rambox.ux.Auth0', {
singleton: true
// private
,lock: null
,auth0: null
,backupCurrent: false
,init: function() {
var me = this;
var Auth0Lock = require('auth0-lock')['default'];
var Auth0 = require('auth0-js');
// Auth0 Config
me.lock = new Auth0Lock(auth0Cfg.clientID, auth0Cfg.domain, {
autoclose: true
,autofocus: true
,auth: {
redirect: false
,params: {scope: 'openid offline_access'}
}
,theme: {
logo: 'resources/Icon.png'
,primaryColor: '#0675A0'
}
,languageDictionary: {
title: 'Rambox Account'
}
,popupOptions: {
nodeIntegration: 'no'
}
,language: localStorage.getItem('locale-auth0') === null ? 'en' : localStorage.getItem('locale-auth0')
});
me.auth0 = new Auth0.WebAuth({ clientID: auth0Cfg.clientID, domain : auth0Cfg.domain });
me.defineEvents();
}
,defineEvents: function() {
var me = this;
me.lock.on("authenticated", function(authResult) {
me.lock.getProfile(authResult.idToken, 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
});
}
// 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('id_token', authResult.idToken);
localStorage.setItem('refresh_token', authResult.refreshToken);
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.getCurrentWindow().reload();
}
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')).user_id
,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: '<i class="fa fa-check fa-3x fa-pull-left" aria-hidden="true"></i> 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: '<i class="fa fa-times fa-3x fa-pull-left" aria-hidden="true"></i> 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.lock.getProfile(localStorage.getItem('id_token'), function (err, profile) {
if ( err ) {
if ( err.error === 401 || err.error === 'Unauthorized' ) return me.renewToken(me.checkConfiguration);
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
});
}
// First we remove all current services
Ext.cq1('app-main').getController().removeAllServices(false, function() {
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.lock.getProfile(localStorage.getItem('id_token'), function (err, profile) {
if ( err ) {
if ( err.error === 401 || err.error === 'Unauthorized' ) return me.renewToken(me.checkConfiguration);
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
});
}
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/delegation'
,method: 'POST'
,jsonData: {
grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer'
,client_id: auth0Cfg.clientID
,refresh_token: localStorage.getItem('refresh_token')
,api_type: 'app'
}
,success: function(response) {
var json = Ext.decode(response.responseText);
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;
me.lock.show();
}
,logout: function() {
var me = this;
localStorage.removeItem('profile');
localStorage.removeItem('id_token');
localStorage.removeItem('refresh_token');
// Set cookies to help Tooltip.io messages segmentation
Ext.util.Cookies.set('auth0', false);
}
});

461
app/ux/WebView.js

@ -1,6 +1,7 @@
/**
* Default config for all webviews created
*/
Ext.define('Rambox.ux.WebView',{
extend: 'Ext.panel.Panel'
,xtype: 'webview'
@ -34,12 +35,10 @@ Ext.define('Rambox.ux.WebView',{
}
}
// Allow Custom sites with self certificates
//if ( me.record.get('trust') ) ipc.send('allowCertificate', me.src);
const prefConfig = ipc.sendSync('getConfig');
Ext.apply(me, {
items: me.webViewConstructor()
,title: me.record.get('tabname') ? me.record.get('name') : ''
,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')) : 'resources/icons/'+me.record.get('logo')
,src: me.record.get('url')
,type: me.record.get('type')
@ -124,6 +123,45 @@ Ext.define('Rambox.ux.WebView',{
]
}
}
,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
@ -163,6 +201,7 @@ Ext.define('Rambox.ux.WebView',{
} else {
cfg = [{
xtype: 'component'
,cls: 'webview'
,hideMode: 'offsets'
,autoRender: true
,autoShow: true
@ -170,28 +209,32 @@ Ext.define('Rambox.ux.WebView',{
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')).user_id : '')
,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: 'allowRunningInsecureContent=yes' //,nativeWindowOpen=yes
//,disablewebsecurity: 'on' // Disabled because some services (Like Google Drive) dont work with this enabled
,useragent: Ext.getStore('ServicesList').getById(me.record.get('type')).get('userAgent')
,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'
}
}];
if ( Ext.getStore('ServicesList').getById(me.record.get('type')).get('allow_popups') ) cfg[0].autoEl.allowpopups = 'on';
}
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'
@ -228,20 +271,26 @@ Ext.define('Rambox.ux.WebView',{
if ( !me.record.get('enabled') ) return;
var webview = me.down('component').el.dom;
// Google Analytics Event
ga_storage._trackEvent('Services', 'load', me.type, 1, true);
var webview = me.getWebView();
me.errorCodeLog = []
// Notifications in Webview
me.setNotifications(localStorage.getItem('locked') || JSON.parse(localStorage.getItem('dontDisturb')) ? false : me.record.get('notifications'));
require('electron').remote.session.fromPartition('persist:' + me.record.get('type') + '_' + me.id.replace('tab_', '') + (localStorage.getItem('id_token') ? '_' + Ext.decode(localStorage.getItem('profile')).sub : '')).webRequest.onBeforeSendHeaders((details, callback) => {
const change = details.url.match(/^https:\/\/accounts\.google\.com(\/|$)/);
if ( change ) details.requestHeaders['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:97.0) Gecko/20100101 Firefox/97.0';
callback({ cancel: false, requestHeaders: details.requestHeaders });
});
// Show and hide spinner when is loading
webview.addEventListener("did-start-loading", function() {
console.info('Start loading...', me.src);
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();
@ -253,153 +302,94 @@ Ext.define('Rambox.ux.WebView',{
// 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);
});
// Open links in default browser
webview.addEventListener('new-window', function(e) {
switch ( me.type ) {
case 'skype':
// hack to fix multiple browser tabs on Skype link click, re #11
if ( e.url.match('https:\/\/web.skype.com\/..\/undefined') ) {
e.preventDefault();
return;
} else if ( e.url.indexOf('imgpsh_fullsize') >= 0 ) {
ipc.send('image:download', e.url, e.target.partition);
e.preventDefault();
return;
}
break;
case 'hangouts':
e.preventDefault();
if ( e.url.indexOf('plus.google.com/u/0/photos/albums') >= 0 ) {
ipc.send('image:popup', e.url, e.target.partition);
return;
} else if ( e.url.indexOf('/el/CONVERSATION/') >= 0 ) {
me.add({
xtype: 'window'
,title: 'Video Call'
,width: '80%'
,height: '80%'
,maximizable: true
,resizable: true
,draggable: true
,collapsible: true
,items: {
xtype: 'component'
,hideMode: 'offsets'
,autoRender: true
,autoShow: true
,autoEl: {
tag: 'webview'
,src: e.url
,style: 'width:100%;height:100%;'
,partition: me.getWebView().partition
,useragent: Ext.getStore('ServicesList').getById(me.record.get('type')).get('userAgent')
}
}
}).show();
return;
}
break;
case 'slack':
if ( e.url.indexOf('slack.com/call/') >= 0 ) {
me.add({
xtype: 'window'
,title: e.options.title
,width: e.options.width
,height: e.options.height
,maximizable: true
,resizable: true
,draggable: true
,collapsible: true
,items: {
xtype: 'component'
,hideMode: 'offsets'
,autoRender: true
,autoShow: true
,autoEl: {
tag: 'webview'
,src: e.url
,style: 'width:100%;height:100%;'
,partition: me.getWebView().partition
,useragent: Ext.getStore('ServicesList').getById(me.record.get('type')).get('userAgent')
}
}
}).show();
e.preventDefault();
return;
}
// 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 'icloud':
if ( e.url.indexOf('index.html#compose') >= 0 ) {
me.add({
xtype: 'window'
,title: 'iCloud - Compose'
,width: 700
,height: 500
,maximizable: true
,resizable: true
,draggable: true
,collapsible: true
,items: {
xtype: 'component'
,itemId: 'webview'
,hideMode: 'offsets'
,autoRender: true
,autoShow: true
,autoEl: {
tag: 'webview'
,src: e.url
,style: 'width:100%;height:100%;'
,partition: me.getWebView().partition
,useragent: Ext.getStore('ServicesList').getById(me.record.get('type')).get('userAgent')
,preload: './resources/js/rambox-modal-api.js'
}
}
,listeners: {
show: function(win) {
const webview = win.down('#webview').el.dom;
webview.addEventListener('ipc-message', function(event) {
var channel = event.channel;
switch (channel) {
case 'close':
win.close();
break;
default:
break;
}
});
}
}
}).show();
e.preventDefault();
return;
}
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 'flowdock':
if ( e.disposition === 'new-window' ) {
e.preventDefault();
require('electron').shell.openExternal(e.url);
}
return;
case -106:
me.onFailLoad(msg[e.errorCode])
break;
default:
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;
}
});
const protocol = require('url').parse(e.url).protocol;
if (protocol === 'http:' || protocol === 'https:' || protocol === 'mailto:') {
e.preventDefault();
require('electron').shell.openExternal(e.url);
}
// Open links in default browser
webview.addEventListener('new-window', function(e) {
e.preventDefault();
const { URL } = require('url');
const url = new URL(e.url);
const protocol = 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(url.href);
});
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);
@ -407,7 +397,7 @@ Ext.define('Rambox.ux.WebView',{
var js_inject = '';
// Injected code to detect new messages
if ( me.record ) {
var js_unread = Ext.getStore('ServicesList').getById(me.record.get('type')).get('js_unread');
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');
@ -418,7 +408,7 @@ Ext.define('Rambox.ux.WebView',{
}
// 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')).get('titleBlink') ) {
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;
@ -430,8 +420,8 @@ Ext.define('Rambox.ux.WebView',{
js_inject += 'document.body.scrollTop=0;';
// Handles Certificate Errors
webview.getWebContents().on('certificate-error', function(event, url, error, certificate, callback) {
if ( me.record.get('trust') ) {
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 {
@ -441,12 +431,54 @@ Ext.define('Rambox.ux.WebView',{
me.down('statusbar').keep = true;
me.down('statusbar').show();
me.down('statusbar').setStatus({
text: '<i class="fa fa-exclamation-triangle" aria-hidden="true"></i> Certification Warning'
text: '<i class="fa fa-exclamation-triangle" aria-hidden="true"></i> 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;
}
webview.executeJavaScript(js_inject);
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) {
@ -462,7 +494,6 @@ Ext.define('Rambox.ux.WebView',{
showWindowAndActivateTab(event);
break;
}
/**
* Handles 'rambox.clearUnreadCount' messages.
* Clears the unread count.
@ -475,14 +506,15 @@ Ext.define('Rambox.ux.WebView',{
/**
* Handles 'rambox.setUnreadCount' messages.
* Sets the badge text if the event contains an integer as first argument.
* 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)) {
if (count === parseInt(count, 10) || "•" === count) {
if ( count === 999999 ) count = "•";
me.setUnreadCount(count);
}
}
@ -490,14 +522,18 @@ Ext.define('Rambox.ux.WebView',{
function showWindowAndActivateTab(event) {
require('electron').remote.getCurrentWindow().show();
Ext.cq1('app-main').setActiveTab(me);
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 prevent it by setting 'dont_update_unread_from_title' to true.
* 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')).get('dont_update_unread_from_title') !== true) {
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';
@ -508,7 +544,7 @@ Ext.define('Rambox.ux.WebView',{
});
}
webview.addEventListener('did-get-redirect-request', function( e ) {
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.
});
@ -546,12 +582,9 @@ Ext.define('Rambox.ux.WebView',{
*/
,doManualNotification: function(count) {
var me = this;
if (Ext.getStore('ServicesList').getById(me.type).get('manual_notifications') &&
me.currentUnreadCount < count &&
me.record.get('notifications') &&
!JSON.parse(localStorage.getItem('dontDisturb'))) {
Rambox.util.Notifier.dispatchNotification(me, count);
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;
@ -584,7 +617,7 @@ Ext.define('Rambox.ux.WebView',{
,reloadService: function(btn) {
var me = this;
var webview = me.down('component').el.dom;
var webview = me.getWebView();
if ( me.record.get('enabled') ) {
me.clearUnreadCounter();
@ -592,16 +625,62 @@ Ext.define('Rambox.ux.WebView',{
}
}
,onFailLoad: function(v) {
let me = this
me.errorCodeLog = []
setTimeout(() => Ext.getCmp(me.id+'statusbar').setStatus({ text: '<i class="fa fa-warning fa-fw" aria-hidden="true"></i> 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.down('component').el.dom;
var webview = me.getWebView();
if ( me.record.get('enabled') ) webview.isDevToolsOpened() ? webview.closeDevTools() : webview.openDevTools();
}
,setURL: function(url) {
var me = this;
var webview = me.down('component').el.dom;
var webview = me.getWebView();
me.src = url;
@ -610,7 +689,7 @@ Ext.define('Rambox.ux.WebView',{
,setAudioMuted: function(muted, calledFromDisturb) {
var me = this;
var webview = me.down('component').el.dom;
var webview = me.getWebView();
me.muted = muted;
@ -642,7 +721,7 @@ Ext.define('Rambox.ux.WebView',{
,setNotifications: function(notification, calledFromDisturb) {
var me = this;
var webview = me.down('component').el.dom;
var webview = me.getWebView();
me.notifications = notification;
@ -671,43 +750,47 @@ Ext.define('Rambox.ux.WebView',{
,goBack: function() {
var me = this;
var webview = me.down('component').el.dom;
var webview = me.getWebView();
if ( me.record.get('enabled') ) webview.goBack();
}
,goForward: function() {
var me = this;
var webview = me.down('component').el.dom;
var webview = me.getWebView();
if ( me.record.get('enabled') ) webview.goForward();
}
,zoomIn: function() {
var me = this;
var webview = me.down('component').el.dom;
me.zoomLevel = me.zoomLevel + 0.25;
if ( me.record.get('enabled') ) {
webview.setZoomLevel(me.zoomLevel);
me.record.set('zoomLevel', me.zoomLevel);
}
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() {
var me = this;
var webview = me.down('component').el.dom;
me.zoomLevel = me.zoomLevel - 0.25;
if ( me.record.get('enabled') ) {
webview.setZoomLevel(me.zoomLevel);
me.record.set('zoomLevel', me.zoomLevel);
}
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.down('component').el.dom;
var webview = me.getWebView();
me.zoomLevel = 0;
if ( me.record.get('enabled') ) {
@ -718,7 +801,7 @@ Ext.define('Rambox.ux.WebView',{
,getWebView: function() {
if ( this.record.get('enabled') ) {
return this.down('component').el.dom;
return this.down('component[cls=webview]').el.dom;
} else {
return false;
}

33
app/view/add/Add.js

@ -61,13 +61,19 @@ Ext.define('Rambox.view.add.Add',{
,{
xtype: 'textfield'
,name: 'url'
,value: me.edit && me.service.get('url').indexOf('___') >= 0 ? me.record.get('url').replace(me.service.get('url').split('___')[0], '').replace(me.service.get('url').split('___')[1], '') : (me.record.get('url').indexOf('___') === -1 ? me.record.get('url') : '')
,value: me.edit && me.service.get('url').indexOf('___') >= 0 ? me.record.get('url').replace(me.service.get('url').split('___')[0], '').replace(me.service.get('url').split('___')[1], '').endsWith('/') ? me.record.get('url').replace(me.service.get('url').split('___')[0], '').replace(me.service.get('url').split('___')[1], '').slice(0, -1) : me.record.get('url').replace(me.service.get('url').split('___')[0], '').replace(me.service.get('url').split('___')[1], '') : (me.record.get('url').indexOf('___') === -1 ? me.record.get('url') : '')
,readOnly: me.edit ? (me.service.get('custom_domain') && me.service.get('url') === me.record.get('url') ? true : me.service.get('url').indexOf('___') === -1 && !me.service.get('custom_domain')) : me.record.get('url').indexOf('___') === -1 && me.record.get('custom_domain')
,allowBlank: false
,submitEmptyText: false
,emptyText: me.record.get('url') === '___' ? 'http://' : ''
,vtype: me.record.get('url') === '___' ? 'url' : ''
,listeners: { specialkey: 'onEnter' }
,emptyText: me.record.get('url') === '___' ? 'https://' : ''
,validator: function(v) {
if ( !me.edit ? me.record.get('url') !== '___' : me.service.get('url').indexOf('https://___') === 0 ) return true
if ( v.match(/^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,}))\.?)(?::\d{2,5})?(?:[/?#]\S*)?$/i) === null && v.match(/^https:\/\/\w+(\.\w+)*(:[0-9]+)?\/?(\/[.\w]*)*$/) === null && v.match(/^http:\/\/\w+(\.\w+)*(:[0-9]+)?\/?(\/[.\w]*)*$/) === null ) return false;
return true;
}
,listeners: {
specialkey: 'onEnter'
}
,flex: 1
}
,{
@ -80,12 +86,12 @@ Ext.define('Rambox.view.add.Add',{
items: [
{
text: me.edit ? (me.service.get('url').indexOf('___') === -1 ? 'Official Server' : Ext.String.endsWith(me.service.get('url'), '/') ? me.service.get('url').split('___')[1].slice(0, -1) : me.service.get('url').split('___')[1]) : (me.record.get('url').indexOf('___') === -1 ? 'Official Server' : Ext.String.endsWith(me.record.get('url'), '/') ? me.record.get('url').split('___')[1].slice(0, -1) : me.record.get('url').split('___')[1])
,checked: me.edit ? (me.service.get('custom_domain') && me.service.get('url') === me.record.get('url') ? true : Ext.String.endsWith(me.record.get('url'), me.service.get('url').split('___')[1])) : true
,checked: me.edit ? (me.service.get('custom_domain') && me.service.get('url') === me.record.get('url') ? true : Ext.String.endsWith(me.record.get('url').endsWith('/') ? me.record.get('url').slice(0, -1) : me.record.get('url'), me.service.get('url').split('___')[1])) : true
,disabled: me.edit ? me.service.get('url') === '___' : me.record.get('url') === '___'
}
,{
text: 'Custom Server'
,checked: me.edit ? (me.service.get('custom_domain') && me.service.get('url') === me.record.get('url') ? false : !Ext.String.endsWith(me.record.get('url'), me.service.get('url').split('___')[1])) : false
,checked: me.edit ? (me.service.get('custom_domain') && me.service.get('url') === me.record.get('url') ? false : !Ext.String.endsWith(me.record.get('url').endsWith('/') ? me.record.get('url').slice(0, -1) : me.record.get('url'), me.service.get('url').split('___')[1])) : false
,custom: true
,disabled: me.edit ? !me.service.get('custom_domain') : !me.record.get('custom_domain')
}
@ -97,7 +103,7 @@ Ext.define('Rambox.view.add.Add',{
}
,changeHandler: function(cycleBtn, activeItem) {
Ext.apply(cycleBtn.previousSibling(), {
emptyText: activeItem.custom ? 'http://' : ' '
emptyText: activeItem.custom ? 'https://' : ' '
,vtype: activeItem.custom ? 'url' : ''
});
cycleBtn.previousSibling().applyEmptyText();
@ -120,14 +126,14 @@ Ext.define('Rambox.view.add.Add',{
,{
xtype: 'hiddenfield'
,name: 'cycleValue'
,value: me.edit ? (me.service.get('custom_domain') && me.service.get('url') === me.record.get('url') ? 1 : (!Ext.String.endsWith(me.record.get('url'), me.service.get('url').split('___')[1]) ? 2 : 1)) : 1
,value: me.edit ? (me.service.get('custom_domain') && me.service.get('url') === me.record.get('url') ? 1 : (!Ext.String.endsWith(me.record.get('url').endsWith('/') ? me.record.get('url').slice(0, -1) : me.record.get('url'), me.service.get('url').split('___')[1]) ? 2 : 1)) : 1
}
]
}
,{
xtype: 'textfield'
,fieldLabel: locale['app.window[18]']
,emptyText: 'http://url.com/image.png'
,emptyText: 'https://url.com/image.png'
,name: 'logo'
,vtype: me.record.get('type') === 'custom' ? 'url' : ''
,value: me.record.get('type') === 'custom' ? (me.edit ? me.record.get('logo') : '') : me.record.get('logo')
@ -186,6 +192,15 @@ Ext.define('Rambox.view.add.Add',{
,uncheckedValue: false
,inputValue: true
}
,{
xtype: 'checkbox'
,boxLabel: 'Disable auto-reload on fail'
,name: 'disableAutoReloadOnFail'
,hidden: false
,checked: me.edit ? me.record.get('disableAutoReloadOnFail') : false
,uncheckedValue: false
,inputValue: true
}
,{
xtype: 'checkbox'
,boxLabel: locale['app.window[19]']

1
app/view/add/AddController.js

@ -40,6 +40,7 @@ Ext.define('Rambox.view.add.AddController', {
,includeInGlobalUnreadCounter: formValues.includeInGlobalUnreadCounter
,trust: formValues.trust
,js_unread: formValues.js_unread
,disableAutoReloadOnFail: formValues.disableAutoReloadOnFail
});
var view = Ext.getCmp('tab_'+win.record.get('id'));

147
app/view/main/Main.js

@ -25,6 +25,10 @@ Ext.define('Rambox.view.main.Main', {
,autoRender: true
,autoShow: true
,deferredRender: false
,tabBar: {
id: 'mainTabBar'
,cls: JSON.parse(localStorage.getItem('dontDisturb')) ? 'dontdisturb' : ''
}
,items: [
{
icon: 'resources/IconTray@2x.png'
@ -137,12 +141,15 @@ Ext.define('Rambox.view.main.Main', {
,baseCls: ''
,tooltip: locale['app.main[10]']
,handler: 'removeAllServices'
,bind: {
disabled: '{emptyServices}'
}
}
]
,columns: [
{
xtype: 'templatecolumn'
,width: 50
,width: 52
,variableRowHeight: true
,tpl: '<img src="{[ values.type !== \"custom\" ? \"resources/icons/\"+values.logo : (values.logo == \"\" ? \"resources/icons/custom.png\" : values.logo) ]}" data-qtip="{type:capitalize}" width="32" style="{[ values.enabled ? \"-webkit-filter: grayscale(0)\" : \"-webkit-filter: grayscale(1)\" ]}" />'
}
@ -227,9 +234,9 @@ Ext.define('Rambox.view.main.Main', {
,overflowHandler: 'menu'
,items: [
{
glyph: 'xf1f7@FontAwesome'
glyph: JSON.parse(localStorage.getItem('dontDisturb')) ? 'xf1f7@FontAwesome' : 'xf0f3@FontAwesome'
,text: locale['app.main[16]']+': '+(JSON.parse(localStorage.getItem('dontDisturb')) ? locale['app.window[20]'] : locale['app.window[21]'])
,tooltip: locale['app.main[17]']+'<br/><b>'+locale['app.main[18]']+': F1</b>'
,tooltip: locale['app.main[17]']+'<br/><b>'+locale['app.main[18]']+(require('electron').remote.process.platform === 'darwin' ? ': Cmd + Alt + D</b>' : ': Alt + Shift + D</b>')
,enableToggle: true
,handler: 'dontDisturb'
,reference: 'disturbBtn'
@ -239,77 +246,11 @@ Ext.define('Rambox.view.main.Main', {
,{
glyph: 'xf023@FontAwesome'
,text: locale['app.main[19]']
,tooltip: locale['app.main[20]']+'<br/><b>'+locale['app.main[18]']+': F2</b>'
,tooltip: locale['app.main[20]']+'<br/><b>'+locale['app.main[18]']+(require('electron').remote.process.platform === 'darwin' ? ': Cmd + Alt + L</b>' : ': Alt + Shift + L</b>')
,handler: 'lockRambox'
,id: 'lockRamboxBtn'
}
,'->'
,{
xtype: 'image'
,id: 'avatar'
,bind: {
src: '{avatar}'
,hidden: '{!avatar}'
}
,width: 30
,height: 30
,style: 'border-radius: 50%;border:2px solid #d8d8d8;'
}
,{
id: 'usernameBtn'
,bind: {
text: '{username}'
,hidden: '{!username}'
}
,menu: [
{
text: 'Synchronize Configuration'
,glyph: 'xf0c2@FontAwesome'
,menu: [
{
xtype: 'label'
,bind: {
html: '<b class="menu-title">Last Sync: {last_sync}</b>'
}
}
,{
text: 'Backup'
,glyph: 'xf0ee@FontAwesome'
,scope: Rambox.ux.Auth0
,handler: Rambox.ux.Auth0.backupConfiguration
}
,{
text: 'Restore'
,glyph: 'xf0ed@FontAwesome'
,scope: Rambox.ux.Auth0
,handler: Rambox.ux.Auth0.restoreConfiguration
}
,{
text: 'Check for updated backup'
,glyph: 'xf021@FontAwesome'
,scope: Rambox.ux.Auth0
,handler: Rambox.ux.Auth0.checkConfiguration
}
]
}
,'-'
,{
text: locale['app.main[21]']
,glyph: 'xf08b@FontAwesome'
,handler: 'logout'
}
]
}
,{
text: locale['app.main[22]']
,icon: 'resources/auth0.png'
,id: 'loginBtn'
,tooltip: locale['app.main[23]']+'<br /><br /><i>'+locale['app.main[24]']+' Auth0 (http://auth0.com)</i>'
,bind: {
hidden: '{username}'
}
,handler: 'login'
}
,{
tooltip: locale['preferences[0]']
,glyph: 'xf013@FontAwesome'
@ -317,56 +258,23 @@ Ext.define('Rambox.view.main.Main', {
}
]
}
,bbar: [
{
xtype: 'segmentedbutton'
,allowToggle: false
,items: [
{
text: '<b>Help us</b> with'
,pressed: true
}
,{
text: locale['app.main[25]']
,glyph: 'xf21e@FontAwesome'
,handler: 'showDonate'
}
,{
text: 'Translation'
,glyph: 'xf0ac@FontAwesome'
,href: 'https://crowdin.com/project/rambox/invite'
}
]
}
,'->'
,{
xtype: 'label'
,html: '<span class="fa fa-code" style="color:black;"></span> '+locale['app.main[26]']+' <span class="fa fa-heart" style="color:red;"></span> '+locale['app.main[27]'].replace('Argentina', '<img src="resources/flag.png" alt="Argentina" data-qtip="Argentina" />')
}
,'->'
,{
xtype: 'segmentedbutton'
,allowToggle: false
,items: [
{
text: '<b>Follow us</b>'
,pressed: true
}
,{
glyph: 'xf082@FontAwesome'
,href: 'https://www.facebook.com/ramboxapp'
}
,{
glyph: 'xf099@FontAwesome'
,href: 'https://www.twitter.com/ramboxapp'
}
,{
glyph: 'xf09b@FontAwesome'
,href: 'https://www.github.com/saenzramiro/rambox'
,bbar: {
xtype: 'toolbar'
,cls: 'deprecation'
,items: [
'<i class="fa fa-exclamation-triangle" aria-hidden="true"></i> <b>This version of Rambox is no longer supported.</b> We highly recommend that you update to the new version of Rambox which has a free plan with all the features you already use and much more!'
,'->'
,{
xtype: 'button'
,text: 'Migrate now'
,handler: function(btn) {
btn.setText('Downloading...');
btn.setDisabled(true);
Rambox.app.checkUpdate();
}
]
}
]
}
]
}
}
,{ id: 'tbfill', tabConfig : { xtype : 'tbfill' } }
]
@ -376,5 +284,6 @@ Ext.define('Rambox.view.main.Main', {
,add: 'updatePositions'
,remove: 'updatePositions'
,childmove: 'updatePositions'
,boxready: 'initialize'
}
});

162
app/view/main/MainController.js

@ -3,13 +3,26 @@ Ext.define('Rambox.view.main.MainController', {
,alias: 'controller.main'
,initialize: function( tabPanel ) {
const config = ipc.sendSync('getConfig');
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' ) {
@ -26,7 +39,13 @@ Ext.define('Rambox.view.main.MainController', {
}
var webview = newTab.down('component').el.dom;
if ( webview ) webview.focus();
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 ) {
@ -42,14 +61,20 @@ Ext.define('Rambox.view.main.MainController', {
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 ( rec.get('align') === 'right' ) i--;
if ( align === 'right' ) i--;
rec.set('align', align);
rec.set('position', i);
rec.save();
}
else if ( t.id === 'tbfill' ) {
align = 'right';
}
});
store.load();
@ -89,6 +114,7 @@ Ext.define('Rambox.view.main.MainController', {
,displayTabUnreadCounter: rec.get('displayTabUnreadCounter')
,enabled: rec.get('enabled')
,record: rec
,useragent: ipc.sendSync('getConfig').user_agent
,hidden: hideTab
,tabConfig: {
service: rec
@ -103,7 +129,7 @@ Ext.define('Rambox.view.main.MainController', {
});
}
,removeServiceFn: function(serviceId, total, actual) {
,removeServiceFn: function(serviceId, total, actual, callback) {
var me = this;
if ( !serviceId ) return false;
@ -113,16 +139,14 @@ Ext.define('Rambox.view.main.MainController', {
if ( !rec.get('enabled') ) {
rec.set('enabled', true);
me.onEnableDisableService(null, Ext.getStore('Services').indexOf(rec), true, null, true);
Ext.defer(function() {
// 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);
});
}, 1000);
// 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);
@ -135,20 +159,27 @@ Ext.define('Rambox.view.main.MainController', {
if ( config.default_service === rec.get('id') ) ipc.send('setConfig', Ext.apply(config, { default_service: 'ramboxTab' }));
function clearData(webview, tab) {
webview.getWebContents().clearHistory();
webview.getWebContents().session.flushStorageData();
webview.getWebContents().session.clearCache(function() {
webview.getWebContents().session.clearStorageData(function() {
webview.getWebContents().session.cookies.flushStore(function() {
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 ( 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) })
}
}
@ -166,23 +197,22 @@ Ext.define('Rambox.view.main.MainController', {
,removeAllServices: function(btn, callback) {
var me = this;
// Clear counter for unread messaging
document.title = 'Rambox';
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++);
me.removeServiceFn(serviceId, count, i++, callback || false);
});
if ( Ext.isFunction(callback) ) callback();
if ( count === 0 && Ext.isFunction(callback) ) callback();
Ext.cq1('app-main').resumeEvent('remove');
document.title = 'Rambox';
}
});
} else {
@ -191,11 +221,10 @@ Ext.define('Rambox.view.main.MainController', {
const count = Ext.getStore('Services').getCount();
var i = 1;
Ext.Array.each(Ext.getStore('Services').collect('id'), function(serviceId) {
me.removeServiceFn(serviceId, count, i++);
me.removeServiceFn(serviceId, count, i++, callback || false);
});
if ( Ext.isFunction(callback) ) callback();
if ( count === 0 && Ext.isFunction(callback) ) callback();
Ext.cq1('app-main').resumeEvent('remove');
document.title = 'Rambox';
}
}
@ -268,9 +297,6 @@ Ext.define('Rambox.view.main.MainController', {
,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);
@ -290,6 +316,13 @@ Ext.define('Rambox.view.main.MainController', {
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({
@ -342,14 +375,22 @@ Ext.define('Rambox.view.main.MainController', {
}
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);
@ -437,47 +478,6 @@ Ext.define('Rambox.view.main.MainController', {
}
,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();
}
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 ) {
Tooltip.API.show('zxzKWZfcmgRtHXgth');
}
});

1
app/view/main/MainModel.js

@ -9,5 +9,6 @@ Ext.define('Rambox.view.main.MainModel', {
,username: localStorage.getItem('profile') ? JSON.parse(localStorage.getItem('profile')).name : ''
,avatar: localStorage.getItem('profile') ? JSON.parse(localStorage.getItem('profile')).picture : ''
,last_sync: localStorage.getItem('profile') && JSON.parse(localStorage.getItem('profile')).user_metadata && JSON.parse(localStorage.getItem('profile')).user_metadata.services_lastupdate ? new Date(JSON.parse(localStorage.getItem('profile')).user_metadata.services_lastupdate).toUTCString() : ''
,emptyServices: true
}
});

154
app/view/preferences/Preferences.js

@ -16,12 +16,15 @@ Ext.define('Rambox.view.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]']
@ -71,45 +74,50 @@ Ext.define('Rambox.view.preferences.Preferences',{
,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': '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': 'fr', 'auth0': 'fr', 'label': 'French' }
,{ 'value': 'de', 'auth0': 'de', 'label': 'German' }
,{ 'value': 'de-CH', 'auth0': 'de', 'label': 'German, Switzerland' }
,{ 'value': 'el', 'auth0': 'en', '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': 'tr', 'auth0': 'tr', 'label': 'Turkish' }
,{ 'value': 'uk', 'auth0': 'en', 'label': 'Ukrainian' }
,{ 'value': 'vi', 'auth0': 'en', 'label': 'Vietnamese' }
{ 'value': 'af', 'extjs': 'af', 'label': 'Afrikaans' }
,{ 'value': 'ar', 'extjs': 'en', 'label': 'Arabic' }
,{ 'value': 'bs2', 'extjs': 'en', 'label': 'Barndutsch, Switzerland' }
,{ 'value': 'bn', 'extjs': 'en', 'label': 'Bengali' }
,{ 'value': 'bg', 'extjs': 'en', 'label': 'Bulgarian' }
,{ 'value': 'ca', 'extjs': 'ca', 'label': 'Catalan' }
,{ 'value': 'ceb', 'extjs': 'en', 'label': 'Cebuano' }
,{ 'value': 'zh-CN', 'extjs': 'zh', 'label': 'Chinese Simplified' }
,{ 'value': 'zh-TW', 'extjs': 'zh-tw', 'label': 'Chinese Traditional' }
,{ 'value': 'hr', 'extjs': 'en', 'label': 'Croatian' }
,{ 'value': 'cs', 'extjs': 'cs', 'label': 'Czech' }
,{ 'value': 'da', 'extjs': 'da', 'label': 'Danish' }
,{ 'value': 'nl', 'extjs': 'nl', 'label': 'Dutch' }
,{ 'value': 'en', 'extjs': 'en', 'label': 'English' }
,{ 'value': 'fi', 'extjs': 'fi', 'label': 'Finnish' }
,{ 'value': 'fil', 'extjs': 'en', 'label': 'Filipino' }
,{ 'value': 'fr', 'extjs': 'fr', 'label': 'French' }
,{ 'value': 'de', 'extjs': 'de', 'label': 'German' }
,{ 'value': 'de-CH', 'extjs': 'de', 'label': 'German, Switzerland' }
,{ 'value': 'el', 'extjs': 'el', 'label': 'Greek' }
,{ 'value': 'he', 'extjs': 'en', 'label': 'Hebrew' }
,{ 'value': 'hi', 'extjs': 'en', 'label': 'Hindi' }
,{ 'value': 'hu', 'extjs': 'hu', 'label': 'Hungarian' }
,{ 'value': 'id', 'extjs': 'en', 'label': 'Indonesian' }
,{ 'value': 'it', 'extjs': 'it', 'label': 'Italian' }
,{ 'value': 'ja', 'extjs': 'ja', 'label': 'Japanese' }
,{ 'value': 'ko', 'extjs': 'ko', 'label': 'Korean' }
,{ 'value': 'no', 'extjs': 'no', 'label': 'Norwegian' }
,{ 'value': 'fa', 'extjs': 'fa', 'label': 'Persian' }
,{ 'value': 'pl', 'extjs': 'pl', 'label': 'Polish' }
,{ 'value': 'pt-PT', 'extjs': 'pt-br', 'label': 'Portuguese' }
,{ 'value': 'pt-BR', 'extjs': 'pt-br', 'label': 'Portuguese (Brazilian)' }
,{ 'value': 'ro', 'extjs': 'ro', 'label': 'Romanian' }
,{ 'value': 'ru', 'extjs': 'ru', 'label': 'Russian' }
,{ 'value': 'sr', 'extjs': 'en', 'label': 'Serbian (Cyrillic)' }
,{ 'value': 'sk', 'extjs': 'sk', 'label': 'Slovak' }
,{ 'value': 'es-ES', 'extjs': 'es', 'label': 'Spanish' }
,{ 'value': 'sv-SE', 'extjs': 'sv', 'label': 'Swedish' }
,{ 'value': 'tl', 'extjs': 'en', 'label': 'Tagalog' }
,{ 'value': 'th', 'extjs': 'en', 'label': 'Thai' }
,{ 'value': 'tr', 'extjs': 'tr', 'label': 'Turkish' }
,{ 'value': 'uk', 'extjs': 'en', 'label': 'Ukrainian' }
,{ 'value': 'ur-PK', 'extjs': 'en', 'label': 'Urdu (Pakistan)' }
,{ 'value': 'vi', 'extjs': 'en', 'label': 'Vietnamese' }
]
})
}
@ -146,10 +154,37 @@ Ext.define('Rambox.view.preferences.Preferences',{
,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: 'Default service to display when Rambox starts'
,fieldLabel: locale['preferences[12]']
,labelAlign: 'top'
//,width: 380
//,labelWidth: 105
@ -165,7 +200,7 @@ Ext.define('Rambox.view.preferences.Preferences',{
,{
xtype: 'combo'
,name: 'window_display_behavior'
,fieldLabel: 'Display behaviour'
,fieldLabel: locale['preferences[13]']
,labelAlign: 'left'
,width: 380
,labelWidth: 105
@ -176,9 +211,9 @@ Ext.define('Rambox.view.preferences.Preferences',{
,store: Ext.create('Ext.data.Store', {
fields: ['value', 'label']
,data: [
{ 'value': 'show_taskbar', 'label': 'Show in Taskbar' }
,{ 'value': 'show_trayIcon', 'label': 'Show Tray Icon' }
,{ 'value': 'taskbar_tray', 'label': 'Show in Taskbar and Tray Icon' }
{ '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'
@ -186,7 +221,7 @@ Ext.define('Rambox.view.preferences.Preferences',{
,{
xtype: 'combo'
,name: 'window_close_behavior'
,fieldLabel: 'When closing the main window'
,fieldLabel: locale['preferences[17]']
,labelAlign: 'left'
,width: 380
,labelWidth: 180
@ -197,9 +232,9 @@ Ext.define('Rambox.view.preferences.Preferences',{
,store: Ext.create('Ext.data.Store', {
fields: ['value', 'label']
,data: [
{ 'value': 'keep_in_tray', 'label': 'Keep in tray' }
,{ 'value': 'keep_in_tray_and_taskbar', 'label': 'Keep in tray and/or taskbar' }
,{ 'value': 'quit', 'label': 'Quit' }
{ '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'
@ -207,13 +242,13 @@ Ext.define('Rambox.view.preferences.Preferences',{
,{
xtype: 'checkbox'
,name: 'always_on_top'
,boxLabel: 'Always on top'
,boxLabel: locale['preferences[21]']
,value: config.always_on_top
}
,{
xtype: 'checkbox'
,name: 'systemtray_indicator'
,boxLabel: 'Show System Tray indicator on unread messages'
,boxLabel: locale['preferences[22]']
,value: config.systemtray_indicator
,hidden: process.platform === 'darwin'
}
@ -226,7 +261,7 @@ Ext.define('Rambox.view.preferences.Preferences',{
,{
xtype: 'checkbox'
,name: 'disable_gpu'
,boxLabel: 'Disable Hardware Acceleration (needs to relaunch)'
,boxLabel: locale['preferences[23]']
,value: config.disable_gpu
}
,{
@ -234,10 +269,20 @@ Ext.define('Rambox.view.preferences.Preferences',{
,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: 'Master Password - Ask for password on startup'
,title: locale['preferences[24]']
,collapsed: !config.master_password
,checkboxToggle: true
,checkboxName: 'master_password'
@ -249,7 +294,7 @@ Ext.define('Rambox.view.preferences.Preferences',{
{
xtype: 'textfield'
,inputType: 'password'
,fieldLabel: 'Password'
,fieldLabel: locale['preferences[25]']
,name: 'master_password1'
,itemId: 'pass'
,flex: 1
@ -265,7 +310,7 @@ Ext.define('Rambox.view.preferences.Preferences',{
,{
xtype: 'textfield'
,inputType: 'password'
,fieldLabel: 'Repeat Password'
,fieldLabel: locale['preferences[26]']
,name: 'master_password2'
,margin: '0 0 0 10'
,vtype: 'password'
@ -312,6 +357,7 @@ Ext.define('Rambox.view.preferences.Preferences',{
,name: 'proxyPassword'
,value: config.proxyPassword
,emptyText: 'Optional'
,inputType: 'password'
}
]
}

9
app/view/preferences/PreferencesController.js

@ -45,10 +45,17 @@ Ext.define('Rambox.view.preferences.PreferencesController', {
return;
}
// User Agent
if ( values.user_agent !== ipc.sendSync('getConfig').user_agent ) {
Ext.Msg.confirm('Action required', 'To change the user agent of Rambox, you need to reload the app. Do you want to do it now?', function(btnId) {
if ( btnId === 'yes' ) ipc.send('relaunchApp');
});
}
// Locale
if ( values.locale !== ipc.sendSync('getConfig').locale ) {
localStorage.setItem('locale', values.locale);
localStorage.setItem('locale-auth0', me.getView().down('form').down('combo[name="locale"]').getSelection().get('auth0'));
localStorage.setItem('locale-extjs', me.getView().down('form').down('combo[name="locale"]').getSelection().get('extjs'));
Ext.Msg.confirm('Action required', 'To change the language of Rambox, you need to reload the app. Do you want to do it now?', function(btnId) {
if ( btnId === 'yes' ) ipc.send('relaunchApp');
});

52
appveyor.yml

@ -1,4 +1,6 @@
version: 0.5.16
environment:
matrix:
- nodejs_version: '14.16.1'
pull_requests:
do_not_increment_build_number: true
branches:
@ -6,46 +8,18 @@ branches:
- master
skip_non_tags: true
init:
- cmd: git config --global core.autocrlf input
- cmd: git config --global core.autocrlf input
- cmd: node --version
- cmd: npm --version
install:
- cmd: >-
git reset --hard HEAD
- ps: Update-NodeJsInstallation $env:nodejs_version x64
- cmd: >-
git clone https://github.com/saenzramiro/rambox-build.git %APPVEYOR_BUILD_FOLDER%\build\production\Rambox\
npm run sencha:clean
cd %APPVEYOR_BUILD_FOLDER%\build\production\Rambox\
git clone https://github.com/saenzramiro/rambox-build.git %APPVEYOR_BUILD_FOLDER%\build\production\Rambox\
npm install npm -g
npm install
npm --prefix %APPVEYOR_BUILD_FOLDER%\build\production\Rambox\ install %APPVEYOR_BUILD_FOLDER%\build\production\Rambox\
npm prune
cache:
- '%APPDATA%\npm-cache'
- '%USERPROFILE%\.electron'
- node_modules
- build\production\Rambox\node_modules
npm install
build_script:
- cmd: >-
node --version
npm --version
node_modules/.bin/build --win --ia32 --x64
- cmd: cd %APPVEYOR_BUILD_FOLDER%\build\production\Rambox\
- cmd: npm run build:win
test: off
artifacts:
- path: dist\win\*.exe
- path: dist\win\*.nupkg
- path: dist\win\RELEASES
- path: dist\win-ia32\*.exe
- path: dist\*.zip
deploy:
- provider: GitHub
tag: $(appveyor_build_version)
release: $(appveyor_build_version)
auth_token:
secure: RKFkz2S89dkYXdW+k47Wv42yrUeE1bDDMkM1PNuxrb0ZOcVVXPO88+t5dUllyvOG
draft: true
prerelease: false

368
electron/main.js

@ -1,12 +1,12 @@
'use strict';
const {app, protocol, BrowserWindow, dialog, shell, Menu, ipcMain, nativeImage, session} = require('electron');
const {app, BrowserWindow, shell, Menu, ipcMain, nativeImage, session} = require('electron');
// Tray
const tray = require('./tray');
// AutoLaunch
var AutoLaunch = require('auto-launch-patched');
// Configuration
const Config = require('electron-config');
const Config = require('electron-store');
// Development
const isDev = require('electron-is-dev');
// Updater
@ -15,11 +15,18 @@ const updater = require('./updater');
var fs = require("fs");
const path = require('path');
// Disk usage:
// const disk = require('diskusage');
if ( isDev ) app.getVersion = function() { return require('../package.json').version; }; // FOR DEV ONLY, BECAUSE IN DEV RETURNS ELECTRON'S VERSION
// 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
@ -36,7 +43,9 @@ const config = new Config({
,proxyPassword: ''
,locale: 'en'
,enable_hidpi_support: false
,user_agent: ''
,default_service: 'ramboxTab'
,sendStatistics: false
,x: undefined
,y: undefined
@ -52,89 +61,29 @@ if (config.get('enable_hidpi_support') && (process.platform === 'win32')) {
app.commandLine.appendSwitch('force-device-scale-factor', '1')
}
app.commandLine.appendSwitch('lang', config.get('locale') === 'en' ? 'en-US' : config.get('locale'));
// Temporary fix to load Twitter and other websites inside webviews
// Bug related with Electron: https://github.com/electron/electron/issues/25469
app.commandLine.appendSwitch('disable-features', 'CrossOriginOpenerPolicy');
// Because we build it using Squirrel, it will assign UserModelId automatically, so we match it here to display notifications correctly.
// https://github.com/electron-userland/electron-builder/issues/362
app.setAppUserModelId('com.squirrel.Rambox.Rambox');
app.setAppUserModelId('com.grupovrs.ramboxce');
// Menu
const appMenu = require('./menu')(config);
// Configure AutoLaunch
const appLauncher = new AutoLaunch({
name: 'Rambox'
,isHidden: config.get('start_minimized')
});
config.get('auto_launch') && !isDev ? appLauncher.enable() : appLauncher.disable();
// this should be placed at top of main.js to handle setup events quickly
if (handleSquirrelEvent()) {
// squirrel event handled and app will exit in 1000ms, so don't do anything else
return;
let appLauncher;
if ( !isDev ) {
appLauncher = new AutoLaunch({
name: 'Rambox'
,isHidden: config.get('start_minimized')
});
config.get('auto_launch') ? appLauncher.enable() : appLauncher.disable();
}
function handleSquirrelEvent() {
if (process.argv.length === 1) {
return false;
}
const ChildProcess = require('child_process');
const appFolder = path.resolve(process.execPath, '..');
const rootAtomFolder = path.resolve(appFolder, '..');
const updateDotExe = path.resolve(path.join(rootAtomFolder, 'Update.exe'));
const exeName = path.basename(process.execPath);
const spawn = function(command, args) {
let spawnedProcess, error;
try {
spawnedProcess = ChildProcess.spawn(command, args, {detached: true});
} catch (error) {}
return spawnedProcess;
};
const spawnUpdate = function(args) {
return spawn(updateDotExe, args);
};
const squirrelEvent = process.argv[1];
switch (squirrelEvent) {
case '--squirrel-install':
case '--squirrel-updated':
// Optionally do things such as:
// - Add your .exe to the PATH
// - Write to the registry for things like file associations and
// explorer context menus
// Install desktop and start menu shortcuts
spawnUpdate(['--createShortcut', exeName]);
setTimeout(app.quit, 1000);
return true;
case '--squirrel-uninstall':
// Undo anything you did in the --squirrel-install and
// --squirrel-updated handlers
// Remove desktop and start menu shortcuts
spawnUpdate(['--removeShortcut', exeName]);
// Remove user app data
require('rimraf').sync(require('electron').app.getPath('userData'));
setTimeout(app.quit, 1000);
return true;
case '--squirrel-obsolete':
// This is called on the outgoing version of your app before
// we update to the new version - it's the opposite of
// --squirrel-updated
app.quit();
return true;
}
};
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow;
@ -156,15 +105,22 @@ function createWindow () {
,show: !config.get('start_minimized')
,acceptFirstMouse: true
,webPreferences: {
webSecurity: false
,nodeIntegration: true
enableRemoteModule: true
,plugins: true
,partition: 'persist:rambox'
,nodeIntegration: true
,webviewTag: true
,contextIsolation: false
,spellcheck: false
}
});
if ( !config.get('start_minimized') && config.get('maximized') ) mainWindow.maximize();
if ( config.get('window_display_behavior') !== 'show_trayIcon' && config.get('start_minimized') ) mainWindow.minimize();
// Check if user has defined a custom User-Agent
if ( config.get('user_agent').length > 0 ) mainWindow.webContents.setUserAgent( config.get('user_agent') );
// Wait for the mainWindow.loadURL(..) and the optional mainWindow.webContents.openDevTools()
// to be finished before minimizing
config.get('start_minimized') && mainWindow.webContents.once('did-finish-load', () => config.get('window_display_behavior') === 'show_trayIcon' ? mainWindow.hide() : mainWindow.minimize());
// Check if the window its outside of the view (ex: multi monitor setup)
const { positionOnScreen } = require('./utils/positionOnScreen');
@ -187,7 +143,7 @@ function createWindow () {
tray.create(mainWindow, config);
if ( fs.existsSync(path.resolve(path.dirname(process.execPath), '..', 'Update.exe')) && process.argv.indexOf('--without-update') === -1 ) updater.initialize(mainWindow);
updater.initialize(mainWindow);
// Open links in default browser
mainWindow.webContents.on('new-window', function(e, url, frameName, disposition, options) {
@ -196,6 +152,7 @@ function createWindow () {
case 'new-window':
e.preventDefault();
const win = new BrowserWindow(options);
if ( config.get('user_agent').length > 0 ) win.webContents.setUserAgent( config.get('user_agent') );
win.once('ready-to-show', () => win.show());
win.loadURL(url);
e.newGuest = win;
@ -255,6 +212,15 @@ function createWindow () {
}
}
});
mainWindow.on('minimize', function(e) {
if ( config.get('window_display_behavior') === 'show_trayIcon' ) mainWindow.setSkipTaskbar(true);
});
mainWindow.on('restore', function(e) {
if ( config.get('window_display_behavior') === 'show_taskbar' ) mainWindow.setSkipTaskbar(false);
});
mainWindow.on('show', function(e) {
if ( config.get('window_display_behavior') !== 'show_trayIcon' ) mainWindow.setSkipTaskbar(false);
});
mainWindow.on('closed', function(e) {
mainWindow = null;
});
@ -266,6 +232,10 @@ function createMasterPasswordWindow() {
mainMasterPasswordWindow = new BrowserWindow({
backgroundColor: '#0675A0'
,frame: false
,webPreferences: {
nodeIntegration: true
,enableRemoteModule: true
}
});
// Open the DevTools.
if ( isDev ) mainMasterPasswordWindow.webContents.openDevTools();
@ -277,15 +247,12 @@ function createMasterPasswordWindow() {
function updateBadge(title) {
title = title.split(" - ")[0]; //Discard service name if present, could also contain digits
var messageCount = title.match(/\d+/g) ? parseInt(title.match(/\d+/g).join("")) : 0;
messageCount = isNaN(messageCount) ? 0 : messageCount;
tray.setBadge(messageCount, config.get('systemtray_indicator'));
if (process.platform === 'win32') { // Windows
if (messageCount === 0) {
mainWindow.setOverlayIcon(null, "");
return;
}
if (process.platform === 'win32') {
if (messageCount === 0) return mainWindow.setOverlayIcon(null, '');
mainWindow.webContents.send('setBadge', messageCount);
} else { // macOS & Linux
app.setBadgeCount(messageCount);
@ -294,15 +261,51 @@ function updateBadge(title) {
if ( messageCount > 0 && !mainWindow.isFocused() && !config.get('dont_disturb') && config.get('flash_frame') ) mainWindow.flashFrame(true);
}
function formatBytes(bytes, decimals = 2) {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const dm = decimals < 0 ? 0 : decimals;
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}
/* async function availableSpaceWatchDog() {
// optionally render this information also in rambox window
try {
const { available } = await disk.check(appPath);
if (available < 1073741824) { // 1 GB
const options = {
type: 'warning',
buttons: ['OK, quit'],
defaultId: 0,
title: `Running out of disk space! - Rambox shutting down`,
detail: `You've got just ${formatBytes(available)} space left.\n\nRambox has been frozen to prevent settings corruption.\n\nOnce you quit this dialog, Rambox will shutdown.\n\n1 GB of avalable disk space is required.\nFree up space on partition where Rambox is installed then start the app again.\n\nRambox path: \n${appPath}`,
message: `Running out of disk space! - Rambox shutting down`,
};
dialog.showMessageBoxSync(null, options);
app.quit();
}
} catch (err) {
console.error(err)
}
} */
ipcMain.on('setBadge', function(event, messageCount, value) {
var img = nativeImage.createFromDataURL(value);
mainWindow.setOverlayIcon(img, messageCount.toString());
mainWindow.setOverlayIcon(nativeImage.createFromDataURL(value), messageCount.toString());
});
ipcMain.on('getConfig', function(event, arg) {
event.returnValue = config.store;
});
ipcMain.on('sConfig', function(event, values) {
config.set(values);
event.returnValue = config;
});
ipcMain.on('setConfig', function(event, values) {
config.set(values);
@ -312,10 +315,12 @@ ipcMain.on('setConfig', function(event, values) {
// always_on_top
mainWindow.setAlwaysOnTop(values.always_on_top);
// auto_launch
values.auto_launch ? appLauncher.enable() : appLauncher.disable();
if ( !isDev ) values.auto_launch ? appLauncher.enable() : appLauncher.disable();
// systemtray_indicator
updateBadge(mainWindow.getTitle());
mainWindow.webContents.executeJavaScript('(function(a){if(a)a.controller.initialize(a)})(Ext.cq1("app-main"))');
switch ( values.window_display_behavior ) {
case 'show_taskbar':
mainWindow.setSkipTaskbar(false);
@ -334,6 +339,10 @@ ipcMain.on('setConfig', function(event, values) {
}
});
ipcMain.on('sendStatistics', function(event) {
event.returnValue = config.get('sendStatistics');
});
ipcMain.on('validateMasterPassword', function(event, pass) {
if ( config.get('master_password') === require('crypto').createHash('md5').update(pass).digest('hex') ) {
createWindow();
@ -345,6 +354,7 @@ ipcMain.on('validateMasterPassword', function(event, pass) {
// Handle Service Notifications
ipcMain.on('setServiceNotifications', function(event, partition, op) {
if ( partition === null ) return;
session.fromPartition(partition).setPermissionRequestHandler(function(webContents, permission, callback) {
if (permission === 'notifications') return callback(op);
callback(true)
@ -353,7 +363,7 @@ ipcMain.on('setServiceNotifications', function(event, partition, op) {
ipcMain.on('setDontDisturb', function(event, arg) {
config.set('dont_disturb', arg);
})
});
// Reload app
ipcMain.on('reloadApp', function(event) {
@ -366,7 +376,12 @@ ipcMain.on('relaunchApp', function(event) {
app.exit(0);
});
const shouldQuit = app.makeSingleInstance((commandLine, workingDirectory) => {
const shouldQuit = app.requestSingleInstanceLock();
if (!shouldQuit) {
app.quit();
return;
}
app.on('second-instance', (event, commandLine, workingDirectory) => {
// Someone tried to run a second instance, we should focus our window.
if (mainWindow) {
if (mainWindow.isMinimized()) mainWindow.restore();
@ -377,10 +392,85 @@ const shouldQuit = app.makeSingleInstance((commandLine, workingDirectory) => {
}
});
if (shouldQuit) {
app.quit();
return;
}
// ALLOWED URLS POPUPS
let allowPopUp = [
'feedly.com/v3/auth/',
'identity.linuxfoundation.org/cas/login',
'auth.missiveapp.com',
'accounts.google.com/AccountChooser',
'facebook.com/v3.1/dialog/oauth?',
'accounts.google.com/o/oauth2',
'app.slack.com/files/import/gdrive',
'spikenow.com/s/account',
'app.mixmax.com/_oauth/google',
'officeapps.live.com',
'dropbox.com/profile_services/start_auth_flow',
'facebook.com/v3.2/dialog/oauth?',
'notion.so/googlepopupredirect',
'zoom.us/office365',
'figma.com/start_google_sso',
'mail.google.com/mail',
'app.slack.com/free-willy/',
'messenger.com/videocall',
'api.moo.do',
'manychat.com/fb?popup',
'=?print=true' // esta ultima checkea como anda imprimir un pedf desde gmail, si no va bie sacala
];
app.on('web-contents-created', (webContentsCreatedEvent, contents) => {
if (contents.getType() !== 'webview') return;
// Block some Deep links to prevent that open its app (Ex: Slack)
contents.on('will-navigate', (event, url) => url.substring(0, 8) === 'slack://' && event.preventDefault());
// New Window handler
contents.on('new-window', (event, url, frameName, disposition, options, additionalFeatures, referrer, postBody) => {
// If the url is about:blank we allow the window and handle it in 'did-create-window'
if (['about:blank', 'about:blank#blocked'].includes(url)) {
event.preventDefault();
Object.assign(options, { show: false });
const win = new BrowserWindow(options);
win.center();
let once = false;
win.webContents.on('will-navigate', (e, nextURL) => {
if (once) return;
if (['about:blank', 'about:blank#blocked'].includes(nextURL)) return;
once = true;
let allow = false;
allowPopUp.forEach(url => nextURL.indexOf(url) > -1 && (allow = true));
// If the url is in aboutBlankOnlyWindow we handle this as a popup window
if (allow) return win.show();
shell.openExternal(nextURL);
win.close()
})
event.newGuest = win;
return;
}
// We check if url is in the allowPopUpLoginURLs or allowForegroundTabURLs in Firebase to open a as a popup,
// if it is not we send this to the app
let allow = false;
allowPopUp.forEach(allowed => url.indexOf(allowed) > -1 && (allow = true));
if (allow) return;
shell.openExternal(url);
event.preventDefault();
});
contents.on('did-create-window', (win, details) => {
// Here we center the new window.
win.center();
// The following code is for handling the about:blank cases only.
if (!['about:blank', 'about:blank#blocked'].includes(details.url)) return;
let once = false;
win.webContents.on('will-navigate', (e, nextURL) => {
if (once) return;
if (['about:blank', 'about:blank#blocked'].includes(nextURL)) return;
once = true;
let allow = false;
allowPopUp.forEach(url => nextURL.indexOf(url) > -1 && (allow = true));
// If the url is in aboutBlankOnlyWindow we handle this as a popup window
if (allow) return win.show();
shell.openExternal(url);
win.close();
});
});
});
// Code for downloading images as temporal files
// Credit: Ghetto Skype (https://github.com/stanfieldr/ghetto-skype)
@ -405,6 +495,8 @@ ipcMain.on('image:download', function(event, url, partition) {
}
});
if ( config.get('user_agent').length > 0 ) tmpWindow.webContents.setUserAgent( config.get('user_agent') );
tmpWindow.webContents.session.once('will-download', (event, downloadItem) => {
imageCache[url] = file = {
path: tmp.tmpNameSync() + '.' + mime.extension(downloadItem.getMimeType())
@ -438,39 +530,107 @@ ipcMain.on('image:popup', function(event, url, partition) {
}
});
if ( config.get('user_agent').length > 0 ) tmpWindow.webContents.setUserAgent( config.get('user_agent') );
tmpWindow.maximize();
tmpWindow.loadURL(url);
});
ipcMain.on('toggleWin', function(event, allwaysShow) {
if ( config.get('window_display_behavior') !== 'show_trayIcon' ) mainWindow.setSkipTaskbar(false);
if ( !mainWindow.isMinimized() && mainWindow.isMaximized() && mainWindow.isVisible() ) { // Maximized
!allwaysShow ? mainWindow.close() : mainWindow.show();
} else if ( mainWindow.isMinimized() && !mainWindow.isMaximized() && !mainWindow.isVisible() ) { // Minimized
if ( process.platform === 'linux' ) {
mainWindow.minimize();
mainWindow.restore();
mainWindow.focus();
return
}
mainWindow.restore();
} else if ( !mainWindow.isMinimized() && !mainWindow.isMaximized() && mainWindow.isVisible() ) { // Windowed mode
!allwaysShow ? mainWindow.close() : mainWindow.show();
} else if ( mainWindow.isMinimized() && !mainWindow.isMaximized() && mainWindow.isVisible() ) { // Closed to taskbar
if ( process.platform === 'linux' ) {
mainWindow.minimize();
mainWindow.restore();
mainWindow.focus();
return
}
mainWindow.restore();
} else if ( !mainWindow.isMinimized() && mainWindow.isMaximized() && !mainWindow.isVisible() ) { // Closed maximized to tray
mainWindow.show();
} else if ( !mainWindow.isMinimized() && !mainWindow.isMaximized() && !mainWindow.isVisible() ) { // Closed windowed to tray
mainWindow.show();
} else if ( mainWindow.isMinimized() && !mainWindow.isMaximized() && !mainWindow.isVisible() ) { // Closed minimized to tray
mainWindow.restore();
} else {
mainWindow.show();
} else {
if ( process.platform === 'linux' ) {
mainWindow.minimize();
mainWindow.maximize();
mainWindow.focus();
return
}
mainWindow.restore();
}
});
// ScreenShare
ipcMain.on('screenShare:show', (event, screenList) => {
let tmpWindow = new BrowserWindow({
title: 'Rambox - Select screen',
width: 600,
height: 500,
icon: __dirname + '/../resources/Icon.ico',
autoHideMenuBar: true,
transparent: true,
show: true,
frame: false,
hasShadow: true,
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
},
});
const close = () => {
tmpWindow.close();
tmpWindow = null;
};
const onCancel = () => {
event.sender.send('screenShare:cancel');
close();
};
const onShare = (_, shareId) => {
event.sender.send('screenShare:share', shareId);
close();
};
ipcMain.handle('screenShare:getSources', () => screenList);
ipcMain.on('screenShare:cancelSelection', onCancel);
ipcMain.on('screenShare:selectScreen', onShare);
tmpWindow.on('closed', () => {
ipcMain.removeHandler('screenShare:getSources');
ipcMain.removeAllListeners('screenShare:cancelSelection');
ipcMain.removeAllListeners('screenShare:selectScreen');
});
tmpWindow.loadFile(__dirname + '/../screenselector.html');
});
// Proxy
if ( config.get('proxy') ) {
app.commandLine.appendSwitch('proxy-server', config.get('proxyHost')+':'+config.get('proxyPort'));
app.on('login', (event, webContents, request, authInfo, callback) => {
if(!authInfo.isProxy)
return;
event.preventDefault()
event.preventDefault();
callback(config.get('proxyLogin'), config.get('proxyPassword'))
})
}
@ -485,8 +645,8 @@ if ( config.get('disable_gpu') ) app.disableHardwareAcceleration();
// initialization and is ready to create browser windows.
app.on('ready', function() {
config.get('master_password') ? createMasterPasswordWindow() : createWindow();
// setInterval(availableSpaceWatchDog, 1000 * 60);
});
// Quit when all windows are closed.
app.on('window-all-closed', function () {
// On OS X it is common for applications and their menu bar
@ -503,7 +663,9 @@ app.on('activate', function () {
config.get('master_password') ? createMasterPasswordWindow() : createWindow();
}
if ( mainWindow !== null ) mainWindow.show();
if (mainWindow) {
mainWindow.show();
}
});
app.on('before-quit', function () {

85
electron/menu.js

@ -1,6 +1,7 @@
'use strict';
const os = require('os');
const electron = require('electron');
const { systemPreferences } = require('electron')
const app = electron.app;
const BrowserWindow = electron.BrowserWindow;
const shell = electron.shell;
@ -22,7 +23,7 @@ module.exports = function(config) {
{
label: `&`+locale['menu.help[0]'],
click() {
shell.openExternal('http://rambox.pro');
shell.openExternal('https://rambox.app');
}
},
{
@ -40,44 +41,24 @@ module.exports = function(config) {
{
label: `&GitHub`,
click() {
shell.openExternal('https://www.github.com/saenzramiro/rambox');
shell.openExternal('https://github.com/ramboxapp/community-edition');
}
},
{
type: 'separator'
},
{
label: '&'+locale['menu.help[1]'],
click() {
const body = `
<!-- Please describe here your issue and steps to reproduce it. -->
<!-- DON'T REMOVE THE FOLLOWING LINES -->
-
> ${app.getName()} ${app.getVersion()}
> Electron ${process.versions.electron}
> ${process.platform} ${process.arch} ${os.release()}`;
shell.openExternal(`https://github.com/saenzramiro/rambox/issues/new?body=${encodeURIComponent(body)}`);
}
},
{
label: `&`+locale['menu.help[2]'],
click() {
shell.openExternal('https://rambox.typeform.com/to/t7jc4C');
}
},
{
label: `&Tools`,
submenu: [
{
label: `&Clear Cache`,
click(item, win) {
win.webContents.session.clearCache(function() {
win.webContents.session.clearCache()
.then(() => {
win.reload();
});
}).catch(err => {
console.log(err)
})
}
},
{
@ -85,22 +66,15 @@ module.exports = function(config) {
click(item, win) {
win.webContents.session.clearStorageData({
storages: ['localstorage']
}, function() {
}).then(() => {
win.reload();
});
}).catch(err => {
console.log(err)
})
}
}
]
},
{
type: 'separator'
},
{
label: `&`+locale['menu.help[3]'],
click() {
shell.openExternal('https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=WU75QWS7LH2CA');
}
}
];
let tpl = [
@ -163,13 +137,28 @@ module.exports = function(config) {
type: 'separator'
},
{
role: 'zoomin'
label: '&Toggle Status Bar',
click() {
sendAction('toggleStatusBar');
}
},
{
role: 'zoomout'
type: 'separator'
},
{
role: 'resetzoom'
label: 'Zoom In',
accelerator: 'Ctrl+Plus',
click(item, win) { win.webContents.send('zoomin-webview')}
},
{
label: 'Zoom Out',
accelerator: 'Ctrl+-',
click(item, win) { win.webContents.send('zoomout-webview')}
},
{
label: 'Reset Zoom',
accelerator: 'Ctrl+0',
click(item, win) { win.webContents.send('resetzoom-webview')}
}
]
},
@ -209,7 +198,7 @@ module.exports = function(config) {
}
];
if (process.platform === 'darwin') {
if ( process.platform === 'darwin' ) {
tpl.unshift({
label: appName,
submenu: [
@ -268,6 +257,18 @@ module.exports = function(config) {
}
]
});
helpSubmenu.push({
type: 'separator'
});
helpSubmenu.push({
label: 'Grant Microphone and Camera permissions',
visible: systemPreferences.getMediaAccessStatus('microphone') !== 'granted' || systemPreferences.getMediaAccessStatus('camera') !== 'granted',
click(item, win) {
const webContents = win.webContents;
const send = webContents.send.bind(win.webContents);
send('grantPermissions');
}
});
} else {
tpl.unshift({
label: '&'+locale['menu.file[0]'],

11
electron/tray.js

@ -44,12 +44,12 @@ exports.create = function(win, config) {
// Double click is not supported and Click its only supported when app indicator is not used.
// Read more here (Platform limitations): https://github.com/electron/electron/blob/master/docs/api/tray.md
appIcon.on('click', function() {
win.webContents.executeJavaScript('ipc.send("toggleWin", true);');
win.webContents.executeJavaScript('ipc.send("toggleWin", false);');
});
break;
case 'win32':
appIcon.on('double-click', function() {
win.webContents.executeJavaScript('ipc.send("toggleWin", true);');
win.webContents.executeJavaScript('ipc.send("toggleWin", false);');
});
break;
default:
@ -66,12 +66,13 @@ exports.setBadge = function(messageCount, showUnreadTray) {
if (process.platform === 'darwin' || !appIcon) return;
let icon;
messageCount = parseInt(messageCount);
if (process.platform === 'linux') {
icon = messageCount && showUnreadTray ? 'IconTrayUnread.png' : 'IconTray.png';
icon = messageCount > 0 && showUnreadTray ? 'IconTrayUnread.png' : 'IconTray.png';
} else {
icon = messageCount && showUnreadTray ? 'IconTrayUnread.ico' : 'Icon.ico';
icon = messageCount > 0 && showUnreadTray ? 'IconTrayUnread.ico' : 'Icon.ico';
}
const iconPath = path.join(__dirname, `../resources/${icon}`);
appIcon.setImage(iconPath);
appIcon.setImage(electron.nativeImage.createFromPath(iconPath));
};

32
electron/updater.js

@ -1,19 +1,29 @@
const {app, autoUpdater, ipcMain} = require('electron');
const version = app.getVersion();
const platform = process.platform === 'darwin' ? 'osx' : process.platform;
const url = `https://getrambox.herokuapp.com/update/${platform}/${version}`;
const { app, ipcMain, BrowserWindow } = require('electron');
const { autoUpdater } = require("electron-updater");
// autoUpdater.logger = require("electron-log");
// autoUpdater.logger.transports.file.level = "debug";
// autoUpdater.currentVersion = '0.8.0';
// autoUpdater.updateConfigPath = path.join(__dirname, 'dev-app-update.yml');
autoUpdater.setFeedURL({
"provider": "github",
"owner": "ramboxapp",
"repo": "download",
"vPrefixedTagName": true
});
const initialize = (window) => {
const webContents = window.webContents;
const send = webContents.send.bind(window.webContents);
autoUpdater.on('checking-for-update', (event) => send('autoUpdater:checking-for-update:'));
autoUpdater.on('update-downloaded', (event, ...args) => send('autoUpdater:update-downloaded', ...args));
ipcMain.on('autoUpdater:quit-and-install', (event) => autoUpdater.quitAndInstall());
ipcMain.on('autoUpdater:check-for-updates', (event) => autoUpdater.checkForUpdates());
webContents.on('did-finish-load', () => {
autoUpdater.setFeedURL(url);
//autoUpdater.checkForUpdates();
autoUpdater.on('checking-for-update', (event) => send('autoUpdater:checking-for-update'));
autoUpdater.on('update-downloaded', (...args) => send('autoUpdater:update-downloaded', ...args));
ipcMain.on('autoUpdater:quit-and-install', (event) => {
app.removeAllListeners('window-all-closed');
BrowserWindow.getAllWindows().forEach((browserWindow) => browserWindow.removeAllListeners('close'));
autoUpdater.quitAndInstall(true, true);
});
ipcMain.on('autoUpdater:check-for-updates', (event) => autoUpdater.checkForUpdates());
};
module.exports = {initialize};

4
env-sample.js

@ -1,4 +0,0 @@
var auth0Cfg = {
clientID: ''
,domain: ''
};

2
ext/packages/ext-aria/build/resources/Readme.md

@ -1,3 +1,3 @@
# ext-aria/resources
This folder contains static resources (typically an `"images"` folder as well).
This folder contains static resources (typically an `images` folder as well).

2
ext/packages/ext-aria/resources/Readme.md

@ -1,3 +1,3 @@
# ext-aria/resources
This folder contains static resources (typically an `"images"` folder as well).
This folder contains static resources (typically an `images` folder as well).

4
ext/packages/ext-aria/sass/etc/Readme.md

@ -1,4 +1,4 @@
# ext-aria/sass/etc
This folder contains miscellaneous SASS files. Unlike `"ext-aria/sass/etc"`, these files
need to be used explicitly.
This folder contains miscellaneous SASS files.
Unlike `ext-aria/sass/etc`, these files need to be used explicitly.

1
ext/packages/sencha-soap/Readme.md

@ -1,2 +1 @@
# sencha-soap - Read Me

65
index.html

@ -1,5 +1,6 @@
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta charset="UTF-8">
@ -7,36 +8,12 @@
<title>Rambox</title>
<script type='text/javascript'>
var xhr = new XMLHttpRequest();
var file = "http://rambox.pro/api/latestversion.json";
var randomNum = Math.round(Math.random() * 10000);
xhr.open('HEAD', file + "?rand=" + randomNum, true);
xhr.send();
xhr.addEventListener("readystatechange", function() {
setTimeout(processRequest, 5000);
}, false);
function processRequest(e) {
if (xhr.readyState == 4) {
if (xhr.status >= 200 && xhr.status < 304) {
console.info('Internet Connection', true);
} else {
console.info('Internet Connection', false);
alert('Please, check your internet connection and restart Rambox. If you use a Proxy, please go to Preferences to configure it.', 'No Internet Connection');
}
}
}
</script>
<!-- The line below must be kept intact for Sencha Cmd to build your application -->
<script id="microloader" type="text/javascript" src="bootstrap.js"></script>
<!--- Localization -->
<script type='text/javascript'>
(function(d, s){
(function(d, s){
var t = d.createElement(s), e = d.getElementsByTagName(s)[0];
t.type = "text/javascript"; e.parentNode.insertBefore(t, e);
t.src = "resources/languages/"+require('electron').ipcRenderer.sendSync('getConfig').locale+".js";
@ -44,19 +21,26 @@
</script>
<!--- Localization -->
<!--- Tooltip player -->
<!--- Signalayer player -->
<script type='text/javascript'>
(function(d, s){
var t = d.createElement(s), e = d.getElementsByTagName(s)[0];
t.type = "text/javascript"; e.parentNode.insertBefore(t, e);
t.async = "async";
t.src = "https://cdn.tooltip.io/static/player.js?apiKey=sEF8shc4KSuqtHMx0ztmTFdcrQO0cAVpszZ9Y8hLfQ2";
})(document, "script");
window.Signalayer||function(t,e){var o={
url:"https://cdn.signalayer.com/static/player.js",
key:"sEF8shc4KSuqtHMx0ztmTFdcrQO0cAVpszZ9Y8hLfQ2",
async:true
};window.Signalayer={cs:[],_apiKey:o.key};for(
var r=["identify","goal","updateUserData","start","stop","refresh","show","hide","on"],
i={},n=0;n>r.length;n++){var a=r[n];i[a]=function(t){return function(){var
e=Array.prototype.slice.call(arguments);
window.Signalayer.cs.push({method:t,args:e})}}(a)}window.Signalayer.API=i;var
n=t.createElement(e),s=t.getElementsByTagName(e)[0];
n.type="text/javascript",
n.async=o.async,s.parentNode.insertBefore(n,s),n.src=o.url}(document,"script");
</script>
<!--- Tooltip player -->
<!--- Signalayer player -->
</head>
<body>
<div id="spinner" class="component" data-path-start="M280,466c0,0.13-0.001,0.26-0.003,0.39c-0.002,0.134-0.004,0.266-0.007,0.396
<div id="spinner" class="component" style="z-index:999999;" data-path-start="M280,466c0,0.13-0.001,0.26-0.003,0.39c-0.002,0.134-0.004,0.266-0.007,0.396
C279.572,482.992,266.307,496,250,496h-2.125H51.625H50c-16.316,0-29.592-13.029-29.99-29.249c-0.003-0.13-0.006-0.261-0.007-0.393
C20.001,466.239,20,466.119,20,466l0,0c0-0.141,0.001-0.281,0.003-0.422C20.228,449.206,33.573,436,50,436h1.625h196.25H250
c16.438,0,29.787,13.222,29.997,29.608C279.999,465.738,280,465.869,280,466L280,466z" data-path-listen="M181,466c0,0.13-0.001,0.26-0.003,0.39c-0.002,0.134-0.004,0.266-0.007,0.396
@ -65,5 +49,18 @@ C120.001,466.239,120,466.119,120,466l0,0c0-0.141,0.001-0.281,0.003-0.422C120.228
c16.438,0,29.787,13.222,29.997,29.608C180.999,465.738,181,465.869,181,466L181,466z" data-path-player="M290,40c0,0.13-0.001,380.26-0.003,380.39c-0.002,0.134,0.006,24.479,0.003,24.609 c0,3.095-2.562,5.001-5,5.001h-27.125H41.625H15c-1.875,0-5-1.25-5-5.001c-0.003-0.13,0.004-24.509,0.003-24.641 C10.001,420.239,10,40.119,10,40l0,0c0-0.141-0.002-24.859,0-25c0,0,0-5,5-5h26.625h216.25H285c2.438,0,5,1.906,5,5 C290.002,15.13,290,39.869,290,40L290,40z">
<div class="button button--start uil-ring-css" style="transform:scale(1);"><div></div></div>
</div>
<div id="background" style="height: 100%; width: 100%; background-color: #0675A0; position: absolute; z-index:99999; top: 0;">
</div>
</body>
<!-- Fixes visibility issues with some apps that only update the badges while visible -->
<style>
.x-hidden-offsets {
visibility: visible!important;
position: absolute!important;
z-index: -10!important;
top: 0!important;
}
</style>
</html>

2
languages.js

@ -18,7 +18,7 @@ var deleteFolderRecursive = function(path) {
};
var crowdin = new Crowdin({
apiKey: '',
apiKey: '1e7c2453268af5e31f6ac8cf6044d48b',
endpointUrl: 'https://api.crowdin.net/api/project/rambox'
});

21
masterpassword.html

@ -9,14 +9,31 @@
<body>
<div style="background-image: url(resources/Icon.png);background-size:200px;width:200px;height:200px;position:relative;left:50%;margin-left:-100px;margin-top:100px;"></div>
<div style="color:#FFF;text-align:center;font-size:20px;font-family:Verdana;margin:30px 0;">Master Password</div>
<div style="text-align:center;margin:30px 0;"><input type="password" autofocus placeholder="Enter your password..." onkeyup="doValidate(event, this.value)" style="text-align:center;font-size:20px;font-family:Verdana;padding:10px;border: 0;" /><button onclick="onButtonClick()" style="height:44px;border:0;width:44px;position:relative;top:2px;font-size:30px;background-color:#053767;color:white;">&raquo;</button></div>
<div style="text-align:center;margin:30px 0;"><input type="password" autofocus placeholder="Enter your password..." onpaste="handlePaste(event)" onkeyup="doValidate(event, this.value)" style="text-align:center;font-size:20px;font-family:Verdana;padding:10px;border: 0;" /><button onclick="onButtonClick()" style="height:44px;border:0;width:44px;position:relative;top:2px;font-size:30px;background-color:#053767;color:white;">&raquo;</button></div>
<div id='wrong-pass' style="color:crimson;text-align:center;font-size:20px;font-family:Verdana;margin:30px 0;visibility:hidden;">The password is incorrect. Try again...</div>
<div style="text-align:center;margin-top:60px;"><a href="#" onclick="exit()" style="text-decoration:none;color:#4e9dbb;font-family:Arial;">Exit Rambox</a></div>
<script>
function handlePaste(e) {
var clipboardData, pastedData;
// Stop data actually being pasted into div
e.stopPropagation();
e.preventDefault();
// Get pasted data via clipboard API
clipboardData = e.clipboardData || window.clipboardData;
pastedData = clipboardData.getData('Text');
document.getElementsByTagName('input')[0].value += pastedData
// Do whatever with pasteddata
}
function doValidate(e, value) {
document.getElementById('wrong-pass').style.visibility = 'hidden'
if (e.keyCode == 13) {
const { ipcRenderer } = require('electron');
if ( !ipcRenderer.sendSync('validateMasterPassword', value) ) {
alert('The password is incorrect. Try again...');
document.getElementsByTagName("input")[0].value = "";
document.getElementById('wrong-pass').style.visibility = 'visible'
}
}
}

7605
package-lock.json generated

File diff suppressed because it is too large Load Diff

224
package.json

@ -1,48 +1,103 @@
{
"private": true,
"name": "Rambox",
"productName": "Rambox",
"version": "0.8.0",
"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 <support@rambox.app>",
"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 && cp app/package.json build/production/Rambox/ && npm --prefix ./build/production/Rambox/ install ./build/production/Rambox/",
"sencha:compile:build": "sencha app build && cp app/package.json build/production/Rambox/ && cp -R build/production/Rambox/* ../rambox-build",
"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 --version=1.3.4 --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:osx": "npm run pack:osx64 && npm run pack:osxarm64",
"pack:osx64": "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:osxarm64": "electron-packager \"./build/production/Rambox/\" \"Rambox\" --out=dist --platform=darwin --arch=arm64 --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 --version=1.3.4 --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 --version=1.3.4 --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: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 --version=1.3.4 --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 --version=1.3.4 --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: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": "build --macos",
"build:linux": "npm run build:linux32 && npm run build:linux64",
"build:linux32": "build --linux --ia32",
"build:linux64": "build --linux --x64",
"build:win32": "build --win --ia32",
"build:win64": "build --win --x64",
"setup:osx": "npm run sencha:clean && npm run sencha:compile && npm run clean:osx && npm run pack:osx && npm run build:osx",
"build:osx": "electron-builder --macos --universal",
"build:osx64": "electron-builder --macos --x64",
"build:osxarm64": "electron-builder --macos --arm64",
"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 && npm run build:osx64 && npm run build:osxarm64",
"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"
"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.saenzramiro.rambox",
"appId": "com.grupovrs.ramboxce",
"afterSign": "resources/installer/notarize.js",
"asar": true,
"electronVersion": "13.6.3",
"electronDownload": {
"version": "13.6.3"
},
"mac": {
"category": "public.app-category.productivity",
"artifactName": "Rambox-${version}-mac-${arch}.${ext}",
"target": [
"default"
]
{
"target": "default",
"arch": [
"universal"
]
}
],
"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,
@ -57,57 +112,136 @@
}
]
},
"squirrelWindows": {
"iconUrl": "https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/Icon.ico"
},
"win": {
"publisherName": "Rambox LLC",
"artifactName": "Rambox-${version}-win-${arch}.${ext}",
"target": [
"squirrel",
"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": {
"category": "Office",
"icon": "resources/installer/icons",
"category": "Network",
"desktop": {
"Terminal": "false",
"Type": "Application",
"Categories": "GTK;GNOME;Utility;Office;Email;Chat;InstantMessaging;"
"Categories": "GTK;GNOME;Network;Email;Chat;InstantMessaging;"
},
"artifactName": "Rambox-${version}-linux-${arch}.${ext}",
"executableArgs": [
"--no-sandbox"
],
"target": [
"AppImage",
"deb",
"rpm",
"zip",
"tar.gz"
{
"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/",
"app": "build/production/Rambox/"
}
"output": "dist/"
},
"publish": [
{
"provider": "github",
"owner": "ramboxapp",
"repo": "community-edition",
"vPrefixedTagName": false
}
]
},
"devDependencies": {
"asar": "^0.12.4",
"asar": "0.12.4",
"chai": "3.5.0",
"crowdin": "1.0.0",
"csvjson": "4.3.3",
"electron": "^1.8.3",
"electron-builder": "^17.10.0",
"electron-builder-squirrel-windows": "15.0.0",
"electron-squirrel-startup": "^1.0.0",
"mocha": "3.2.0",
"spectron": "3.4.0"
"electron": "13.6.3",
"electron-builder": "22.14.13",
"electron-notarize": "1.0.0",
"electron-packager": "15.1.0",
"mocha": "5.2.0",
"spectron": "^15.0.0"
},
"dependencies": {
"@exponent/electron-cookies": "2.0.0",
"auth0-js": "^8.10.1",
"auth0-lock": "^10.22.0",
"auto-launch-patched": "5.0.2",
"electron-config": "0.2.1",
"electron-is-dev": "^0.3.0",
"mime": "^1.4.0",
"crypto": "1.0.1",
"electron-contextmenu-wrapper": "git+https://github.com/ramboxapp/electron-contextmenu-wrapper.git",
"electron-is-dev": "1.2.0",
"electron-log": "4.3.0",
"electron-store": "6.0.1",
"electron-updater": "4.5.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"
}
}

1
packages/local/rambox-default-theme/Readme.md

@ -1,2 +1 @@
# rambox-default-theme - Read Me

47
packages/local/rambox-default-theme/examples/Readme.md

@ -1,38 +1,45 @@
# rambox-default-theme/examples
This folder contains example applications demonstrating this package. Each of
these applications will be built as part of the package build:
This folder contains example applications demonstrating this package.
Each of these applications will be built as part of the package build:
cd /path/to/package
sencha package build
```bash
cd /path/to/package
sencha package build
```
As applications, they can also be built individually:
cd /path/to/package/examples/example-app
sencha app build
```bash
cd /path/to/package/examples/example-app
sencha app build
```
Or you can build all examples as a group:
cd /path/to/package
sencha ant examples
```bash
cd /path/to/package
sencha ant examples
```
The ideal location for the example builds to reside is the `"./build"` folder:
/path/to/package/
src/
resources/
```text
/path/to/package/
src/
resources/
...
examples/
example-app/
other-example/
...
build/
resources/
examples/
example-app/
other-example/
...
build/
resources/
examples/
example-app/
other-example/
```
This can be specified in the `".sencha/app/build.properties"` file for the
example applications:
This can be specified in the `".sencha/app/build.properties"` file for the example applications:
build.dir=${package.build.dir}/examples/${app.name}
`build.dir=${package.build.dir}/examples/${app.name}`

8
packages/local/rambox-default-theme/sass/Readme.md

@ -2,6 +2,8 @@
This folder contains SASS files of various kinds, organized in sub-folders:
rambox-default-theme/sass/etc
rambox-default-theme/sass/src
rambox-default-theme/sass/var
```text
rambox-default-theme/sass/etc
rambox-default-theme/sass/src
rambox-default-theme/sass/var
```

4
packages/local/rambox-default-theme/sass/etc/Readme.md

@ -1,4 +1,4 @@
# rambox-default-theme/sass/etc
This folder contains miscellaneous SASS files. Unlike `"rambox-default-theme/sass/etc"`, these files
need to be used explicitly.
This folder contains miscellaneous SASS files.
Unlike `"rambox-default-theme/sass/etc"`, these files need to be used explicitly.

12
packages/local/rambox-default-theme/sass/etc/all.scss

@ -272,3 +272,15 @@ body {
color: #FFF !important;
}
}
.x-tab-bar-default.dontdisturb {
background-color: #c3c3c3 !important;
.x-tab {
background-color: #c3c3c3;
}
}
.deprecation {
background-color: #E6A23C !important;
color: #FFF;
}

4
packages/local/rambox-default-theme/sass/src/Readme.md

@ -1,4 +1,4 @@
# rambox-default-theme/sass/src
This folder contains SASS sources that mimic the component-class hierarchy. These files
are gathered in to a build of the CSS based on classes that are used by the build.
This folder contains SASS sources that mimic the component-class hierarchy.
These files are gathered in to a build of the CSS based on classes that are used by the build.

3
packages/local/rambox-default-theme/src/Readme.md

@ -1,4 +1,3 @@
# rambox-default-theme/src
This folder contains source code that will automatically be added to the classpath when
the package is used.
This folder contains source code that will automatically be added to the classpath when the package is used.

4
resources/Readme.md

@ -1,4 +0,0 @@
# Rambox/resources
This folder contains resources (such as images) needed by the application. This file can
be removed if not needed.

BIN
resources/icons/airdroid.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
resources/icons/allo.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

BIN
resources/icons/amium.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

BIN
resources/icons/androidmessages.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

BIN
resources/icons/aol.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
resources/icons/awsworkmail.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

BIN
resources/icons/bearychat.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

BIN
resources/icons/bip.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

BIN
resources/icons/calendar.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

BIN
resources/icons/ciscospark.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

BIN
resources/icons/cliq.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
resources/icons/clocktweets.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

BIN
resources/icons/converse.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
resources/icons/crisp.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
resources/icons/dasher.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

BIN
resources/icons/devrant.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
resources/icons/dingtalk.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
resources/icons/discord.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
resources/icons/drift.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
resources/icons/duo.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
resources/icons/element.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
resources/icons/facebook.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
resources/icons/fastmail.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
resources/icons/fleep.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
resources/icons/flock.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
resources/icons/freenode.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
resources/icons/glip.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save