mirror of https://github.com/keeweb/keeweb.git
theme plugins
This commit is contained in:
parent
0c155c1e6a
commit
e459b8ef7b
|
@ -21,6 +21,16 @@ const SettingsManager = {
|
|||
'zh-CN': '汉语'
|
||||
},
|
||||
|
||||
allThemes: {
|
||||
fb: 'setGenThemeFb',
|
||||
db: 'setGenThemeDb',
|
||||
sd: 'setGenThemeSd',
|
||||
sl: 'setGenThemeSl',
|
||||
wh: 'setGenThemeWh',
|
||||
te: 'setGenThemeTe',
|
||||
hc: 'setGenThemeHc'
|
||||
},
|
||||
|
||||
customLocales: {
|
||||
},
|
||||
|
||||
|
|
|
@ -452,6 +452,7 @@
|
|||
"setPlInstallBtnProgress": "Installing",
|
||||
"setPlUninstallBtn": "Uninstall",
|
||||
"setPlLocaleBtn": "Switch to this language",
|
||||
"setPlThemeBtn": "Switch to this theme",
|
||||
"setPlJs": "code",
|
||||
"setPlCss": "styles",
|
||||
"setPlLoc": "language",
|
||||
|
|
|
@ -7,6 +7,7 @@ const Logger = require('../util/logger');
|
|||
const SettingsManager = require('../comp/settings-manager');
|
||||
const IoCache = require('../storage/io-cache');
|
||||
const AppSettingsModel = require('../models/app-settings-model');
|
||||
const BaseLocale = require('../locales/base.json');
|
||||
|
||||
const commonLogger = new Logger('plugin');
|
||||
const io = new IoCache({
|
||||
|
@ -171,7 +172,7 @@ const Plugin = Backbone.Model.extend({
|
|||
const manifest = this.get('manifest');
|
||||
const promises = [];
|
||||
if (this.resources.css) {
|
||||
promises.push(this.applyCss(manifest.name, this.resources.css));
|
||||
promises.push(this.applyCss(manifest.name, this.resources.css, manifest.theme));
|
||||
}
|
||||
if (this.resources.js) {
|
||||
promises.push(this.applyJs(manifest.name, this.resources.js));
|
||||
|
@ -229,10 +230,15 @@ const Plugin = Backbone.Model.extend({
|
|||
});
|
||||
},
|
||||
|
||||
applyCss(name, data) {
|
||||
applyCss(name, data, theme) {
|
||||
return Promise.resolve().then(() => {
|
||||
const text = kdbxweb.ByteUtils.bytesToString(data);
|
||||
this.createElementInHead('style', 'plugin-css-' + name, 'text/css', text);
|
||||
if (theme) {
|
||||
const locKey = this.getThemeLocaleKey(theme.name);
|
||||
SettingsManager.allThemes[theme.name] = locKey;
|
||||
BaseLocale[locKey] = theme.title;
|
||||
}
|
||||
this.logger.debug('Plugin style installed');
|
||||
});
|
||||
},
|
||||
|
@ -300,6 +306,18 @@ const Plugin = Backbone.Model.extend({
|
|||
}
|
||||
},
|
||||
|
||||
getThemeLocaleKey(name) {
|
||||
return `setGenThemeCustom_${name}`;
|
||||
},
|
||||
|
||||
removeTheme(theme) {
|
||||
delete SettingsManager.allThemes[theme.name];
|
||||
if (AppSettingsModel.instance.get('theme') === theme.name) {
|
||||
AppSettingsModel.instance.set('theme', 'fb');
|
||||
}
|
||||
delete BaseLocale[this.getThemeLocaleKey(theme.name)];
|
||||
},
|
||||
|
||||
uninstall() {
|
||||
const manifest = this.get('manifest');
|
||||
this.logger.info('Uninstalling plugin with resources', Object.keys(manifest.resources).join(', '));
|
||||
|
@ -320,6 +338,9 @@ const Plugin = Backbone.Model.extend({
|
|||
if (manifest.resources.loc) {
|
||||
this.removeLoc(this.get('manifest').locale);
|
||||
}
|
||||
if (manifest.theme) {
|
||||
this.removeTheme(manifest.theme);
|
||||
}
|
||||
return this.deleteResources().then(() => {
|
||||
this.set('status', 'inactive');
|
||||
this.logger.info('Uninstall complete', this.logger.ts(ts));
|
||||
|
|
|
@ -47,16 +47,6 @@ const SettingsGeneralView = Backbone.View.extend({
|
|||
|
||||
views: null,
|
||||
|
||||
allThemes: {
|
||||
fb: 'setGenThemeFb',
|
||||
db: 'setGenThemeDb',
|
||||
sd: 'setGenThemeSd',
|
||||
sl: 'setGenThemeSl',
|
||||
wh: 'setGenThemeWh',
|
||||
te: 'setGenThemeTe',
|
||||
hc: 'setGenThemeHc'
|
||||
},
|
||||
|
||||
initialize: function() {
|
||||
this.views = {};
|
||||
this.listenTo(UpdateModel.instance, 'change:status', this.render, this);
|
||||
|
@ -69,7 +59,7 @@ const SettingsGeneralView = Backbone.View.extend({
|
|||
const updateManual = UpdateModel.instance.get('updateManual');
|
||||
const storageProviders = this.getStorageProviders();
|
||||
this.renderTemplate({
|
||||
themes: _.mapObject(this.allThemes, theme => Locale[theme]),
|
||||
themes: _.mapObject(SettingsManager.allThemes, theme => Locale[theme]),
|
||||
activeTheme: AppSettingsModel.instance.get('theme'),
|
||||
locales: SettingsManager.allLocales,
|
||||
activeLocale: SettingsManager.activeLocale,
|
||||
|
|
|
@ -11,7 +11,8 @@ const SettingsPluginsView = Backbone.View.extend({
|
|||
events: {
|
||||
'click .settings_plugins-install-btn': 'installClick',
|
||||
'click .settings_plugins-uninstall-btn': 'uninstallClick',
|
||||
'click .settings_plugins-use-locale-btn': 'useLocaleClick'
|
||||
'click .settings_plugins-use-locale-btn': 'useLocaleClick',
|
||||
'click .settings_plugins-use-theme-btn': 'useThemeClick'
|
||||
},
|
||||
|
||||
initialize() {
|
||||
|
@ -70,6 +71,11 @@ const SettingsPluginsView = Backbone.View.extend({
|
|||
useLocaleClick(e) {
|
||||
const locale = $(e.target).data('locale');
|
||||
AppSettingsModel.instance.set('locale', locale);
|
||||
},
|
||||
|
||||
useThemeClick(e) {
|
||||
const theme = $(e.target).data('theme');
|
||||
AppSettingsModel.instance.set('theme', theme);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -19,9 +19,12 @@
|
|||
</div>
|
||||
<div class="settings__plugins-plugin-buttons">
|
||||
<button class="settings_plugins-uninstall-btn btn-silent" data-plugin="{{plugin.id}}">{{res 'setPlUninstallBtn'}}</button>
|
||||
{{#if plugin.manifest.resources.loc}}
|
||||
{{#if plugin.manifest.locale}}
|
||||
<button class="settings_plugins-use-locale-btn btn-silent" data-locale="{{plugin.manifest.locale.name}}">{{res 'setPlLocaleBtn'}}</button>
|
||||
{{/if}}
|
||||
{{#if plugin.manifest.theme}}
|
||||
<button class="settings_plugins-use-theme-btn btn-silent" data-theme="{{plugin.manifest.theme.name}}">{{res 'setPlThemeBtn'}}</button>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
{{/each}}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
"licence": "MIT",
|
||||
"url": "https://keeweb.info",
|
||||
"resources": {
|
||||
"js": "AXUK3TetuHvs0wZU0BW4fHHKhxO+GB6ji2YxuAS8UF64hsF4FQXA9dxg4KSDkUyUSvs8DMucmUNSevOw3UOLGP86jvBmiaGrS0M+/EXD4LUEXMtDVhn2mZmlCaX34sA9AyPVbZuP1eI+6o6vcTyS/ugH8T38i6pLAR3Xzl6iC0Z16WkyX0+3zmQGhMEJwAxTQNVfe+RjUtvsXoBIeay/tIohCRgpkXKoB1bOVT/cETdVThaFHeEEPAweGcX0/b3QQ6AU+oqJGB3RoEJJGWFc/rv40OMAlvw310QHtlv9eE+jMLcewQiF/x1LtBOb/a8whp5vhn3HR6jlUhhXOHbwhg=="
|
||||
"js": "GkZuvYFiRx6UZk1hvJjInhmunMxyFVuI3u4UpCB6rjho1hgfR9CtebwU6dyTYARfivzZAsD4kVxx8TnbsU+Wu4PuS0cvE9e7+C3I8yGwoTgpk8GOCnORsaQBXMRvi93Snb/B8TXwT7wpSVFraiNGsuf5VKGZqN7YB0DyZHmeAtZf8KXMeg5XrSiwUtTokdozFQKSAx9pyKpIBvEQ7c03wQfZu9L6xSYJsLTjNje2UbEH6TS7yVt5F1lqaitaHRUMAYGbVgZkAK75jboUitWKebXaJUJbF8VxWJJDp7cmYkq6Zc6Qy1uTElzAu8sR/jTxHsJ0UpgaUeXxqpMZjLEjYQ=="
|
||||
},
|
||||
"publicKey": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1QB+yQofkqIHbHFVAtWhjEFjaxvNekyQx/aK7nEpZzqM8ReoVWbJGVA+7z7MhymwZanbL8uAUrSpNTp5eFWltDksxqHqmXT4UcFU+4reLjYfgwjIaA3c9Q+2JA1Iowqbv3NDcDKm6Ug+dROr04VDCfYE4WRYgGdTYHDbJs5svxUgQ25uc0KKUWAvhYbSKsw43AwmbPbKkHdfZHiS5ZST99HVEJWxn3Kd2zLY9Kk70nu9MzypMLDqxUqjKgdeRCIyZeAYzB75miH3B5vMKhFcdmA8+D6WU2N+6gzKsY5BfqF729uFKSTo4JUKQ5fMU0lKSDHG4qGrkgnURfAUuj9YMQIDAQAB"
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
const Storage = require('storage/index');
|
||||
const Locale = require('locales/base');
|
||||
const BaseLocale = require('locales/base');
|
||||
const StorageBase = require('storage/storage-base');
|
||||
|
||||
const FailStorage = StorageBase.extend({
|
||||
|
@ -43,11 +43,11 @@ const FailStorage = StorageBase.extend({
|
|||
}
|
||||
});
|
||||
|
||||
Locale.failStorage = 'Fail';
|
||||
BaseLocale.failStorage = 'Fail';
|
||||
|
||||
Storage.failStorage = new FailStorage();
|
||||
|
||||
module.exports.uninstall = function() {
|
||||
delete Locale.failStorage;
|
||||
delete BaseLocale.failStorage;
|
||||
delete Storage.failStorage;
|
||||
};
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"version": "0.0.1",
|
||||
"manifestVersion": "0.1.0",
|
||||
"name": "psychodelic",
|
||||
"description": "Crazy animations for KeeWeb",
|
||||
"description": "Crazy animations",
|
||||
"author": {
|
||||
"name": "antelle",
|
||||
"email": "antelle.net@gmail.com",
|
||||
|
@ -15,4 +15,4 @@
|
|||
"css": "P3qX1ccKLeHI/75sWC/46O/Qs8cq6UFyoW2qPYRn05q8dtAfXr7YKXEndt1BqSqaa+ZanaA6TDmb5FJ/GKQpG1KfuXy+ug92uwSvp6QUd7/hj++OR6RRY/bsL4hA9J2BwMB3jYc58lCPcK2jcu3HCYX5T+I1tFLmqOAKbTUGQxl+a4lc0w/zAq9sEFIvm7Nj66HhF7TMqVoPt6pUBz7oWdTYuKJ3rz46rLd9kzTeaeG6WxGorFc6Sk5tlvy+o9e5S2T0lHJwCHw24rMeOSgwV8rA/RXXnKowVc9Qbb3KwVh2TlKUWRtUuygIIgSsp4GmzT+w8+5hXke7iXDTGczp1Q=="
|
||||
},
|
||||
"publicKey": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1QB+yQofkqIHbHFVAtWhjEFjaxvNekyQx/aK7nEpZzqM8ReoVWbJGVA+7z7MhymwZanbL8uAUrSpNTp5eFWltDksxqHqmXT4UcFU+4reLjYfgwjIaA3c9Q+2JA1Iowqbv3NDcDKm6Ug+dROr04VDCfYE4WRYgGdTYHDbJs5svxUgQ25uc0KKUWAvhYbSKsw43AwmbPbKkHdfZHiS5ZST99HVEJWxn3Kd2zLY9Kk70nu9MzypMLDqxUqjKgdeRCIyZeAYzB75miH3B5vMKhFcdmA8+D6WU2N+6gzKsY5BfqF729uFKSTo4JUKQ5fMU0lKSDHG4qGrkgnURfAUuj9YMQIDAQAB"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
.DS_Store
|
||||
*.log
|
||||
*.pem
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"version": "0.0.1",
|
||||
"manifestVersion": "0.1.0",
|
||||
"name": "rainbow-theme",
|
||||
"description": "Rainbow theme",
|
||||
"author": {
|
||||
"name": "antelle",
|
||||
"email": "antelle.net@gmail.com",
|
||||
"url": "http://antelle.net"
|
||||
},
|
||||
"licence": "MIT",
|
||||
"url": "https://keeweb.info",
|
||||
"resources": {
|
||||
"css": "VMBsTo36lliqTzhith4BqWOYW4n4nW5jt+Pj9LqnCJzUChZPtb2eQex1Al3YNC9gCxej1Dw0VNDr55HzBv/q/k4F1/zszaR1twtfRP2fiwGkxN5Cvso0IFjB1PUjr3VeMAnNMtkkkqAz9hHLaFkdIwVZf98wZ2WEIok+lAM2g9vSklZ34aikhvDbRojNZ0Waqovo41IA4Z3xhb0KQkud8WaH3oNxulitsiRdgIbigj43Gd5XlJYE+/JpAcnG033mC0W0XmXXrjEiD0CH8ZoEX/3vo7LVH+AfUuhJWl0zj49+VSjBe9X6+XiPIb2ZUEJEuSaD3vwg9GNSkjF49lB8gA=="
|
||||
},
|
||||
"publicKey": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1QB+yQofkqIHbHFVAtWhjEFjaxvNekyQx/aK7nEpZzqM8ReoVWbJGVA+7z7MhymwZanbL8uAUrSpNTp5eFWltDksxqHqmXT4UcFU+4reLjYfgwjIaA3c9Q+2JA1Iowqbv3NDcDKm6Ug+dROr04VDCfYE4WRYgGdTYHDbJs5svxUgQ25uc0KKUWAvhYbSKsw43AwmbPbKkHdfZHiS5ZST99HVEJWxn3Kd2zLY9Kk70nu9MzypMLDqxUqjKgdeRCIyZeAYzB75miH3B5vMKhFcdmA8+D6WU2N+6gzKsY5BfqF729uFKSTo4JUKQ5fMU0lKSDHG4qGrkgnURfAUuj9YMQIDAQAB",
|
||||
"theme": {
|
||||
"name": "rainbow",
|
||||
"title": "Rainbow"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
.th-rainbow * {
|
||||
animation: rainbow 5s linear 0s infinite;
|
||||
}
|
||||
.th-rainbow button {
|
||||
animation: bgrainbow 5s linear 0s infinite;
|
||||
border: 1px solid;
|
||||
}
|
||||
.th-rainbow input {
|
||||
border: 1px solid;
|
||||
}
|
||||
*:nth-child(5n+1) { animation-delay: -1s; }
|
||||
*:nth-child(5n+2) { animation-delay: -2s; }
|
||||
*:nth-child(5n+3) { animation-delay: -3s; }
|
||||
*:nth-child(5n+4) { animation-delay: -4s; }
|
||||
*:nth-child(5n+5) { animation-delay: -5s; }
|
||||
@keyframes rainbow {
|
||||
0% { color: lightseagreen; }
|
||||
20% { color: darkviolet; }
|
||||
40% { color: gold; }
|
||||
60% { color: hotpink; }
|
||||
80% { color: palegoldenrod; }
|
||||
100% { color: lightseagreen; }
|
||||
}
|
||||
@keyframes bgrainbow {
|
||||
0% { color: darkviolet; background-color: lightseagreen; }
|
||||
20% { color: gold; background-color: darkviolet; }
|
||||
40% { color: hotpink; background-color: gold; }
|
||||
60% { color: palegoldenrod; background-color: hotpink; }
|
||||
80% { color: lightseagreen; background-color: palegoldenrod; }
|
||||
100% { color: darkviolet; background-color: lightseagreen; }
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
"version": "0.0.1",
|
||||
"manifestVersion": "0.1.0",
|
||||
"name": "square-language",
|
||||
"description": "KeeWeb language which replaces everything with squares",
|
||||
"description": "Language which replaces everything with squares",
|
||||
"author": {
|
||||
"name": "antelle",
|
||||
"email": "antelle.net@gmail.com",
|
||||
|
|
|
@ -133,7 +133,8 @@ function gatherPluginData(callback) {
|
|||
'1: js only\n ' +
|
||||
'2: js + css\n ' +
|
||||
'3: css only\n ' +
|
||||
'4: locale\n' +
|
||||
'4: locale\n ' +
|
||||
'5: theme\n' +
|
||||
'Your plugin type is',
|
||||
callback: res => {
|
||||
const placeholder = `<resource signature will be here, please run 'kw-plugin-control sign ${data.name}'>`;
|
||||
|
@ -149,6 +150,11 @@ function gatherPluginData(callback) {
|
|||
break;
|
||||
case '4':
|
||||
data.resources = { loc: placeholder };
|
||||
data.locale = {};
|
||||
break;
|
||||
case '5':
|
||||
data.resources = { css: placeholder };
|
||||
data.theme = {};
|
||||
break;
|
||||
default:
|
||||
console.error('Please enter number from 1 to 4');
|
||||
|
@ -158,18 +164,18 @@ function gatherPluginData(callback) {
|
|||
}
|
||||
}, {
|
||||
text: 'Locale code (format: xx or xx-XX)',
|
||||
if: () => data.resources.loc,
|
||||
if: () => data.locale,
|
||||
callback: loc => {
|
||||
if (!/^[a-z]{2}(-[A-Z]{2})?$/.test(loc) || loc === 'en') {
|
||||
console.error('Invalid locale');
|
||||
return true;
|
||||
}
|
||||
data.locale = { name: loc };
|
||||
data.locale.name = loc;
|
||||
next();
|
||||
}
|
||||
}, {
|
||||
text: 'Locale name (human-readable)',
|
||||
if: () => data.resources.loc,
|
||||
if: () => data.locale,
|
||||
callback: loc => {
|
||||
if (!loc || loc.toLowerCase() === 'english' || loc.toLowerCase() === 'default') {
|
||||
console.error('Invalid locale');
|
||||
|
@ -178,6 +184,24 @@ function gatherPluginData(callback) {
|
|||
data.locale.title = loc;
|
||||
next();
|
||||
}
|
||||
}, {
|
||||
text: 'Theme class name (lowercase letters and dashes only)',
|
||||
if: () => data.theme,
|
||||
callback: loc => {
|
||||
if (!/^[a-z\-]+$/.test(loc)) {
|
||||
console.error('Invalid theme');
|
||||
return true;
|
||||
}
|
||||
data.theme.name = loc;
|
||||
next();
|
||||
}
|
||||
}, {
|
||||
text: 'Theme name (human-readable)',
|
||||
if: () => data.theme,
|
||||
callback: loc => {
|
||||
data.theme.title = loc;
|
||||
next();
|
||||
}
|
||||
}];
|
||||
|
||||
next();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "keeweb-plugin",
|
||||
"version": "0.1.0",
|
||||
"version": "0.1.1",
|
||||
"description": "KeeWeb plugin utils",
|
||||
"main": "keeweb-plugin.js",
|
||||
"scripts": {
|
||||
|
|
Loading…
Reference in New Issue