Browse Source

Add darkmode switcher

ghorsington 4 years ago
parent
commit
4bb8d157d6

+ 18 - 0
controllers/appearanceController.js

@@ -0,0 +1,18 @@
+const config = require('../config.js');
+
+let appearanceController = {};
+
+appearanceController.toggleDarkMode = async (req, res, next) => {
+    let cur = req.cookies.appearance || 'light';
+    if(cur == 'light')
+        cur = 'dark';
+    else if(cur == 'dark')
+        cur = 'light';
+    res.cookie('appearance', cur, {
+        'domain': config.domain,
+        'expires': new Date(253402300000000) 
+    });
+    return res.json({ currentStyle: cur });
+};
+
+module.exports = appearanceController;

+ 5 - 2
lolisafe.js

@@ -8,6 +8,7 @@ const RateLimit = require('express-rate-limit');
 const db = require('knex')(config.database);
 const fs = require('fs');
 const exphbs = require('express-handlebars');
+const cookieParser = require('cookie-parser');
 const safe = express();
 
 require('./database/db.js')(db);
@@ -18,6 +19,8 @@ fs.existsSync('./' + config.uploads.folder) || fs.mkdirSync('./' + config.upload
 fs.existsSync('./' + config.uploads.folder + '/thumbs') || fs.mkdirSync('./' + config.uploads.folder + '/thumbs');
 fs.existsSync('./' + config.uploads.folder + '/zips') || fs.mkdirSync('./' + config.uploads.folder + '/zips')
 
+safe.use(cookieParser());
+
 safe.use(helmet());
 safe.set('trust proxy', 1);
 
@@ -46,9 +49,9 @@ safe.use('/api', api);
 
 for (let page of config.pages) {
 	if (page === 'home') {
-		safe.get('/', (req, res, next) => res.render('home', { layout: false, config: config }));
+		safe.get('/', (req, res, next) => res.render('home', { layout: false, config: config, appearance: req.cookies.appearance || 'light' }));
 	} else {
-		safe.get(`/${page}`, (req, res, next) => res.render(page, { layout:false, config: config }));
+		safe.get(`/${page}`, (req, res, next) => res.render(page, { layout:false, config: config, appearance: req.cookies.appearance || 'light' }));
 	}
 }
 

+ 1 - 0
package.json

@@ -17,6 +17,7 @@
   "dependencies": {
     "bcrypt": "^3.0.4",
     "body-parser": "^1.18.2",
+    "cookie-parser": "^1.4.4",
     "express": "^4.16.1",
     "express-handlebars": "^3.0.0",
     "express-rate-limit": "^2.11.0",

+ 16 - 0
public/css/style.css

@@ -2,6 +2,10 @@
 		HOME
 ------------------ */
 
+body {
+	min-height: 100vh;
+}
+
 section#home #b {
 	-webkit-animation-delay: 0.5s;
 	animation-delay: 0.5s;
@@ -134,3 +138,15 @@ table.bold-children td.normal {
 	text-overflow: ellipsis;
 	overflow: hidden;
 } */
+
+span#appearance-switch {
+	position: absolute;
+	top: 0;
+	right: 0;
+	padding: 0.2em;
+	cursor: pointer;
+}
+
+span#appearance-switch > i {
+	font-size: 2em !important;
+}

+ 63 - 0
public/css/style_dark.css

@@ -0,0 +1,63 @@
+span#appearance-switch {
+    color: #f5f5f5;
+}
+
+body, .hero, .section {
+    background-color: #363636;
+}
+
+.hero {
+    color: #f5f5f5;
+}
+
+.hero .subtitle, .hero strong, .hero .title,
+.section .subtitle, .section strong, a:hover, .section .title,
+.menu-label {
+    color: rgba(245,245,245,.9);
+}
+
+.pagination-link:hover, .pagination-next:hover, .pagination-previous:hover {
+    color: rgba(245,245,245,.9);
+}
+
+.message strong {
+    color: #363636;
+}
+
+section#home #b {
+    background-color: #202020;
+}
+
+.menu-list a {
+    color: rgba(245,245,245,.9);
+}
+
+.menu-list a:hover {
+    background-color: #202020;
+}
+
+table {
+    background-color: #363636 !important;
+}
+
+.table td, .table th {
+    color: #f5f5f5 !important;
+}
+
+table tr:hover {
+    background-color: #151515 !important;
+}
+
+.table.is-striped tbody tr:nth-child(even) {
+    background-color: #303030 !important;
+}
+
+input {
+    background-color: #505050 !important;
+    color: #f0f0f0 !important;
+    border-color: #303030 !important;
+}
+
+::placeholder {
+    color: #d0d0d0 !important;
+}

+ 7 - 0
public/css/style_light.css

@@ -0,0 +1,7 @@
+span#appearance-switch {
+    color: black;
+}
+
+section#login {
+    background-color: #f5f6f8;
+}

+ 25 - 0
public/js/appearance.js

