Use OS and color theme specific icons for a toggle button in JPM - firefox-addon-sdk

In Firefox, depending of the theme and OS, the icons are differents. Example:
On Linux:
On Windows 10:
(source: saranitus.com)
Lightweight theme:
Notice how the icons are darker on Windows 10 and white on a personas (Pretty obvious).
The thing is, my addon adds a new button (a togglebutton, to be exact) to the Firefox menu, and for now only haves a static icon.
I know there was an addon made on JPM (or CFX, pretty much the same thing) that achieved this behavior, but I don't remember which one, nor do I remember how.
How can I make my icon change depending of the OS and theme?

Found it. It was Mozilla's Addon Compatiblity Reporter.
Add this to your startup code:
var {Cc, Ci, Cu} = require("chrome");
if ( Cc["#mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator).getMostRecentWindow("navigator:browser").navigator.oscpu.indexOf("Windows NT 10.0") > -1 ) {
var icontype = "Modern";
}
else if ( Cc["#mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator).getMostRecentWindow("navigator:browser").navigator.oscpu.indexOf("Windows NT 6.3") > -1 || Cc["#mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator).getMostRecentWindow("navigator:browser").navigator.oscpu.indexOf("Windows NT 6.2") > -1) {
var icontype = "Metro";
}
else if ( Cc["#mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator).getMostRecentWindow("navigator:browser").navigator.oscpu.indexOf("Windows NT 6.1") > -1 || Cc["#mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator).getMostRecentWindow("navigator:browser").navigator.oscpu.indexOf("Windows NT 6.0") > -1) {
var icontype = "Aero";
}
else if ( Cc["#mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator).getMostRecentWindow("navigator:browser").navigator.oscpu.indexOf("Mac OS X") > -1 ) {
var icontype = "Aqua";
}
else {
var icontype = "Linux";
}
And then, when declaring your icons, simply type that:
icon: {
"16": "./" + icontype + "_16.png",
"32": "./" + icontype + "_32.png"
},
So when you created an icon for Mac OS X, drop it as data/Aqua_16.png and it should work.

Related

What is the name of the element that github copilot uses to highlighting text?

I would like to make a control similar to the used by github copilot. I mean highlighting the proposed text. Live share extension uses a very similar approach. What is the name of this control?
Control in live preview extension:
Control in copilot extension:
I guess it could be TextEditorDecorationType? However, I do not know how to style it so that the author is absolutely positioned :/
You can create a similar experience using Text Editor Decorators. These decorators allow you to use custom style patterns for any text in a document (including foreground and background colors).
The text highlighting examples that you have visualized above, are simply adding a a background color to a span of text that has been selected by a user, or suggested by an extension.
As an example: if you wanted to add custom highlighting for console.log:
Then you could use the following:
import * as vscode from 'vscode'
const decorationType = vscode.window.createTextEditorDecorationType({
backgroundColor: 'green',
border: '2px solid white',
})
export function activate(context: vscode.ExtensionContext) {
vscode.workspace.onWillSaveTextDocument(event => {
const openEditor = vscode.window.visibleTextEditors.filter(
editor => editor.document.uri === event.document.uri
)[0]
decorate(openEditor)
})
}
function decorate(editor: vscode.TextEditor) {
let sourceCode = editor.document.getText()
let regex = /(console\.log)/
let decorationsArray: vscode.DecorationOptions[] = []
const sourceCodeArr = sourceCode.split('\n')
for (let line = 0; line < sourceCodeArr.length; line++) {
let match = sourceCodeArr[line].match(regex)
if (match !== null && match.index !== undefined) {
let range = new vscode.Range(
new vscode.Position(line, match.index),
new vscode.Position(line, match.index + match[1].length)
)
let decoration = { range }
decorationsArray.push(decoration)
}
}
editor.setDecorations(decorationType, decorationsArray)
}
Reference Link

How to dynamically change gutter icons in VSCode with TextEditor.setDecorations()

I am getting some odd behavior when updating gutter icons in VSCode using TextEditor.setDecorations() https://code.visualstudio.com/api/references/vscode-api#TextEditor.
On activate of my VSCode extension the class below is instantiated and it's constructor called which "one-time" creates 3 TextEditorDecorationType's https://code.visualstudio.com/api/references/vscode-api#TextEditorDecorationType, one for each state that a test result can be in represented by a NONE, PASS, FAIL icon and finally triggerUpdateDecorations() is called to collect the current globalResults within 3 arrays and set the gutter icons with vscode.window.activeTextEditor.setDecorations()
So far everything works as expected. No tests have been run and every test shown in the editor is updated with a NONE gutter icon.
Now as each test is run in the editor, on completion, triggerUpdateDecorations() is called once again to collect results and update the gutter icons.
If there are for example 10 tests in the editor, each with a NONE gutter icon, if I run a single test that test correctly updates with either a PASS or FAIL gutter icon. This behavior repeats itself for all subsequent tests run, except for the last one. The last test run remains set with its NONE gutter icon. It's not tied to a specific test as I can jump around and the behavior follows the last test run.
I've tried adding a dummy NONE icon to a random place in the gutter not tied to a test and that allows all gutter icons tied to a test to be updated with PASS or FAIL gutter icons.
I've been experimenting a lot to try and solve this and can't seem to find the root cause. Greatly appreciate any insights on how to solve this.
Note some of this code stems from the VSCode Samples shown here
https://github.com/microsoft/vscode-extension-samples/blob/main/decorator-sample/src/extension.ts#L58
import * as path from 'path';
import * as vscode from 'vscode';
class ProviderDecorations
{
private timeout: NodeJS.Timeout;
private context: vscode.ExtensionContext;
private activeEditor: vscode.TextEditor;
private readonly decorationNone: vscode.TextEditorDecorationType;
private readonly decorationPass: vscode.TextEditorDecorationType;
private readonly decorationFail: vscode.TextEditorDecorationType;
constructor(context: vscode.ExtensionContext)
{
this.context = context;
this.activeEditor = vscode.window.activeTextEditor;
this.decorationNone = this.getDecorationType(ENTRY_STATE.NONE);
this.decorationPass = this.getDecorationType(ENTRY_STATE.PASS);
this.decorationFail = this.getDecorationType(ENTRY_STATE.FAIL);
vscode.window.onDidChangeActiveTextEditor(editor =>
{
this.activeEditor = editor;
if (editor)
{
this.triggerUpdateDecorations();
}
}, null, this.context.subscriptions);
vscode.workspace.onDidChangeTextDocument(event =>
{
if (this.activeEditor && event.document === this.activeEditor.document)
{
this.triggerUpdateDecorations();
}
}, null, this.context.subscriptions);
this.triggerUpdateDecorations();
}
public updateDecorations()
{
if (!this.activeEditor)
{
return;
}
let rangeNone = [];
let rangePass = [];
let rangeFail = [];
globalResults.forEach((result) =>
{
let range = new vscode.Range(result.line, 0, result.line, 0);
switch (result.state)
{
case ENTRY_STATE.NONE:
rangeNone.push({ range });
break;
case ENTRY_STATE.PASS:
rangePass.push({ range });
break;
case ENTRY_STATE.FAIL:
rangeFail.push({ range });
break;
}
});
if (rangePass.length > 0)
{
this.activeEditor.setDecorations(this.decorationPass, rangePass);
}
if (rangeFail.length > 0)
{
this.activeEditor.setDecorations(this.decorationFail, rangeFail);
}
if (rangeNone.length > 0)
{
this.activeEditor.setDecorations(this.decorationNone, rangeNone);
}
}
private getDecorationType(state: ENTRY_STATE): vscode.TextEditorDecorationType
{
let icon = 'none.svg';
if (state === ENTRY_STATE.PASS)
{
icon = 'pass.svg';
}
else if (state === ENTRY_STATE.FAIL)
{
icon = 'fail.svg';
}
const decorationType = vscode.window.createTextEditorDecorationType(
{
light:
{
gutterIconPath: path.join(__dirname, '..', 'resources', 'light', icon),
gutterIconSize: '85%',
},
dark:
{
gutterIconPath: path.join(__dirname, '..', 'resources', 'dark', icon),
gutterIconSize: '85%'
}
});
return decorationType;
}
public triggerUpdateDecorations()
{
if (this.timeout)
{
clearTimeout(this.timeout);
this.timeout = undefined;
}
this.timeout = setTimeout(() =>
{
this.updateDecorations();
}, 250);
}
}
export default ProviderDecorations;
You never clear a Decorator type, remove the if (rangePass.length > 0) parts
this.activeEditor.setDecorations(this.decorationPass, rangePass);
this.activeEditor.setDecorations(this.decorationFail, rangeFail);
this.activeEditor.setDecorations(this.decorationNone, rangeNone);

How can I change the breakpoint for MegaMenu in Magento 2?

I am using the MegaMenu in Magento 2. The default breakpoint for the menu to collapse is 1024px / 1025px. The smaller version is a simple list of categories, sliding in from the right side of the screen. The bigger version is a dropdown with categories to hover.
How can I change the breakpoint to 1194px / 1195px?
I tried modifying JS and CSS but it just broke the menu. I could also not find an option in the admin panel.
I don't own the extension but i read the javascript and in the file of demo website:
https://mega-menu-m2-ce.magento-demo.amasty.com/static/version1586867535/frontend/Magento/luma/en_US/Amasty_MegaMenu/js/open-type.js
Line number 35:
_create: function () {
var self = this,
isMobile = $(window).width() <= 1024 ? 1 : 0,
options = self.options,
openType = options.openType,
isHamburger = +options.hamburgerStatus;
There is the breakpoint (1024). Maybe if you change that to 1194 or 1195?
_create: function () {
var self = this,
isMobile = $(window).width() <= 1194 ? 1 : 0,
options = self.options,
openType = options.openType,
isHamburger = +options.hamburgerStatus;
Override that setting with js. or override the whole js file? Hope that helps.

TinyMCE custom buttons only appear in "Visual" mode. How to make them appear in "Text" mode too

The functions below I'm using to add my custom buttons to the TinyMCE. The buttons are displaying fine while in the "Visual" mode. However, when I switch over to the "Text" mode, I'm not seeing them.
In the script below, I've commented out the lines that filter for rich_editing mode. What am I missing?
function addbuttons() {
global $page_handle;
// Don't bother doing this stuff if the current user lacks permissions
if ( !current_user_can('edit_posts') && !current_user_can('edit_pages') )
return;
// Add only in Rich Editor mode
//if ( get_user_option('rich_editing') == 'true') {
$svr_uri = $_SERVER['REQUEST_URI'];
if ( strstr($svr_uri, 'post.php') || strstr($svr_uri, 'post-new.php') || strstr($svr_uri, 'page.php') || strstr($svr_uri, 'page-new.php') || strstr($svr_uri, $page_handle) ) {
add_filter("mce_external_plugins", array (&$this, 'add_tinymce_plugin' ), 5);
add_filter('mce_buttons', array (&$this, 'register_button' ), 5);
add_filter('mce_external_languages', array (&$this, 'add_tinymce_langs_path'));
}
//}
}
function register_button($buttons) {
array_push($buttons, 'separator', 'nextpage' , 'CustomCodes' );
return $buttons;
}
function add_tinymce_plugin($plugin_array) {
$plugin_array['CustomCodes'] = $this->path . 'plugins/custom/editor_plugin_src.js';
return $plugin_array;
}
function add_tinymce_langs_path($plugin_array) {
// Load the TinyMCE language file
$plugin_array[$this->pluginname] = CB_ADMIN . '/tinymce/langs.php';
return $plugin_array;
}

Creating a fake image for a CKEditor custom Plugin

I am developing a plugin for video embedding, I put this code when the plugin dialog OK button is clicked.
var embedCode =
'<iframe title="YouTube video player" class="youtube-player" type="text/html"' +
width="' + width + '" height="' + height + '" src="http://www.youtube.com/embed/' + textField + '?rel=0"' +
frameborder="0" width="620" height="200" style="width:' + width + 'px; height:' + height + 'px">' +
'</iframe>';
this.getParentEditor().insertHtml(embedCode);
Now when double click on the iframe in the editor open the iframe properties dialog not my plugin dialog.
How I can develop a fake image for my custom plugin.
I have found a solution for it.
Ckeditor make fake elements from the code generated by the plugins. When the editor loads it takes the code and convert it to fake elements and the default editing is worked on that fake elements the code for it will be defined in the
afterInit : function( editor )
{
function of the the editor and will be called in on OK event of the edior
onOk : function()
{
var embedCode = updatePreview( this,true );
var newFakeImage = editor.createFakeElement( embedCode, 'cke_audio', 'audio', true );
The Code for the fake element example is the following, I have created for an audio embed code plugin
afterInit : function( editor )
{
function createFakeElement( editor, realElement )
{
return editor.createFakeParserElement( realElement, 'cke_audio', 'audio', true );
}
var dataProcessor = editor.dataProcessor,
dataFilter = dataProcessor && dataProcessor.dataFilter;
if ( dataFilter )
{
dataFilter.addRules(
{
elements :
{
'div' : function( element )
{
//alert("here");
var attributes = element.attributes;
if( attributes.class == 'audio' ){
//alert("here");
return createFakeElement( editor, element );
}
return null;
}
}
},
5);
}
}