Settings module

This commit is contained in:
Lorenz Hübschle-Schneider 2014-12-22 22:17:01 +01:00 committed by Tor Hveem
parent 48582cff3f
commit be6e356363
7 changed files with 148 additions and 127 deletions

View file

@ -25,6 +25,7 @@
<script type="text/javascript" src="js/weechat.js"></script> <script type="text/javascript" src="js/weechat.js"></script>
<script type="text/javascript" src="js/irc-utils.js"></script> <script type="text/javascript" src="js/irc-utils.js"></script>
<script type="text/javascript" src="js/glowingbear.js"></script> <script type="text/javascript" src="js/glowingbear.js"></script>
<script type="text/javascript" src="js/settings.js"></script>
<script type="text/javascript" src="js/utils.js"></script> <script type="text/javascript" src="js/utils.js"></script>
<script type="text/javascript" src="js/notifications.js"></script> <script type="text/javascript" src="js/notifications.js"></script>
<script type="text/javascript" src="js/filters.js"></script> <script type="text/javascript" src="js/filters.js"></script>
@ -38,7 +39,7 @@
<script type="text/javascript" src="3rdparty/favico-0.3.5.min.js"></script> <script type="text/javascript" src="3rdparty/favico-0.3.5.min.js"></script>
</head> </head>
<body ng-controller="WeechatCtrl" ng-keydown="handleKeyPress($event)" ng-keyup="handleKeyRelease($event)" ng-keypress="handleKeyPress($event)" ng-class="{'no-overflow': connected}" lang="en-US"> <body ng-controller="WeechatCtrl" ng-keydown="handleKeyPress($event)" ng-keyup="handleKeyRelease($event)" ng-keypress="handleKeyPress($event)" ng-class="{'no-overflow': connected}" lang="en-US">
<link ng-href="css/themes/{{theme}}.css" rel="stylesheet" media="screen" /> <link ng-href="css/themes/{{settings.theme}}.css" rel="stylesheet" media="screen" />
<div ng-hide="connected" class="container"> <div ng-hide="connected" class="container">
<h2> <h2>
<img alt="logo" src="assets/img/glowing-bear.svg"> <img alt="logo" src="assets/img/glowing-bear.svg">
@ -71,10 +72,10 @@
<div class="input-group"> <div class="input-group">
<div class="row no-gutter"> <div class="row no-gutter">
<div class="col-sm-9"> <div class="col-sm-9">
<input type="text" class="form-control favorite-font" id="host" ng-model="host" placeholder="Address" autocapitalize="off"> <input type="text" class="form-control favorite-font" id="host" ng-model="settings.host" placeholder="Address" autocapitalize="off">
</div> </div>
<div class="col-sm-3"> <div class="col-sm-3">
<input type="text" class="form-control favorite-font" id="port" ng-model="port" placeholder="Port"> <input type="text" class="form-control favorite-font" id="port" ng-model="settings.port" placeholder="Port">
</div> </div>
</div> </div>
</div> </div>
@ -86,19 +87,19 @@
<div class="checkbox"> <div class="checkbox">
<label class="control-label" for="savepassword"> <label class="control-label" for="savepassword">
<input type="checkbox" id="savepassword" ng-model="savepassword"> <input type="checkbox" id="savepassword" ng-model="settings.savepassword">
Save password in your browser Save password in your browser
</label> </label>
</div> </div>
<div class="checkbox" ng-show="savepassword"> <div class="checkbox" ng-show="settings.savepassword">
<label class="control-label" for="autoconnect"> <label class="control-label" for="autoconnect">
<input type="checkbox" id="autoconnect" ng-model="autoconnect"> <input type="checkbox" id="autoconnect" ng-model="settings.autoconnect">
Automatically connect Automatically connect
</label> </label>
</div> </div>
<div class="checkbox"> <div class="checkbox">
<label class="control-label" for="ssl"> <label class="control-label" for="ssl">
<input type="checkbox" id="ssl" ng-model="ssl"> <input type="checkbox" id="ssl" ng-model="settings.ssl">
Encryption. Read instructions for help Encryption. Read instructions for help
</label> </label>
</div> </div>
@ -122,7 +123,7 @@
<div>To start using glowing bear, please enable the relay plugin in your WeeChat client: <div>To start using glowing bear, please enable the relay plugin in your WeeChat client:
<pre> <pre>
/set relay.network.password yourpassword /set relay.network.password yourpassword
/relay add weechat {{ port || 9001 }} /relay add weechat {{ settings.port || 9001 }}
</pre> </pre>
<span class="label label-danger">WeeChat version 0.4.2 or higher is required.</span><br> <span class="label label-danger">WeeChat version 0.4.2 or higher is required.</span><br>
The communication goes directly between your browser and your WeeChat relay in plain text. Check the instructions below for help on setting up encrypted communication. The communication goes directly between your browser and your WeeChat relay in plain text. Check the instructions below for help on setting up encrypted communication.
@ -157,18 +158,18 @@
<div id="collapseThree" class="panel-collapse collapse in"> <div id="collapseThree" class="panel-collapse collapse in">
<div class="panel-body"> <div class="panel-body">
<p>If you check the encryption box, the communication between browser and WeeChat will be encrypted with TLS.</p> <p>If you check the encryption box, the communication between browser and WeeChat will be encrypted with TLS.</p>
<p><strong>Note</strong>: If you are using a self-signed certificate, you have to visit <a href="https://{{ host }}:{{ port }}/">https://{{ host || 'weechathost' }}:{{ port || 'relayport' }}/</a> in your browser first to add a security exception. You can close that tab once you confirmed the certificate, no content will appear. The necessity of this process is a bug in <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=594502">Firefox</a> and other browsers.</p> <p><strong>Note</strong>: If you are using a self-signed certificate, you have to visit <a href="https://{{ settings.host }}:{{ settings.port }}/">https://{{ settings.host || 'weechathost' }}:{{ settings.port || 'relayport' }}/</a> in your browser first to add a security exception. You can close that tab once you confirmed the certificate, no content will appear. The necessity of this process is a bug in <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=594502">Firefox</a> and other browsers.</p>
<p><strong>Setup</strong>: If you want to use an encrypted session you first have to set up the relay to use TLS. You basically have two options: a self-signed certificate is easier to set up, but requires manual security exceptions. Using a certificate that is trusted by your browser requires more setup, but offers greater convenience later on and does not require security exceptions. You can find a guide to set up WeeChat with a free trusted certificate from StartSSL <a href="https://4z2.de/2014/07/06/weechat-trusted-relay">here</a>. Should you wish to use a self-signed certificate instead, execute the following commands in a shell on the same host and as the user running WeeChat:</p> <p><strong>Setup</strong>: If you want to use an encrypted session you first have to set up the relay to use TLS. You basically have two options: a self-signed certificate is easier to set up, but requires manual security exceptions. Using a certificate that is trusted by your browser requires more setup, but offers greater convenience later on and does not require security exceptions. You can find a guide to set up WeeChat with a free trusted certificate from StartSSL <a href="https://4z2.de/2014/07/06/weechat-trusted-relay">here</a>. Should you wish to use a self-signed certificate instead, execute the following commands in a shell on the same host and as the user running WeeChat:</p>
<pre> <pre>
$ mkdir -p ~/.weechat/ssl $ mkdir -p ~/.weechat/ssl
$ cd ~/.weechat/ssl $ cd ~/.weechat/ssl
$ openssl req -nodes -newkey rsa:4096 -keyout relay.pem -x509 -days 365 -out relay.pem -subj "/CN={{host || 'your weechat host'}}/" $ openssl req -nodes -newkey rsa:4096 -keyout relay.pem -x509 -days 365 -out relay.pem -subj "/CN={{settings.host || 'your weechat host'}}/"
</pre> </pre>
<p>If WeeChat is already running, you can reload the certificate and private key and set up an encrypted relay on port {{ port || 9001 }} with these WeeChat commands:</p> <p>If WeeChat is already running, you can reload the certificate and private key and set up an encrypted relay on port {{ settings.port || 9001 }} with these WeeChat commands:</p>
<pre> <pre>
/set relay.network.password yourpassword /set relay.network.password yourpassword
/relay sslcertkey /relay sslcertkey
/relay add ssl.weechat {{ port || 9001 }} /relay add ssl.weechat {{ settings.port || 9001 }}
</pre> </pre>
</div> </div>
</div> </div>
@ -213,7 +214,7 @@ $ openssl req -nodes -newkey rsa:4096 -keyout relay.pem -x509 -days 365 -out rel
<div id="topbar"> <div id="topbar">
<div class="brand"> <div class="brand">
<a href="#" ng-click="toggleSidebar()"> <a href="#" ng-click="toggleSidebar()">
<img alt="brand" src="assets/img/favicon.png" title="Connected to {{ host }}:{{ port}}"> <img alt="brand" src="assets/img/favicon.png" title="Connected to {{ settings.host }}:{{ settings.port}}">
</a> </a>
<button ng-if="debugMode" ng-click="countWatchers()">Count<br />Watchers</button> <button ng-if="debugMode" ng-click="countWatchers()">Count<br />Watchers</button>
</div> </div>
@ -255,7 +256,7 @@ $ openssl req -nodes -newkey rsa:4096 -keyout relay.pem -x509 -days 365 -out rel
</li> </li>
</ul> </ul>
</div> </div>
<table ng-class="{'notimestamp':!showtimestamp,'notimestampseconds':!showtimestampSeconds}"> <table ng-class="{'notimestamp':!settings.showtimestamp,'notimestampseconds':!settings.showtimestampSeconds}">
<tbody> <tbody>
<tr class="bufferline"> <tr class="bufferline">
<td ng-hide="activeBuffer().allLinesFetched" colspan="3"> <td ng-hide="activeBuffer().allLinesFetched" colspan="3">
@ -306,12 +307,12 @@ $ openssl req -nodes -newkey rsa:4096 -keyout relay.pem -x509 -days 365 -out rel
<div class="form-group"> <div class="form-group">
<label for="font" class="col-sm-3 control-label make-thinner">Preferred font</label> <label for="font" class="col-sm-3 control-label make-thinner">Preferred font</label>
<div class="col-sm-4"> <div class="col-sm-4">
<input type="text" ng-model="fontfamily" class="form-control" id="font"> <input type="text" ng-model="settings.fontfamily" class="form-control" id="font">
</div> </div>
<label for="size" class="col-sm-1 control-label">Size</label> <label for="size" class="col-sm-1 control-label">Size</label>
<div class="col-sm-2"> <div class="col-sm-2">
<input type="text" ng-model="fontsize" class="form-control" id="size"> <input type="text" ng-model="settings.fontsize" class="form-control" id="size">
</div> </div>
</div> </div>
</form> </form>
@ -321,7 +322,7 @@ $ openssl req -nodes -newkey rsa:4096 -keyout relay.pem -x509 -days 365 -out rel
<div class="form-group"> <div class="form-group">
<label for="theme" class="col-sm-3 control-label make-thinner">Theme</label> <label for="theme" class="col-sm-3 control-label make-thinner">Theme</label>
<div class="col-sm-7"> <div class="col-sm-7">
<select id="theme" class="form-control" ng-model="theme" ng-options="theme for theme in themes"></select> <select id="theme" class="form-control" ng-model="settings.theme" ng-options="theme for theme in themes"></select>
</div> </div>
</div> </div>
</form> </form>
@ -331,7 +332,7 @@ $ openssl req -nodes -newkey rsa:4096 -keyout relay.pem -x509 -days 365 -out rel
<form class="form-inline" role="form"> <form class="form-inline" role="form">
<div class="checkbox"> <div class="checkbox">
<label> <label>
<input type="checkbox" ng-model="onlyUnread"> <input type="checkbox" ng-model="settings.onlyUnread">
Only show buffers with unread messages Only show buffers with unread messages
</label> </label>
</div> </div>
@ -341,17 +342,17 @@ $ openssl req -nodes -newkey rsa:4096 -keyout relay.pem -x509 -days 365 -out rel
<form class="form-inline" role="form"> <form class="form-inline" role="form">
<div class="checkbox"> <div class="checkbox">
<label> <label>
<input type="checkbox" ng-model="showtimestamp"> <input type="checkbox" ng-model="settings.showtimestamp">
Show timestamps Show timestamps
</label> </label>
</div> </div>
</form> </form>
<ul ng-show="showtimestamp"> <ul ng-show="settings.showtimestamp">
<li> <li>
<form class="form-inline" role="form"> <form class="form-inline" role="form">
<div class="checkbox"> <div class="checkbox">
<label> <label>
<input type="checkbox" ng-model="showtimestampSeconds"> <input type="checkbox" ng-model="settings.showtimestampSeconds">
Show seconds Show seconds
</label> </label>
</div> </div>
@ -363,7 +364,7 @@ $ openssl req -nodes -newkey rsa:4096 -keyout relay.pem -x509 -days 365 -out rel
<form class="form-inline" role="form"> <form class="form-inline" role="form">
<div class="checkbox"> <div class="checkbox">
<label> <label>
<input type="checkbox" ng-model="noembed"> <input type="checkbox" ng-model="settings.noembed">
Hide embedded content by default<span class="text-muted settings-help">NSFW content will be hidden regardless of this choice</span> Hide embedded content by default<span class="text-muted settings-help">NSFW content will be hidden regardless of this choice</span>
</label> </label>
</div> </div>
@ -373,7 +374,7 @@ $ openssl req -nodes -newkey rsa:4096 -keyout relay.pem -x509 -days 365 -out rel
<form class="form-inline" role="form"> <form class="form-inline" role="form">
<div class="checkbox"> <div class="checkbox">
<label> <label>
<input type="checkbox" ng-model="hotlistsync"> <input type="checkbox" ng-model="settings.hotlistsync">
Mark messages as read in WeeChat Mark messages as read in WeeChat
</label> </label>
</div> </div>
@ -383,7 +384,7 @@ $ openssl req -nodes -newkey rsa:4096 -keyout relay.pem -x509 -days 365 -out rel
<form class="form-inline" role="form"> <form class="form-inline" role="form">
<div class="checkbox"> <div class="checkbox">
<label> <label>
<input type="checkbox" ng-model="nonicklist"> <input type="checkbox" ng-model="settings.nonicklist">
Hide nicklist Hide nicklist
</label> </label>
</div> </div>
@ -393,7 +394,7 @@ $ openssl req -nodes -newkey rsa:4096 -keyout relay.pem -x509 -days 365 -out rel
<form class="form-inline" role="form"> <form class="form-inline" role="form">
<div class="checkbox"> <div class="checkbox">
<label> <label>
<input type="checkbox" ng-model="orderbyserver"> <input type="checkbox" ng-model="settings.orderbyserver">
Hierarchical buffer view (order by server) Hierarchical buffer view (order by server)
</label> </label>
</div> </div>
@ -403,7 +404,7 @@ $ openssl req -nodes -newkey rsa:4096 -keyout relay.pem -x509 -days 365 -out rel
<form class="form-inline" role="form"> <form class="form-inline" role="form">
<div class="checkbox"> <div class="checkbox">
<label> <label>
<input type="checkbox" ng-model="readlineBindings"> <input type="checkbox" ng-model="settings.readlineBindings">
Enable common readline keybindings in input bar Enable common readline keybindings in input bar
</label> </label>
</div> </div>
@ -413,7 +414,7 @@ $ openssl req -nodes -newkey rsa:4096 -keyout relay.pem -x509 -days 365 -out rel
<form class="form-inline" role="form"> <form class="form-inline" role="form">
<div class="checkbox"> <div class="checkbox">
<label> <label>
<input type="checkbox" ng-model="useFavico"> <input type="checkbox" ng-model="settings.useFavico">
Display unread count in favicon Display unread count in favicon
</label> </label>
</div> </div>
@ -423,7 +424,7 @@ $ openssl req -nodes -newkey rsa:4096 -keyout relay.pem -x509 -days 365 -out rel
<form class="form-inline" role="form"> <form class="form-inline" role="form">
<div class="checkbox"> <div class="checkbox">
<label> <label>
<input type="checkbox" ng-model="soundnotification"> <input type="checkbox" ng-model="settings.soundnotification">
Play sound on notification Play sound on notification
</label> </label>
</div> </div>