@@ -0,0 +1,25 @@
+axios.defaults.withCredentials = true;
+
+let appearance = {};
+
+appearance.sheetElement = null;
+
+appearance.prepare = () => {
+    appearance.sheetElement = document.getElementById('appearance-sheet');
+    let lightbulb = document.getElementById('appearance-switch');
+    lightbulb.addEventListener('click', appearance.toggleLightMode);
+};
+
+appearance.toggleLightMode = (e) => {
+    e.preventDefault();
+
+    axios.post('/api/appearance/toggle').then(res => {
+        let newStyle = res.data.currentStyle;
+        appearance.sheetElement.setAttribute("href", `/css/style_${newStyle}.css`);
+        appearance.currentStyle = newStyle;
+    });
+};
+
+window.addEventListener('load', () => {
+    appearance.prepare();
+});

+ 2 - 0
routes/api.js

@@ -4,6 +4,7 @@ const uploadController = require('../controllers/uploadController');
 const albumsController = require('../controllers/albumsController');
 const tokenController = require('../controllers/tokenController');
 const authController = require('../controllers/authController');
+const appearanceController = require('../controllers/appearanceController');
 
 routes.get('/check', (req, res, next) => {
 	return res.json({
@@ -12,6 +13,7 @@ routes.get('/check', (req, res, next) => {
 	});
 });
 
+routes.post('/appearance/toggle', (req, res, next) => appearanceController.toggleDarkMode(req, res, next));
 routes.post('/login', (req, res, next) => authController.verify(req, res, next));
 routes.post('/register', (req, res, next) => authController.register(req, res, next));
 routes.post('/password/change', (req, res, next) => authController.changePassword(req, res, next));

+ 0 - 1
views/album.handlebars

@@ -2,7 +2,6 @@
     {{#*inline "head-block"}}
        <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.1.3/sweetalert.min.css">
         <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.1.3/sweetalert.min.js"></script>
-		<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.15.3/axios.min.js"></script>
         <script type="text/javascript" src="/js/album.js"></script>
     {{/inline}}
     {{#*inline "body-block"}}

+ 0 - 1
views/album_public.handlebars

@@ -16,7 +16,6 @@
 		{{#*inline "head-block"}}
 				<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.1.3/sweetalert.min.css">
         <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.1.3/sweetalert.min.js"></script>
-				<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.15.3/axios.min.js"></script>
     {{/inline}}
     {{#*inline "body-block"}}
 		<section class="hero is-fullheight">

+ 0 - 8
views/auth.handlebars

@@ -2,17 +2,9 @@
     {{#*inline "head-block"}}
         <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.1.3/sweetalert.min.css">
         <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.1.3/sweetalert.min.js"></script>
-		<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.15.3/axios.min.js"></script>
-        <script type="text/javascript" src="https://use.fontawesome.com/cd26baa9bd.js"></script>
         <script type="text/javascript" src="/js/auth.js"></script>
     {{/inline}}
     {{#*inline "body-block"}}
-        <style type="text/css">
-			section#login {
-				background-color: #f5f6f8;
-			}
-		</style>
-
 		<section id='login' class="hero is-fullheight">
 			<div class="hero-body">
 				<div class="container">

+ 0 - 2
views/dashboard.handlebars

@@ -2,8 +2,6 @@
     {{#*inline "head-block"}}
 		<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.1.3/sweetalert.min.css">
         <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.1.3/sweetalert.min.js"></script>
-		<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.15.3/axios.min.js"></script>
-        <script type="text/javascript" src="https://use.fontawesome.com/cd26baa9bd.js"></script>
         <script type="text/javascript" src="/js/dashboard.js"></script>
     {{/inline}}
     {{#*inline "body-block"}}

+ 0 - 1
views/home.handlebars

@@ -2,7 +2,6 @@
     {{#*inline "head-block"}}
 		<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.1.3/sweetalert.min.css">
         <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.1.3/sweetalert.min.js"></script>
-		<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.15.3/axios.min.js"></script>
 		<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/dropzone/4.3.0/min/dropzone.min.js"></script>
         <script type="text/javascript" src="/js/home.js"></script>
     {{/inline}}

+ 7 - 1
views/partials/base.handlebars

@@ -33,13 +33,19 @@
         {{/cards-block}}
 
 		<title>{{#if title}}{{title}}{{else}}{{config.title}}{{/if}}</title>
+
+		<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.15.3/axios.min.js"></script>
+        <script type="text/javascript" src="https://use.fontawesome.com/cd26baa9bd.js"></script>
 		<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.3.0/css/bulma.min.css">
-		<link rel="stylesheet" type="text/css" href="/css/style.css">		
+		<link rel="stylesheet" type="text/css" href="/css/style.css">
+		<link id="appearance-sheet" rel="stylesheet" type="text/css" href="/css/style_{{appearance}}.css">
+		<script type="text/javascript" src="/js/appearance.js"></script>		
         {{#> head-block}}
         {{/head-block}}
 	</head>
 
 	<body>
+		<span id="appearance-switch" data-appearance="{{appearance}}"><i class="fa fa-lightbulb-o" aria-hidden="true"></i></span>
         {{#> body-block}}
         {{/body-block}}
 	</body>