Skip to content

Commit

Permalink
Add settings preview pane
Browse files Browse the repository at this point in the history
  • Loading branch information
cyberpirate92 committed Oct 13, 2020
1 parent 973e964 commit e43e0e2
Show file tree
Hide file tree
Showing 2 changed files with 208 additions and 33 deletions.
204 changes: 177 additions & 27 deletions src/js/preferences.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,15 @@
* @property {number} backgroundPadding
*/

/**
* @typedef {Object} Themes
* @property {string[]} themes
*/

/**
* Fetch theme list from backend
* @retuns {Themes} Theme list
*/
async function getThemeList() {
const response = await fetch('https://code2img.vercel.app/api/themes');
Expand All @@ -21,17 +27,84 @@ async function getThemeList() {
}

/**
* Make sure `value` is between `minValue` and `maxValue`
* Get boolean value from their string representation
* @param {string} str The string representation
*
* @returns {boolean} The equivalent boolean value for the given string representation
*/
function fromBooleanString(str) {
return str === 'true';
}

/**
* Generate preview and set it as the source to the provided image element
*
* @param {HTMLImageElement} imageElement
* @param {HTMLDivElement} spinnerElement
* @param {HTMLDivElement} errorAlert
* @param {UserPreferences} preferences
*/
function generatePreview(imageElement, spinnerElement, errorAlert, preferences) {
try {
errorAlert && errorAlert.classList.add('d-none');
spinnerElement && spinnerElement.classList.remove('d-none');
imageElement && imageElement.classList.add('d-none');

let queryParams = new URLSearchParams();
queryParams.set('language', 'java');
queryParams.set('theme', 'xonokai');
queryParams.set('background-color', preferences.backgroundColor);
queryParams.set('show-background', preferences.showBackground);
queryParams.set('line-numbers', preferences.showLineNumbers);
queryParams.set('background-image', preferences.backgroundImage);
queryParams.set('padding', preferences.backgroundPadding);
queryParams.set('scale', 1); // since this is just a preview, no need for high res images here

let requestUrl = `https://code2img.vercel.app/api/to-image?${queryParams.toString()}`;
let request = new XMLHttpRequest();
request.responseType = 'blob';
request.addEventListener("load", function () {
spinnerElement && spinnerElement.classList.add('d-none');
imageElement && imageElement.classList.remove('d-none');
if (this.readyState === 4) {
if (this.status === 200) {
if (this.responseType === 'blob') {
const imageBlobUrl = window.URL.createObjectURL(this.response);
imageElement.src = imageBlobUrl;
} else {
console.error('[Themeify Extension]: ', 'Unknown response, ignored');
}
} else {
spinnerElement && spinnerElement.classList.add('d-none');
imageElement && imageElement.classList.add('d-none');
errorAlert && errorAlert.classList.remove('d-none');
console.error('Generating preview failed');
}
}
});
request.open("POST", requestUrl);
request.send(previewCode);
} catch (error) {
spinnerElement && spinnerElement.classList.add('d-none');
imageElement && imageElement.classList.add('d-none');
errorAlert && errorAlert.classList.remove('d-none');
console.error(error);
}
}

/**
* Make sure `value` is between the inclusive range (`minValue`, `maxValue`)
* @param {number} value The value to be normalized
* @param {number} minValue The upper bound possible for the given value
* @param {number} maxValue The lower bound possible for the given value
* @param {number} minValue Inclusive Upper bound
* @param {number} maxValue Inclusive Lower bound
*
* @returns {number} Number guarenteed to be in the inclusive range {minValue, maxValue}
* @returns {number} Number guarenteed to be in the inclusive range (`minValue`, `maxValue`)
*/
function normalize(value, minValue, maxValue) {
return Math.max(Math.min(value, maxValue), minValue);
}


(() => {
/** @type {HTMLButtonElement} */
let saveButton = document.querySelector('#saveButton');
Expand All @@ -45,9 +118,6 @@ function normalize(value, minValue, maxValue) {
/** @type {HTMLInputElement} */
let backgroundColorTextbox = document.querySelector('#backgroundColor');

/** @type {HTMLDivElement} */
let backgroundColorPreview = document.querySelector('#backgroundColorPreview');

/** @type {HTMLInputElement} */
let showBackgroundCheckbox = document.querySelector('#showBackground');

Expand All @@ -56,6 +126,9 @@ function normalize(value, minValue, maxValue) {

/** @type {HTMLInputElement} */
let backgroundImageInput = document.querySelector('#backgroundImage');

/** @type {HTMLImageElement} */
let backgroundImagePreview = document.querySelector('#backgroundImagePreview');

/** @type {HTMLDivElement} */
let backgroundPrefsSection = document.querySelector('#backgroundPrefsSection');
Expand All @@ -65,37 +138,65 @@ function normalize(value, minValue, maxValue) {

/** @type {HTMLButtonElement} */
let setDefaultsButton = document.querySelector('#setDefaultsButton');

/** @type {HTMLButtonElement} */
let previewButton = document.querySelector('#previewButton');

/** @type {HTMLImageElement} */
let settingsPreviewImage = document.querySelector('#settingsPreviewImage');

/** @type {HTMLDivElement} */
let settingsPreviewSection = document.querySelector('#settingsPreviewSection');

/** @type {HTMLDivElement} */
let previewLoadingSpinner = document.querySelector('#previewLoadingSpinner');

/**
* Get settings configured on page (Not saved settings)
*
* @returns {UserPreferences}
*/
function getSettings() {
return {
showLineNumbers: lineNumbersCheckbox.checked.toString(),
backgroundColor: backgroundColorTextbox.value,
showBackground: showBackgroundCheckbox.checked.toString(),
backgroundPadding: normalize(backgroundPaddingInput.value, 1, 15),
backgroundImage: backgroundImageInput.value || '',
};
}

/**
* Populate form values from storage
*/
function populateValues() {
chrome.storage.sync.get((/** @type {UserPreferences} */ savedPrefs) => {
lineNumbersCheckbox.checked = savedPrefs.showLineNumbers === 'true';
lineNumbersCheckbox.checked = fromBooleanString(savedPrefs.showLineNumbers);
backgroundColorTextbox.value = savedPrefs.backgroundColor;
showBackgroundCheckbox.checked = savedPrefs.showBackground === 'true';
showBackgroundCheckbox.checked = fromBooleanString(savedPrefs.showBackground);
backgroundPaddingInput.value = savedPrefs.backgroundPadding;
backgroundImageInput.value = savedPrefs.backgroundImage || '';

if (backgroundColorPreview) {
backgroundColorPreview.style.background = backgroundColorTextbox.value;
}

if (!showBackgroundCheckbox.checked) {
if (showBackgroundCheckbox.checked) {
backgroundPrefsSection.classList.remove('d-none');
} else {
backgroundPrefsSection.classList.add('d-none');
}

if (backgroundImagePreview) {
backgroundImagePreview.src = backgroundImageInput.value;

if (!backgroundImageInput.value) {
backgroundImagePreview.parentElement.classList.add('d-none');
} else {
backgroundImagePreview.parentElement.classList.remove('d-none');
}
}
});
}

saveButton.addEventListener('click', () => {
/** @type {UserPreferences} */
const prefs = {
showLineNumbers: lineNumbersCheckbox.checked ? 'true' : 'false',
backgroundColor: backgroundColorTextbox.value,
showBackground: showBackgroundCheckbox.checked ? 'true' : 'false',
backgroundPadding: Math.max(Math.min(backgroundPaddingInput.value, 15), 1),
backgroundImage: backgroundImageInput.value || '',
};
const prefs = getSettings();
chrome.storage.sync.set(prefs, () => {
saveSuccessfulAlert.classList.remove('d-none');
window.setTimeout(() => {
Expand All @@ -118,19 +219,68 @@ function normalize(value, minValue, maxValue) {
populateValues();
});

backgroundColorTextbox.addEventListener('input', () => {
backgroundColorPreview.style.background = backgroundColorTextbox.value;
});

showBackgroundCheckbox.addEventListener('change', () => {
if (showBackgroundCheckbox.checked) {
backgroundPrefsSection.classList.remove('d-none');
} else {
backgroundPrefsSection.classList.add('d-none');
}
});

backgroundImageInput.addEventListener('change', () => {
if (backgroundImageInput.value) {
backgroundImagePreview.src = backgroundImageInput.value;
backgroundImagePreview.parentElement.classList.remove('d-none');
} else {
backgroundImagePreview.parentElement.classList.add('d-none')
}
});

previewButton.addEventListener('click', () => {
settingsPreviewSection.classList.remove('d-none');
generatePreview(settingsPreviewImage, previewLoadingSpinner, document.querySelector('#previewErrorAlert'), getSettings());
});

window.addEventListener('load', () => {
populateValues();
});
})();
})();

/**
* The source code snippet that will be
* used for generating the preview
*/
const previewCode = `/*
* 🔥🔥 Generated with Themeify 🔥🔥
*/
import java.util.*;
class FizzBuzz
{
public static void main(String args[])
{
int n = 100;
// loop for 100 times
for (int i=1; i<=n; i++)
{
if (i%15==0)
System.out.print("FizzBuzz"+" ");
// number divisible by 5, print 'Buzz'
// in place of the number
else if (i%5==0)
System.out.print("Buzz"+" ");
// number divisible by 3, print 'Fizz'
// in place of the number
else if (i%3==0)
System.out.print("Fizz"+" ");
// number divisible by 15(divisible by
// both 3 & 5), print 'FizzBuzz' in
// place of the number
else // print the numbers
System.out.print(i+" ");
}
}
}`;
37 changes: 31 additions & 6 deletions src/preferences.html
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,8 @@
</div>
</div>
<div class="card mt-4" id="backgroundPrefsSection">
<div class="card-header prefs-subheader text-white bg-secondary">Background Preferences</div>
<div class="card-header prefs-subheader text-white bg-secondary">Background Preferences</div>
<div class="card-body bg-light">
<!-- <div class="form-group">
<span class="font-weight-bold">Background Color Preview</span>
<div class="color-preview" id="backgroundColorPreview"></div>
</div> -->
<div class="form-group">
<div class="input-group">
<div class="input-group-prepend">
Expand Down Expand Up @@ -68,13 +64,42 @@
<input type="text" placeholder="Image URL (Optional)" class="form-control" id="backgroundImage">
</div>
</div>
<div class="form-group">
<div class="text-center">
<figure class="d-none">
<img class="border" alt="Background image" src="" id="backgroundImagePreview" height="200">
<figcaption>Background Image Preview</figcaption>
</figure>
</div>
</div>
</div>
</div>
<div class="card w-100 mt-4 d-none" id="settingsPreviewSection">
<div class="card-header bg-secondary text-white prefs-subheader">
Preview
</div>
<div class="card-body">
<div class="alert alert-info">
<i class="fas fa-info-circle"></i> This is a preview of how images generated from your current settings will look like
</div>
<div class="text-center d-none" id="previewLoadingSpinner">
<p><i class="fas fa-3x fa-spinner fa-spin text-muted"></i></p>
<p class="h4 text-muted">Generating preview, please wait</p>
</div>
<div class="text-center">
<img id="settingsPreviewImage" width="80%">
</div>
<div class="alert alert-danger d-none" id="previewErrorAlert">
<i class="fas fa-exclamation-circle"></i> The preview failed to load, please make sure you are connected to the internet.
</div>
</div>
</div>
<div class="alert alert-success mt-4 d-none" id="saveSuccessfulAlert">
<i class="fas fa-check-circle"></i> Your preferences are saved.
</div>
<div class="form-group text-right mt-4">
<button class="btn btn-dark float-left" type="button" id="setDefaultsButton"><i class="fas fa-home"></i> Set Defaults</button>
<button class="btn btn-info float-left" type="button" id="previewButton"><i class="fas fa-images"></i> Preview Settings</button>
<button class="ml-2 btn btn-dark float-left" type="button" id="setDefaultsButton"><i class="fas fa-home"></i> Set Defaults</button>
<button class="mr-2 btn btn-secondary" type="button" id="resetButton">Reset Changes <i class="fas fa-history"></i></button>
<button class="btn btn-primary" type="button" id="saveButton">Save Changes <i class="fas fa-save"></i></button>
</div>
Expand Down

0 comments on commit e43e0e2

Please sign in to comment.