View file

@ -12,10 +12,12 @@ weechat.config(['$compileProvider', function ($compileProvider) {
} }
}]); }]);
weechat.controller('WeechatCtrl', ['$rootScope', '$scope', '$store', '$timeout', '$log', 'models', 'connection', 'notifications', 'utils', function ($rootScope, $scope, $store, $timeout, $log, models, connection, notifications, utils) { weechat.controller('WeechatCtrl', ['$rootScope', '$scope', '$store', '$timeout', '$log', 'models', 'connection', 'notifications', 'utils', 'settings',
function ($rootScope, $scope, $store, $timeout, $log, models, connection, notifications, utils, settings) {
$scope.command = ''; $scope.command = '';
$scope.themes = ['dark', 'light']; $scope.themes = ['dark', 'light'];
$scope.settings = settings;
// From: http://stackoverflow.com/a/18539624 by StackOverflow user "plantian" // From: http://stackoverflow.com/a/18539624 by StackOverflow user "plantian"
$rootScope.countWatchers = function () { $rootScope.countWatchers = function () {
@ -193,7 +195,7 @@ weechat.controller('WeechatCtrl', ['$rootScope', '$scope', '$store', '$timeout',
// we will send a /buffer bufferName command every time // we will send a /buffer bufferName command every time
// the user switches a buffer. This will ensure that notifications // the user switches a buffer. This will ensure that notifications
// are cleared in the buffer the user switches to // are cleared in the buffer the user switches to
if ($scope.hotlistsync && ab.fullName) { if (settings.hotlistsync && ab.fullName) {
connection.sendCoreCommand('/buffer ' + ab.fullName); connection.sendCoreCommand('/buffer ' + ab.fullName);
} }
@ -215,7 +217,7 @@ weechat.controller('WeechatCtrl', ['$rootScope', '$scope', '$store', '$timeout',
$rootScope.$on('notificationChanged', function() { $rootScope.$on('notificationChanged', function() {
notifications.updateTitle(); notifications.updateTitle();
if ($scope.useFavico && $rootScope.favico) { if (settings.useFavico && $rootScope.favico) {
notifications.updateFavico(); notifications.updateFavico();
} }
}); });
@ -246,72 +248,31 @@ weechat.controller('WeechatCtrl', ['$rootScope', '$scope', '$store', '$timeout',
$rootScope.iterCandidate = null; $rootScope.iterCandidate = null;
$store.bind($scope, "host", "localhost"); if (settings.savepassword) {
$store.bind($scope, "port", "9001"); $scope.$watch('password', function() {
$store.bind($scope, "proto", "weechat"); settings.password = $scope.password;
$store.bind($scope, "ssl", (window.location.protocol === "https:")); });
$store.bind($scope, "savepassword", false); settings.addCallback('password', function(password) {
if ($scope.savepassword) { $scope.password = password;
$store.bind($scope, "password", ""); });
$scope.password = settings.password;
} else {
settings.password = '';
} }
$store.bind($scope, "autoconnect", false);
// If we are on mobile change some defaults
// We use 968 px as the cutoff, which should match the value in glowingbear.css
var nonicklist = false;
var noembed = false;
var showtimestamp = true;
$rootScope.wasMobileUi = false; $rootScope.wasMobileUi = false;
if (utils.isMobileUi()) { if (utils.isMobileUi()) {
nonicklist = true;
noembed = true;
$rootScope.wasMobileUi = true; $rootScope.wasMobileUi = true;
} }
if (!settings.fontfamily) {
// Save setting for displaying only buffers with unread messages
$store.bind($scope, "onlyUnread", false);
// Save setting for syncing hotlist
$store.bind($scope, "hotlistsync", true);
// Save setting for displaying nicklist
$store.bind($scope, "nonicklist", nonicklist);
// Save setting for displaying embeds
$store.bind($scope, "noembed", noembed);
// Save setting for channel ordering
$store.bind($scope, "orderbyserver", true);
// Save setting for updating favicon
$store.bind($scope, "useFavico", true);
// Save setting for showtimestamp
$store.bind($scope, "showtimestamp", showtimestamp);
// Save setting for showing seconds on timestamps
$store.bind($scope, "showtimestampSeconds", false);
// Save setting for playing sound on notification
$store.bind($scope, "soundnotification", false);
// Save setting for font family
$store.bind($scope, "fontfamily");
// Save setting for theme
$store.bind($scope, "theme", 'dark');
// Save setting for font size
$store.bind($scope, "fontsize", "14px");
// Save setting for readline keybindings
$store.bind($scope, "readlineBindings", false);
// Save settings for non-native Emoji support
$store.bind($scope, "enableJSEmoji", false);
if (!$scope.fontfamily) {
if (utils.isMobileUi()) { if (utils.isMobileUi()) {
$scope.fontfamily = 'sans-serif'; settings.fontfamily = 'sans-serif';
} else { } else {
$scope.fontfamily = "Inconsolata, Consolas, Monaco, Ubuntu Mono, monospace"; settings.fontfamily = "Inconsolata, Consolas, Monaco, Ubuntu Mono, monospace";
} }
} }
// Save setting for displaying embeds in rootScope so it can be used from service
$rootScope.auto_display_embedded_content = $scope.noembed === false;
$scope.isSidebarVisible = function() { $scope.isSidebarVisible = function() {
return document.getElementById('content').getAttribute('sidebar-state') === 'visible'; return document.getElementById('content').getAttribute('sidebar-state') === 'visible';
}; };
@ -333,9 +294,8 @@ weechat.controller('WeechatCtrl', ['$rootScope', '$scope', '$store', '$timeout',
document.getElementById('content').setAttribute('sidebar-state', 'hidden'); document.getElementById('content').setAttribute('sidebar-state', 'hidden');
} }
}; };
// This also fires on page load settings.addCallback('autoconnect', function(autoconnect) {
$scope.$watch('autoconnect', function() { if (autoconnect && !$rootScope.connected && !$rootScope.sslError && !$rootScope.securityError && !$rootScope.errorMessage) {
if ($scope.autoconnect && !$rootScope.connected && !$rootScope.sslError && !$rootScope.securityError && !$rootScope.errorMessage) {
$scope.connect(); $scope.connect();
} }
}); });
@ -354,35 +314,31 @@ weechat.controller('WeechatCtrl', ['$rootScope', '$scope', '$store', '$timeout',
// Open and close panels while on mobile devices through swiping // Open and close panels while on mobile devices through swiping
$scope.openNick = function() { $scope.openNick = function() {
if (utils.isMobileUi()) { if (utils.isMobileUi()) {
if ($scope.nonicklist) { if (settings.nonicklist) {
$scope.nonicklist = false; settings.nonicklist = false;
} }
} }
}; };
$scope.closeNick = function() { $scope.closeNick = function() {
if (utils.isMobileUi()) { if (utils.isMobileUi()) {
if (!$scope.nonicklist) { if (!settings.nonicklist) {
$scope.nonicklist = true; settings.nonicklist = true;
} }
} }
}; };
// Watch model and update show setting when it changes
$scope.$watch('noembed', function() {
$rootScope.auto_display_embedded_content = $scope.noembed === false;
});
// Watch model and update channel sorting when it changes // Watch model and update channel sorting when it changes
$scope.$watch('orderbyserver', function() { settings.addCallback('orderbyserver', function(orderbyserver) {
$rootScope.predicate = $scope.orderbyserver ? 'serverSortKey' : 'number'; $rootScope.predicate = orderbyserver ? 'serverSortKey' : 'number';
}); });
$scope.$watch('useFavico', function() { settings.addCallback('useFavico', function(useFavico) {
// this check is necessary as this is called on page load, too // this check is necessary as this is called on page load, too
if (!$rootScope.connected) { if (!$rootScope.connected) {
return; return;
} }
if ($scope.useFavico) { if (useFavico) {
notifications.updateFavico(); notifications.updateFavico();
} else { } else {
$rootScope.favico.reset(); $rootScope.favico.reset();
@ -390,17 +346,12 @@ weechat.controller('WeechatCtrl', ['$rootScope', '$scope', '$store', '$timeout',
}); });
// Update font family when changed // Update font family when changed
$scope.$watch('fontfamily', function() { settings.addCallback('fontfamily', function(fontfamily) {
utils.changeClassStyle('favorite-font', 'fontFamily', $scope.fontfamily); utils.changeClassStyle('favorite-font', 'fontFamily', fontfamily);
}); });
// Update font size when changed // Update font size when changed
$scope.$watch('fontsize', function() { settings.addCallback('fontsize', function(fontsize) {
utils.changeClassStyle('favorite-font', 'fontSize', $scope.fontsize); utils.changeClassStyle('favorite-font', 'fontSize', fontsize);
});
// Crude scoping hack. The keypress listener does not live in the same scope as
// the checkbox, so we need to transfer this between scopes here.
$scope.$watch('readlineBindings', function() {
$rootScope.readlineBindings = $scope.readlineBindings;
}); });
$scope.setActiveBuffer = function(bufferId, key) { $scope.setActiveBuffer = function(bufferId, key) {
@ -526,7 +477,7 @@ weechat.controller('WeechatCtrl', ['$rootScope', '$scope', '$store', '$timeout',
$rootScope.errorMessage = false; $rootScope.errorMessage = false;
$rootScope.bufferBottom = true; $rootScope.bufferBottom = true;
$scope.connectbutton = 'Connecting ...'; $scope.connectbutton = 'Connecting ...';
connection.connect($scope.host, $scope.port, $scope.password, $scope.ssl); connection.connect(settings.host, settings.port, $scope.password, settings.ssl);
}; };
$scope.disconnect = function() { $scope.disconnect = function() {
$scope.connectbutton = 'Connect'; $scope.connectbutton = 'Connect';
@ -594,7 +545,7 @@ weechat.controller('WeechatCtrl', ['$rootScope', '$scope', '$store', '$timeout',
if ($scope.search && $scope.search !== "") { if ($scope.search && $scope.search !== "") {
return true; return true;
} }
if ($scope.onlyUnread) { if (settings.onlyUnread) {
// Always show current buffer in list // Always show current buffer in list
if (models.getActiveBuffer() === buffer) { if (models.getActiveBuffer() === buffer) {
return true; return true;
@ -609,7 +560,7 @@ weechat.controller('WeechatCtrl', ['$rootScope', '$scope', '$store', '$timeout',
}; };
// Watch model and update show setting when it changes // Watch model and update show setting when it changes
$scope.$watch('nonicklist', function() { settings.addCallback('nonicklist', function() {
$scope.showNicklist = $scope.updateShowNicklist(); $scope.showNicklist = $scope.updateShowNicklist();
// restore bottom view // restore bottom view
if ($rootScope.connected && $rootScope.bufferBottom) { if ($rootScope.connected && $rootScope.bufferBottom) {
@ -628,7 +579,7 @@ weechat.controller('WeechatCtrl', ['$rootScope', '$scope', '$store', '$timeout',
return false; return false;
} }
// Check if option no nicklist is set // Check if option no nicklist is set
if ($scope.nonicklist) { if (settings.nonicklist) {
return false; return false;
} }
// Check if nicklist is empty // Check if nicklist is empty
@ -662,7 +613,7 @@ weechat.controller('WeechatCtrl', ['$rootScope', '$scope', '$store', '$timeout',
}; };
// Helper function since the keypress handler is in a different scope // Helper function since the keypress handler is in a different scope
$rootScope.toggleNicklist = function() { $rootScope.toggleNicklist = function() {
$scope.nonicklist = !$scope.nonicklist; settings.nonicklist = !settings.nonicklist;
}; };

View file

@ -14,13 +14,14 @@ weechat.directive('inputBar', function() {
command: '=command' command: '=command'
}, },
controller: ['$rootScope', '$scope', '$element', '$log', 'connection', 'models', 'IrcUtils', function($rootScope, controller: ['$rootScope', '$scope', '$element', '$log', 'connection', 'models', 'IrcUtils', 'settings', function($rootScope,
$scope, $scope,
$element, //XXX do we need this? don't seem to be using it $element, //XXX do we need this? don't seem to be using it
$log, $log,
connection, //XXX we should eliminate this dependency and use signals instead connection, //XXX we should eliminate this dependency and use signals instead
models, models,
IrcUtils) { IrcUtils,
settings) {
/* /*
* Returns the input element * Returns the input element
@ -340,7 +341,7 @@ weechat.directive('inputBar', function() {
} }
// Some readline keybindings // Some readline keybindings
if ($rootScope.readlineBindings && $event.ctrlKey && !$event.altKey && !$event.shiftKey && document.activeElement === inputNode) { if (settings.readlineBindings && $event.ctrlKey && !$event.altKey && !$event.shiftKey && document.activeElement === inputNode) {
// get current caret position // get current caret position
caretPos = inputNode.selectionStart; caretPos = inputNode.selectionStart;
// Ctrl-a // Ctrl-a

View file

@ -81,6 +81,16 @@ ls.factory("$store", ["$parse", function($parse){
storage.removeItem(key); storage.removeItem(key);
return true; return true;
}, },
/**
* Enumerate all keys
*/
enumerateKeys: function() {
var keys = [];
for (var i = 0, len = storage.length; i < len; ++i) {
keys.push(storage.key(i));
}
return keys;
},
/** /**
* Bind - lets you directly bind a localStorage value to a $scope variable * Bind - lets you directly bind a localStorage value to a $scope variable
* @param $scope - the current scope you want the variable available in * @param $scope - the current scope you want the variable available in

View file

@ -1,9 +1,8 @@
var weechat = angular.module('weechat'); var weechat = angular.module('weechat');
weechat.factory('notifications', ['$rootScope', '$log', 'models', function($rootScope, $log, models) { weechat.factory('notifications', ['$rootScope', '$log', 'models', 'settings', function($rootScope, $log, models, settings) {
var notifications = [];
// Ask for permission to display desktop notifications // Ask for permission to display desktop notifications
var notifications = [];
var requestNotificationPermission = function() { var requestNotificationPermission = function() {
// Firefox // Firefox
if (window.Notification) { if (window.Notification) {
@ -135,7 +134,7 @@ weechat.factory('notifications', ['$rootScope', '$log', 'models', function($root
delete notifications[this.id]; delete notifications[this.id];
}; };
if ($rootScope.soundnotification) { if (settings.soundnotification) {
// TODO fill in a sound file // TODO fill in a sound file
var audioFile = "assets/audio/sonar"; var audioFile = "assets/audio/sonar";
var soundHTML = '<audio autoplay="autoplay"><source src="' + audioFile + '.ogg" type="audio/ogg" /><source src="' + audioFile + '.mp3" type="audio/mpeg" /></audio>'; var soundHTML = '<audio autoplay="autoplay"><source src="' + audioFile + '.ogg" type="audio/ogg" /><source src="' + audioFile + '.mp3" type="audio/mpeg" /></audio>';
@ -153,10 +152,10 @@ weechat.factory('notifications', ['$rootScope', '$log', 'models', function($root
}; };
return { return {
requestNotificationPermission: requestNotificationPermission, requestNotificationPermission: requestNotificationPermission,
updateTitle: updateTitle, updateTitle: updateTitle,
updateFavico: updateFavico, updateFavico: updateFavico,
createHighlight: createHighlight, createHighlight: createHighlight,
cancelAll: cancelAll, cancelAll: cancelAll,
}; };
}]); }]);

View file

@ -3,7 +3,7 @@
var weechat = angular.module('weechat'); var weechat = angular.module('weechat');
weechat.directive('plugin', ['$rootScope', function($rootScope) { weechat.directive('plugin', ['$rootScope', 'settings', function($rootScope, settings) {
/* /*
* Plugin directive * Plugin directive
* Shows additional plugin content * Shows additional plugin content
@ -20,7 +20,7 @@ weechat.directive('plugin', ['$rootScope', function($rootScope) {
$scope.displayedContent = ""; $scope.displayedContent = "";
// Auto-display embedded content only if it isn't NSFW // Auto-display embedded content only if it isn't NSFW
$scope.plugin.visible = $rootScope.auto_display_embedded_content && !$scope.plugin.nsfw; $scope.plugin.visible = !settings.noembed && !$scope.plugin.nsfw;
// user-accessible hash key that is a valid CSS class name // user-accessible hash key that is a valid CSS class name
$scope.plugin.className = "embed_" + $scope.plugin.$$hashKey.replace(':','_'); $scope.plugin.className = "embed_" + $scope.plugin.$$hashKey.replace(':','_');

59
js/settings.js Normal file
View file

@ -0,0 +1,59 @@
(function() {
'use strict';
var weechat = angular.module('weechat');
weechat.factory('settings', ['$store', '$rootScope', function($store, $rootScope) {
var that = this;
this.callbacks = {};
// Define a property for a setting, retrieving it on read
// and writing it to localStorage on write
var defineProperty = function(key) {
Object.defineProperty(that, key, {
enumerable: true,
key: key,
get: function() {
return $store.get(key);
},
set: function(newVal) {
$store.set(key, newVal);
// Call any callbacks
var callbacks = that.callbacks[key];
for (var i = 0; callbacks !== undefined && i < callbacks.length; i++) {
callbacks[i](newVal);
}
// Update the page (might be needed)
setTimeout(function() {
$rootScope.$apply();
}, 0);
}
});
};
// Define properties for all settings
var keys = $store.enumerateKeys();
for (var keyIdx in keys) {
var key = keys[keyIdx];
defineProperty(key);
}
// Add a callback to be called whenever the value is changed
// It's like a free $watch and used to be called the observer
// pattern, but I guess that's too old-school for JS kids :>
this.addCallback = function(key, callback, callNow) {
if (this.callbacks[key] === undefined) {
this.callbacks[key] = [callback];
} else {
this.callbacks[key].push(callback);
}
// call now to emulate $watch behaviour
setTimeout(function() {
callback($store.get(key));
}, 0);
};
return this;
}]);
})();