diff --git a/client/css/forms.css b/client/css/forms.css
index 00cebc9e..1d30e864 100644
--- a/client/css/forms.css
+++ b/client/css/forms.css
@@ -25,6 +25,13 @@ form .input li:first-child {
padding-top: 0;
margin-top: 0;
}
+form .hint {
+ margin-top: 0.5em;
+ margin-bottom: 0;
+ color: var(--inactive-link-color);
+ font-size: 80%;
+ line-height: 120%;
+}
form.tabular ul {
display: table;
diff --git a/client/css/main.css b/client/css/main.css
index ad096879..bbec0161 100644
--- a/client/css/main.css
+++ b/client/css/main.css
@@ -130,6 +130,7 @@ nav.text-nav ul li.active a {
#top-nav ul li[data-name=register],
#top-nav ul li[data-name=login],
#top-nav ul li[data-name=logout],
+#top-nav ul li[data-name=settings],
#top-nav ul li[data-name=help] {
float: none;
}
diff --git a/client/css/users.css b/client/css/users.css
index 85e0e2f8..0a30b427 100644
--- a/client/css/users.css
+++ b/client/css/users.css
@@ -26,14 +26,6 @@
#user-registration .info p:first-child {
margin: 0 0 0.5em 0;
}
-#user .hint,
-#user-registration .hint {
- margin-top: 0.5em;
- margin-bottom: 0;
- color: var(--inactive-link-color);
- font-size: 80%;
- line-height: 120%;
-}
#login .buttons a {
margin-left: 1em;
diff --git a/client/html/settings.hbs b/client/html/settings.hbs
new file mode 100644
index 00000000..aea55749
--- /dev/null
+++ b/client/html/settings.hbs
@@ -0,0 +1,18 @@
+
diff --git a/client/js/controllers/settings_controller.js b/client/js/controllers/settings_controller.js
new file mode 100644
index 00000000..731ea2da
--- /dev/null
+++ b/client/js/controllers/settings_controller.js
@@ -0,0 +1,53 @@
+'use strict';
+
+const page = require('page');
+const events = require('../events.js');
+const topNavController = require('../controllers/top_nav_controller.js');
+const SettingsView = require('../views/settings_view.js');
+
+class SettingsController {
+ constructor() {
+ this.settingsView = new SettingsView();
+ }
+
+ registerRoutes() {
+ page('/settings', (ctx, next) => { this.settingsRoute(); });
+ }
+
+ settingsRoute() {
+ topNavController.activate('settings');
+ this.settingsView.render({
+ getSettings: () => this.getSettings(),
+ saveSettings: newSettings => this.saveSettings(newSettings),
+ });
+ }
+
+ saveSettings(browsingSettings) {
+ localStorage.setItem('settings', JSON.stringify(browsingSettings));
+ events.notify(events.Success, 'Settings saved');
+ }
+
+ getSettings(settings) {
+ const defaultSettings = {
+ endlessScroll: false,
+ };
+ let ret = {};
+ let userSettings = localStorage.getItem('settings');
+ if (userSettings) {
+ userSettings = JSON.parse(userSettings);
+ }
+ if (!userSettings) {
+ userSettings = {};
+ }
+ for (let key of Object.keys(defaultSettings)) {
+ if (key in userSettings) {
+ ret[key] = userSettings[key];
+ } else {
+ ret[key] = defaultSettings[key];
+ }
+ }
+ return ret;
+ }
+};
+
+module.exports = new SettingsController();
diff --git a/client/js/controllers/top_nav_controller.js b/client/js/controllers/top_nav_controller.js
index a9c15ea3..51d30021 100644
--- a/client/js/controllers/top_nav_controller.js
+++ b/client/js/controllers/top_nav_controller.js
@@ -31,6 +31,8 @@ class TopNavController {
'login': new NavigationItem('L', 'Log in', '/login'),
'logout': new NavigationItem('O', 'Logout', '/logout'),
'help': new NavigationItem('E', 'Help', '/help'),
+ 'settings': new NavigationItem(
+ null, '