From 0e9849bab892f0546bcd4b7eface3603fd0715f4 Mon Sep 17 00:00:00 2001 From: Mauro Balades Date: Fri, 9 Aug 2024 00:00:23 +0200 Subject: [PATCH] refactor: Initialize shortcuts only on the browser page --- src/ZenKeyboardShortcuts.mjs | 1 + src/ZenThemeBuilder.mjs | 181 +++++++++++++++++++++++++++++++++++ 2 files changed, 182 insertions(+) create mode 100644 src/ZenThemeBuilder.mjs diff --git a/src/ZenKeyboardShortcuts.mjs b/src/ZenKeyboardShortcuts.mjs index 94be6c8..ca6086a 100644 --- a/src/ZenKeyboardShortcuts.mjs +++ b/src/ZenKeyboardShortcuts.mjs @@ -121,6 +121,7 @@ const kZKSActions = { const kZKSStorageKey = "zen.keyboard.shortcuts"; var gZenKeyboardShortcuts = { init() { + return; this._initShortcuts(); }, diff --git a/src/ZenThemeBuilder.mjs b/src/ZenThemeBuilder.mjs new file mode 100644 index 0000000..9729a25 --- /dev/null +++ b/src/ZenThemeBuilder.mjs @@ -0,0 +1,181 @@ + +const kZenAccentColorConfigKey = "zen.theme.accent-color"; + +var gZenThemeBuilder = { + init() { + this._mouseMoveListener = this._handleThumbMouseMove.bind(this); + setTimeout(() => { + this._initBuilderUI(); + }, 500); + }, + + get _builderWrapper() { + if (this.__builderWrapper) { + return this.__builderWrapper; + } + this.__builderWrapper = document.getElementById("zen-theme-builder-wrapper"); + return this.__builderWrapper; + }, + + _initBuilderUI() { + let wrapper = this._builderWrapper; + console.log(wrapper); + if (!wrapper) { + return; + } + + console.log("gZenThemeBuilder: init builder UI"); + + const kTemplate = ` + + + + + + + + + `; + wrapper.innerHTML = kTemplate; + this._initColorPicker(); + }, + + _getPositionFromColor(ctx, color) { + var w = ctx.canvas.width, + h = ctx.canvas.height, + data = ctx.getImageData(0, 0, w, h), /// get image data + buffer = data.data, /// and its pixel buffer + len = buffer.length, /// cache length + x, y = 0, p, px; /// for iterating + /// iterating x/y instead of forward to get position the easy way + for(;y < h; y++) { + /// common value for all x + p = y * 4 * w; + for(x = 0; x < w; x++) { + /// next pixel (skipping 4 bytes as each pixel is RGBA bytes) + px = p + x * 4; + /// if red component match check the others + if (buffer[px] === color[0]) { + if (buffer[px + 1] === color[1] && + buffer[px + 2] === color[2]) { + return [x, y]; + } + } + } + } + return null; + }, + + _hexToRgb(hex) { + var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); + return [ + parseInt(result[1], 16), + parseInt(result[2], 16), + parseInt(result[3], 16) + ] + }, + + _componentToHex(c) { + var hex = c.toString(16); + return hex.length == 1 ? "0" + hex : hex; + }, + + _rgbToHex(r, g, b) { + return "#" + this._componentToHex(r) + this._componentToHex(g) + this._componentToHex(b); + }, + + _initColorPicker() { + const canvas = document.getElementById("zen-theme-builder-color-picker-canvas"); + const thumb = document.getElementById("zen-theme-builder-color-picker-thumb"); + + // A all the main colors are all blended together towards the center. + // But we also add some random gradients to make it look more interesting. + // Instead of using a simple gradient, we use a radial gradient. + const ctx = canvas.getContext("2d"); + const size = 180; + canvas.width = size; + canvas.height = size; + const center = size / 2; + const radius = size / 2; + const gradient = ctx.createConicGradient(0, center, center); + gradient.addColorStop(0, '#fff490'); + gradient.addColorStop(1 / 12, '#f9e380'); + gradient.addColorStop(2 / 12, '#fecc87'); + gradient.addColorStop(3 / 12, '#ffa894'); + gradient.addColorStop(4 / 12, '#f98089'); + gradient.addColorStop(5 / 12, '#f9b7c5'); + gradient.addColorStop(6 / 12, '#c193b8'); + gradient.addColorStop(7 / 12, '#a8b7e0'); + gradient.addColorStop(8 / 12, '#88d2f9'); + gradient.addColorStop(9 / 12, '#81e8e5'); + gradient.addColorStop(10 / 12, '#b7e5a5'); + gradient.addColorStop(11 / 12, '#eaefac'); + gradient.addColorStop(1, '#fff490'); + + const radialGradient = ctx.createRadialGradient(size / 2, size / 2, 0, size / 2, size / 2, size / 2); + radialGradient.addColorStop(0, 'rgba(255,255,255,1)'); + radialGradient.addColorStop(1, 'rgba(255,255,255,0)'); + + ctx.fillStyle = gradient; + ctx.fillRect(0, 0, size, size); + + //ctx.fillStyle = radialGradient; + //ctx.fillRect(0, 0, size, size); + + // Add the thumb. + const accentColor = Services.prefs.getStringPref(kZenAccentColorConfigKey, "#aac7ff"); + const pos = this._getPositionFromColor(ctx, this._hexToRgb(accentColor)); + + let x = pos ? pos[0] : center; + let y = pos ? pos[1] : center; + + thumb.style.left = `${x}px`; + thumb.style.top = `${y}px`; + + thumb.addEventListener("mousedown", this._handleThumbMouseDown.bind(this)); + document.addEventListener("mouseup", this._handleThumbMouseUp.bind(this)); + }, + + _handleThumbMouseDown(e) { + document.addEventListener("mousemove", this._mouseMoveListener); + }, + + _handleThumbMouseUp(e) { + document.removeEventListener("mousemove", this._mouseMoveListener); + }, + + _handleThumbMouseMove(e) { + const kThumbOffset = 15; + const deck = document.getElementById("zen-theme-builder-color-picker-deck"); + + const thumb = document.getElementById("zen-theme-builder-color-picker-thumb"); + const rect = deck.getBoundingClientRect(); + let x = e.clientX - rect.left; + let y = e.clientY - rect.top; + + if (x > rect.width - kThumbOffset) { + x = rect.width - kThumbOffset; + } + if (y > rect.height - kThumbOffset) { + y = rect.height - kThumbOffset; + } + if (x < kThumbOffset) { + x = kThumbOffset; + } + if (y < kThumbOffset) { + y = kThumbOffset; + } + + thumb.style.left = `${x}px`; + thumb.style.top = `${y}px`; + + const canvas = document.getElementById("zen-theme-builder-color-picker-canvas"); + const ctx = canvas.getContext("2d"); + const imageData = ctx.getImageData(x, y, 1, 1); + + // Update the accent color. + Services.prefs.setStringPref(kZenAccentColorConfigKey, this._rgbToHex(...imageData.data)); + }, +}; + +gZenThemeBuilder.init();