Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
283 changes: 221 additions & 62 deletions CTRLW.user.js

Large diffs are not rendered by default.

33 changes: 30 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,46 @@ Mush (Spanish) : http://mush.twinoid.es

Initially created by kill0u, now maintained by badconker.

Download
How to install
======

CTRL+W works with Firefox(GreaseMonkey) or Chrome(TamperMonkey).

- In Firefox, install the [GreaseMonkey](https://addons.mozilla.org/firefox/addon/greasemonkey/) Add-On
- In Chrome, install the [TamperMonkey](https://chrome.google.com/webstore/detail/tampermonkey/dhdgffkkebhmkfjojejmpbldmpobfkfo) extension

After you've added the script, you can install CTRL+W by opening one of the following files :

<ul>
<li><strong><a href="https://github.com/badconker/ctrl-w/raw/release/CTRLW.user.js">Last stable release (with absolute urls)</a></strong></li>
<li><a href="https://github.com/badconker/ctrl-w/raw/beta/CTRLW.user.js">Last beta version </a></li>
<li><a href="https://github.com/badconker/ctrl-w/raw/master/CTRLW.user.js">Last stable release (with relative urls)</a></li>
<li><a href="https://github.com/badconker/ctrl-w/raw/dev/CTRLW.user.js">Developpement branch (Pull your requests here pls)</a></li>
<li><a href="https://github.com/badconker/ctrl-w/raw/dev/CTRLW.user.js">Development branch (Pull your requests here please)</a></li>
</ul>

Enjoy!


Translators
======

I you want to help me to translate the script in English and Spanish, you have only to edit the .po file in translations directory with .po editor (like poedit : http://www.poedit.net/)
Thank you. :)
Thank you. :)



Developers
======

First make sure you have gulp installed - you can install it by running the following commands from the root directory ( provided you have `npm` installed )
```
npm install
npm install gulp-cli -g
```

After making your changes in the `src` folder, build the latest CTRLW.user.js with :
```
gulp
```

Finally submit your PR requests to the `dev` branch.
15 changes: 15 additions & 0 deletions ctrl-w.pot
Original file line number Diff line number Diff line change
Expand Up @@ -1080,3 +1080,18 @@ msgstr ""

msgid "Canal privé"
msgstr ""

msgid "You have %1 unread message"
msgstr ""

msgid "You have %1 unread messages"
msgstr ""

msgid "Cycle change about to happen"
msgstr ""

msgid "Cycle change just happened"
msgstr ""

msgid "Show browser notifications when tab is inactive."
msgstr ""
1 change: 1 addition & 0 deletions src/globalVariable.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ Main.k.domain = document.domain;
Main.k.mushurl = 'http://' + document.domain;
Main.k.debug = true;
Main.k.errorList = [];
Main.k.windowFocus = true;
if(Main.k.debug){
var console = unsafeWindow.console;
}else{
Expand Down
52 changes: 52 additions & 0 deletions src/main/BrowserNotice.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
Main.k.browserNotice = function(msg){

// Let's check if the browser supports notifications
if (!("Notification" in window)) {
Main.k.quickNoticeError("This browser does not support desktop notifications");
}

// Let's check if the user is okay to get some notification
else if (Notification.permission === "granted") {
// If it's okay let's create a notification
// If window currently in focus, don't notify
if ( Main.k.windowFocus ) return;
Main.k.browserNotify(msg);
}

// Otherwise, we need to ask the user for permission
// Note, Chrome does not implement the permission static property
// So we have to check for NOT 'denied' instead of 'default'
else if (Notification.permission !== 'denied') {
Notification.requestPermission(function (permission) {

// Whatever the user answers, we make sure we store the information
if(!('permission' in Notification)) {
Notification.permission = permission;
}

// If the user is okay, let's create a notification
if (permission === "granted") {
// If window currently in focus, don't notify
if ( Main.k.windowFocus ) return;
Main.k.browserNotify(msg);
}
});
}

// At last, if the user already denied any notification, and you
// want to be respectful there is no need to bother him any more.
};

Main.k.browserNotify = function(msg) {
var options = {
body: msg,
icon: "/img/icons/ui/mush.png"
}

var notification = new Notification("Mush", options);
notification.onclick = function() {
window.focus();
this.close();
}

}
10 changes: 10 additions & 0 deletions src/main/Refresh.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Main.k.refreshAll = function() {
// TODO: loading screen -- Optimize

Main.refreshChat();
Main.acListMaintainer.refresh(true);
Main.syncInvOffset(null,true);
Main.doChatPacks();
Main.topChat();
Main.onChanDone(ChatType.Local[1],true)
}
45 changes: 45 additions & 0 deletions src/main/StatusCheck.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
Main.k.statusCheck = function(){

if (!!Main.k.statusTimeout) clearTimeout(Main.k.statusTimeout);
if (!Main.k.Options.browserNot) return;

Main.k.refreshAll();

var _now = new Date();
var _elapsed = _now.getTime() - Main.tData.clientNow.getTime();
var _timeToGo = (Main.tData.timeToCycle - _elapsed) / 1000.0 | 0;

var _diffHI = parseInt(_timeToGo / 3600.0 | 0);
var _diffMI = parseInt(Math.abs(_timeToGo / 60.0 % 60.0));
var _diffSI = parseInt(Math.abs(_timeToGo % 60));

var _unreads = 0;

$('.cdNbNotRead').each(function(i, notReadEl ) {
_unreads += parseInt( $( notReadEl ).text() );
});

if(_unreads > 0) {
var _unreadMSG = Main.k.text.strargs(Main.k.text.ngettext("You have %1 unread message","You have %1 unread messages",_unreads),[_unreads]);
Main.k.browserNotice(_unreadMSG);
}

if(_diffHI == 0 && _diffMI < 3) {
Main.k.browserNotice(Main.k.text.gettext('Cycle change about to happen'));
}

if(_diffHI == 2 && _diffMI > 55) {
Main.k.browserNotice(Main.k.text.gettext('Cycle change just happened'));
}

// TODO : Make this configurable?
// TODO : Increase timer if long time in inactive tab

// Check every minute
var _timeout = 60000;
// If in hidden tab, check every 5 minutes
if(!Main.k.windowFocus) _timeout = 300000;

Main.k.statusTimeout = setTimeout(Main.k.statusCheck, _timeout);

}
11 changes: 11 additions & 0 deletions src/main/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ Main.k.init = function(){
Main.k.Game.init();
Main.k.initData();
Main.k.displayMainMenu();

//Check if tab is focused
$( window ).focus(function() {
Main.k.windowFocus = true;
}).blur(function() {
Main.k.windowFocus = false;
});

//Integration with others scripts
$( window ).load(function() {

Expand All @@ -14,6 +22,9 @@ Main.k.init = function(){
$(this).removeAttr('data-async_src');
});

//Start notification check and reloads
Main.k.statusCheck();

});
};
Main.k.getFullName = function(dev_surname) {
Expand Down
59 changes: 51 additions & 8 deletions src/main/options/init.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,55 @@
Main.k.Options.init = function() {
Main.k.Options.options = [
// Option Name, Option Object, Need refresh, After(), Desc
["cbubbles", Main.k.Options.cbubbles, false, Main.k.customBubbles, Main.k.text.gettext("Activer la mise en forme personnalisée des messages (bordure + couleur nom + image de fond).")],
["cbubblesNB", Main.k.Options.cbubblesNB, false, Main.k.customBubbles, Main.k.text.gettext("Simplifier la mise en forme personnalisée des messages (suppression de l'image de fond).")],
["dlogo", Main.k.Options.dlogo, true, null, Main.k.text.gettext("Afficher le logo Mush au dessus des onglets.")],
["splitpjt", Main.k.Options.splitpjt, false, Main.k.updateBottom, Main.k.text.gettext("Séparer les projets / recherches / pilgred sous la zone de jeu.")]
//["altpa", Main.k.Options.altpa, true, null, "Utiliser des images alternatives pour les pa / pm."]
];

Main.k.Options.options = {};

/**

Option format :

Main.k.Options.options.OPTIONNAME = {
option: Main.k.Options.OPTIONNAME, // Option value to change
text: Main.k.text.gettext("description"), // Description text
after: callback, // (Optional) After option changed, call this function
refresh: true, // (Optional) Page refresh needed after option change?
};

*/

Main.k.Options.options.cbubbles = {
option: Main.k.Options.cbubbles,
after: Main.k.customBubbles,
text: Main.k.text.gettext("Activer la mise en forme personnalisée des messages (bordure + couleur nom + image de fond)."),
};

Main.k.Options.options.cbubblesNB = {
option: Main.k.Options.cbubblesNB,
after: Main.k.customBubbles,
text: Main.k.text.gettext("Simplifier la mise en forme personnalisée des messages (suppression de l'image de fond)."),
};

Main.k.Options.options.dlogo = {
option: Main.k.Options.dlogo,
refresh: true,
text: Main.k.text.gettext("Afficher le logo Mush au dessus des onglets."),
};

Main.k.Options.options.splitpjt = {
option: Main.k.Options.splitpjt,
after: Main.k.updateBottom,
text: Main.k.text.gettext("Séparer les projets / recherches / pilgred sous la zone de jeu."),
};

// Main.k.Options.options.altpa = {
// option: Main.k.Options.altpa,
// refresh: true,
// text: "Utiliser des images alternatives pour les pa / pm."
// };

Main.k.Options.options.browserNot = {
option: Main.k.Options.browserNot,
after: Main.k.statusCheck,
text: Main.k.text.gettext("Show browser notifications when tab is inactive.")
};

var cook = js.Cookie.get("ctrlwoptions");
if (!cook) return;
Expand Down
3 changes: 2 additions & 1 deletion src/main/options/initData.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ Main.k.Options.dlogo = false;
Main.k.Options.splitpjt = true;
Main.k.Options.altpa = false;
Main.k.Options.mushNoConf = false;
Main.k.Options.options = [];
Main.k.Options.browserNot = true;
Main.k.Options.options = {};
17 changes: 8 additions & 9 deletions src/main/options/open.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ Main.k.Options.open = function() {
$("<p>").addClass("warning").text(Main.k.text.gettext("Plus d'options disponibles prochainement.")).appendTo(td);


for (var i=0; i<Main.k.Options.options.length; i++) {
var opt = Main.k.Options.options[i];
var html = opt[4];
if (opt[2]) html += " "+Main.k.text.gettext("Nécessite un rechargement de la page.");
for (var optname in Main.k.Options.options) {
var opt = Main.k.Options.options[optname];
var html = opt.text;
if (!!opt.refresh) html += " "+Main.k.text.gettext("Nécessite un rechargement de la page.");

var p = $("<p>").css({
color: "#EEE",
Expand All @@ -30,19 +30,18 @@ Main.k.Options.open = function() {
margin: "10px 20px",
clear: "both"
})
.html('<label style="margin-left: 30px;display:block" for="ctrlw_'+opt[0]+'">' + html + '</label>')
.html('<label style="margin-left: 30px;display:block" for="ctrlw_'+optname+'">' + html + '</label>')
.appendTo(td);

var chk = $("<input>").css({
"float": "left"
})
.attr("type", "checkbox")
.attr("optname", opt[0])
.attr("id", 'ctrlw_'+opt[0])
.attr("opti", i)
.attr("optname", optname)
.attr("id", 'ctrlw_'+optname)
.on("change", Main.k.Options.update)
.prependTo(p);
if (opt[1]) chk.attr("checked", "checked");
if (opt.option) chk.attr("checked", "checked");
}

Main.k.MakeButton("<img src='/img/icons/ui/reported.png' style='vertical-align: -20%' /> "+ Main.k.text.gettext("Vider le cache du script"), null, null, Main.k.text.gettext("Vider le cache du script"),
Expand Down
4 changes: 2 additions & 2 deletions src/main/options/update.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ Main.k.Options.update = function(e) {
var tgt = $(e.target);
var key = $(tgt).attr("optname");
var val = $(tgt).is(":checked") ? "y" : "n";
var i = $(tgt).attr("opti");
var optname = $(tgt).attr("optname");

Main.k.Options.updateOpt(key,val);
Main.k.Options.updateCookie();
if (Main.k.Options.options[i][3]) Main.k.Options.options[i][3]();
if (!!Main.k.Options.options[optname].after) Main.k.Options.options[optname].after();
};
10 changes: 6 additions & 4 deletions src/main/options/updateCookie.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
Main.k.Options.updateCookie = function() {
var cook = "";
for (var i=0; i<Main.k.Options.options.length; i++) {
if (i>0) cook += "|";
cook += Main.k.Options.options[i][0] + ":";
cook += Main.k.Options.options[i][1] ? "y" : "n";
for (var optname in Main.k.Options.options) {
if (cook != "") cook += "|";

cook += optname + ":";
cook += Main.k.Options.options[optname].option ? "y" : "n";

}

js.Cookie.set("ctrlwoptions",cook,420000000);
Expand Down
14 changes: 9 additions & 5 deletions src/main/options/updateOpt.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,29 @@ Main.k.Options.updateOpt = function(key, val) {
case "custombubbles":
case "cbubbles":
Main.k.Options.cbubbles = (val == "y");
Main.k.Options.options[0][1] = (val == "y");
Main.k.Options.options.cbubbles.option = (val == "y");
break;
case "custombubbles_nobackground":
case "cbubblesNB":
Main.k.Options.cbubblesNB = (val == "y");
Main.k.Options.options[1][1] = (val == "y");
Main.k.Options.options.cbubblesNB.option = (val == "y");
break;
case "displaylogo":
case "dlogo":
Main.k.Options.dlogo = (val == "y");
Main.k.Options.options[2][1] = (val == "y");
Main.k.Options.options.dlogo.option = (val == "y");
break;
case "splitpjt":
Main.k.Options.splitpjt = (val == "y");
Main.k.Options.options[3][1] = (val == "y");
Main.k.Options.options.splitpjt.option = (val == "y");
break;
//case "altpa":
// Main.k.Options.altpa = (val == "y");
// Main.k.Options.options[4][1] = (val == "y");
// Main.k.Options.options.altpa.option = (val == "y");
// break;
case "browserNot":
Main.k.Options.browserNot = (val == "y");
Main.k.Options.options.browserNot.option = (val == "y");
break;
}
};
Loading