Add color customization and add updated logo to loading screen

This commit is contained in:
yflory 2024-03-19 18:16:01 +01:00
parent f147ad49f3
commit 0dcce94ef0
14 changed files with 158 additions and 29 deletions

View File

@ -15,7 +15,7 @@ define([
elem.innerHTML = [
'<div class="cp-loading-logo">',
'<img class="cp-loading-cryptofist" src="/customize/CryptPad_logo.svg?' + urlArgs + '" alt="' + Messages.label_logo + '">',
'<img class="cp-loading-cryptofist" src="/api/logo?' + urlArgs + '" alt="' + Messages.label_logo + '">',
'</div>',
'<div class="cp-loading-container">',
'<div class="cp-loading-spinner-container">',

View File

@ -9,9 +9,16 @@
@colortheme_app-font-size-small: 13px;
@colortheme_app-font: @colortheme_app-font-size @colortheme_font;
// Colors
@cryptpad_color_brand: #0087FF;
@cryptpad_color_brand_300: lighten(@cryptpad_color_brand, 30%);
@cryptpad_color_brand_fade: fade(@cryptpad_color_brand, 75%);
@cryptpad_color_brand_fader: fade(@cryptpad_color_brand, 50%);
@cryptpad_color_brand_fadest: fade(@cryptpad_color_brand, 25%);
@colortheme_apps: {
default: #0087FF;
drive: #0087FF; // Used as icon color in index.js (index.html)
default: @cryptpad_color_brand;
drive: @cryptpad_color_brand; // Used as icon color in index.js (index.html)
pad: #256ad5;
code: #EAA000;
slide: #e57614;
@ -27,18 +34,11 @@
}
@colortheme_static_apps: {
default: #0087FF;
default: @cryptpad_color_brand;
teams: #4A3BBD;
contacts: #607B8D;
}
// Colors
@cryptpad_color_brand: #0087FF;
@cryptpad_color_brand_300: lighten(@cryptpad_color_brand, 30%);
@cryptpad_color_brand_fade: fade(@cryptpad_color_brand, 75%);
@cryptpad_color_brand_fader: fade(@cryptpad_color_brand, 50%);
@cryptpad_color_brand_fadest: fade(@cryptpad_color_brand, 25%);
@cryptpad_color_white: #FFF;
@cryptpad_color_grey_50: #FAFAFA;
@cryptpad_color_grey_100: #F5F5F5;

View File

@ -9,9 +9,16 @@
@colortheme_app-font-size-small: 13px;
@colortheme_app-font: @colortheme_app-font-size @colortheme_font;
// Colors
@cryptpad_color_brand: #0087FF;
@cryptpad_color_brand_300: lighten(@cryptpad_color_brand, 30%);
@cryptpad_color_brand_fade: fade(@cryptpad_color_brand, 75%);
@cryptpad_color_brand_fader: fade(@cryptpad_color_brand, 50%);
@cryptpad_color_brand_fadest: fade(@cryptpad_color_brand, 25%);
@colortheme_apps: {
default: #0087FF;
drive: #0087FF; // Used as icon color in index.js (index.html)
default: @cryptpad_color_brand;
drive: @cryptpad_color_brand; // Used as icon color in index.js (index.html)
pad: #256ad5;
code: #EAA000;
slide: #e57614;
@ -27,18 +34,11 @@
}
@colortheme_static_apps: {
default: #0087FF;
default: @cryptpad_color_brand;
teams: #4A3BBD;
contacts: #607B8D;
}
// Colors
@cryptpad_color_brand: #0087FF;
@cryptpad_color_brand_300: lighten(@cryptpad_color_brand, 30%);
@cryptpad_color_brand_fade: fade(@cryptpad_color_brand, 75%);
@cryptpad_color_brand_fader: fade(@cryptpad_color_brand, 50%);
@cryptpad_color_brand_fadest: fade(@cryptpad_color_brand, 25%);
@cryptpad_color_white: #FFF;
@cryptpad_color_grey_50: #FAFAFA;
@cryptpad_color_grey_100: #F5F5F5;

View File

@ -75,7 +75,8 @@
margin-left: auto;
margin-right: auto;
max-width: 90vw;
max-height: 300px;
max-height: ~"max(40vh, 250px)";
//max-height: 300px;
width: auto;
height: auto;
margin-bottom: 2em;

View File

@ -151,6 +151,10 @@
flex-flow: column;
align-items: baseline;
}
a {
color: @cryptpad_color_link;
text-decoration: underline;
}
table {
.cp-strong {
font-weight: bold;

View File

@ -61,6 +61,9 @@
@media screen and (max-width: 990px) {
justify-content: center;
}
img {
max-height: ~"max(40vh, 250px)";
}
}
.cp-title {
display: flex;

View File

@ -72,7 +72,7 @@ html:not(.cp-app-noscroll) #placeholder.dark-theme {
margin-left: auto;
margin-right: auto;
max-width: 90vw;
max-height: 300px;
max-height: max(40vh, 250px);
width: auto;
height: auto;
margin-bottom: 2em;

View File

@ -967,6 +967,21 @@ var uploadLogo = (Env, Server, cb, data, unsafeKey) => {
});
};
var changeColor = (Env, Server, cb, data, unsafeKey) => {
const args = Array.isArray(data) && data[1];
if (!args || typeof(args) !== 'object') { return void cb("EINVAL"); }
let color = args.color;
adminDecree(Env, null, function (err) {
if (err) { return void cb(err); }
Env.flushCache();
cb(void 0, true);
}, ['CHANGE_COLOR', [
'SET_ACCENT_COLOR',
[color]
]], unsafeKey);
};
var commands = {
ACTIVE_SESSIONS: getActiveSessions,
ACTIVE_PADS: getActiveChannelCount,
@ -1037,6 +1052,7 @@ var commands = {
UPLOAD_LOGO: uploadLogo,
REMOVE_LOGO: removeLogo,
CHANGE_COLOR: changeColor,
};
// addFirstAdmin is an anon_rpc command

View File

@ -159,7 +159,7 @@ var makeGenericSetter = function (attr, validator) {
};
var isString = (str) => {
return str && typeof(str) === "string";
return typeof(str) === "string";
};
var isInteger = function (n) {
return !(typeof(n) !== 'number' || isNaN(n) || (n % 1) !== 0);
@ -180,9 +180,12 @@ var arg_isPositiveInteger = function (args) {
return Array.isArray(args) && isInteger(args[0]) && args[0] > 0;
};
// CryptPad_AsyncStore.rpc.send('ADMIN', [ 'ADMIN_DECREE', ['LOGO_MIME', ['image/png']]], console.log)
// CryptPad_AsyncStore.rpc.send('ADMIN', [ 'ADMIN_DECREE', ['SET_LOGO_MIME', ['image/png']]], console.log)
commands.SET_LOGO_MIME = makeGenericSetter('logoMimeType', args_isString);
// CryptPad_AsyncStore.rpc.send('ADMIN', [ 'ADMIN_DECREE', ['SET_ACCENT_COLOR', ['#ff0073']]], console.log)
commands.SET_ACCENT_COLOR = makeGenericSetter('accentColor', args_isString);
// CryptPad_AsyncStore.rpc.send('ADMIN', [ 'ADMIN_DECREE', ['ENABLE_PROFILING', [true]]], console.log)
commands.ENABLE_PROFILING = makeBooleanSetter('enableProfiling');

View File

@ -622,6 +622,7 @@ var Define = function (obj) {
app.get('/api/instance', function (req, res) {
res.setHeader('Content-Type', 'text/javascript');
res.send(Define({
color: Env.accentColor,
name: Env.instanceName,
description: Env.instanceDescription,
location: Env.instanceJurisdiction,

View File

@ -9,8 +9,9 @@ const require = define;
*/
define([
'/api/config',
'/api/instance',
'/components/nthen/index.js'
], function (Config, nThen) { /*::});module.exports = (function() {
], function (Config, Instance, nThen) { /*::});module.exports = (function() {
const Config = (undefined:any);
const nThen = (undefined:any);
*/
@ -153,6 +154,10 @@ define([
].join('\n');
text += '\n'+custom;
}
if (Instance && Instance.color) {
let pattern = /_color_brand: ([0-9a-zA-Z#]+);/gm;
text = text.replace(pattern, `_color_brand: ${Instance.color};`);
}
}
cached.res = [ text, lastModified ];
var queue = cached.queue;

View File

@ -61,8 +61,10 @@ define([
blocks.code = val => {
return h('code', val);
};
blocks.inline = (value) => {
return h('span', value);
blocks.inline = (value, className) => {
let attr = {};
if (className) { attr.class = className; }
return h('span', attr, value);
};
blocks.block = (content, className) => {
return h('div', { class: className }, content);

View File

@ -19,5 +19,12 @@
display: flex;
flex-flow: column;
font: @colortheme_app-font;
.cp-admin-color-current {
width: 30px;
height: 30px;
border-radius: 5px;
background: @cryptpad_color_brand;
}
}

View File

@ -19,6 +19,7 @@ define([
'json.sortify',
'/customize/application_config.js',
'/api/config',
'/api/instance',
'/lib/datepicker/flatpickr.js',
'/common/hyperscript.js',
'css!/lib/datepicker/flatpickr.min.css',
@ -42,6 +43,7 @@ define([
Sortify,
AppConfig,
ApiConfig,
Instance,
Flatpickr
) {
var APP = window.APP = {};
@ -760,8 +762,15 @@ define([
Messages.admin_logoHint = "Max 200KB, svg, png or jpg";
Messages.admin_logoButton = "Upload new";
Messages.admin_logoRemoveButton = "Restore default";
Messages.admin_colorTitle = "Main color";
Messages.admin_colorHint = "Change the main color of your CryptPad instance. Please pick a color with good contrast with the rest of CryptPad.";
Messages.admin_colorCurrent = "Current main color";
Messages.admin_colorChange = "Change color";
Messages.admin_colorPick = "Pick a color";
Messages.admin_colorPreview = "Preview color";
sidebar.addItem('logo', (cb) => {
// Msg.admin_emailHint, Msg.admin_emailTitle
// Msg.admin_logoHint, Msg.admin_logoTitle
let input = blocks.input({
type: 'file',
@ -840,6 +849,84 @@ define([
cb(form);
});
sidebar.addItem('color', cb => {
let input = blocks.input({
type: 'color',
value: (Instance && Instance.color) || '#0087FF'
});
let label = blocks.labelledInput(Messages.admin_colorPick, input);
let current = blocks.block([], 'cp-admin-color-current');
let labelCurrent = blocks.labelledInput(Messages.admin_colorCurrent, current);
let preview = blocks.block([
blocks.block([
blocks.link('CryptPad', '/admin/#customize')
]),
blocks.nav([
blocks.button('primary', 'fa-floppy-o', Messages.settings_save),
blocks.button('secondary', 'fa-floppy-o', Messages.settings_save),
])
], 'cp-admin-color-preview');
let labelPreview = blocks.labelledInput(Messages.admin_colorPreview, preview);
let $preview = $(preview);
let remove = blocks.button('danger', '', Messages.admin_logoRemoveButton);
let $remove = $(remove);
let setColor = (color, done) => {
sframeCommand('CHANGE_COLOR', {color}, (err, response) => {
if (err) {
UI.warn(Messages.error);
console.error(err, response);
done(false);
return;
}
done(true);
flushCacheNotice();
UI.log(Messages.saved);
});
};
let btn = blocks.activeButton('primary', '',
Messages.admin_colorChange, (done) => {
let color = $input.val();
setColor(color, done);
});
let $input = $(input).on('change', () => {
require(['/lib/less.min.js'], (Less) => {
let color = $input.val();
let lColor = Less.color(color.slice(1));
let lighten = Less.functions.functionRegistry._data.lighten;
let lightColor = lighten(lColor, {value:30}).toRGB();
$preview.find('.btn-primary').css({
'background-color': color
});
$preview.find('.btn-secondary').css({
'border-color': lightColor,
'color': lightColor,
});
$preview.find('a').css({
'color': lightColor,
});
});
});
UI.confirmButton($remove, {
classes: 'btn-danger',
multiple: true
}, function () {
$remove.attr('disabled', 'disabled');
setColor('', () => {});
});
let form = blocks.form([
labelCurrent,
label
], blocks.nav([btn, remove, btn.spinner]));
cb([form, labelPreview]);
});
sidebar.addItem('registration', function(cb){
var refresh = function () {};