Skip to content

Commit

Permalink
Moved content to extension
Browse files Browse the repository at this point in the history
  • Loading branch information
Ludonope committed Nov 20, 2021
1 parent a12c371 commit 5ef4482
Show file tree
Hide file tree
Showing 15 changed files with 1,401 additions and 23 deletions.
File renamed without changes.
File renamed without changes.
File renamed without changes.
4 changes: 3 additions & 1 deletion gulpfile.js → extension/gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ const zip = require('gulp-zip');
const included_modules = [
'node_modules/monaco-editor/min/**/*',
'node_modules/monaco-editor/LICENSE',
'node_modules/requirejs/require.js'
'node_modules/requirejs/require.js',
'node_modules/portal-unleashed/dist/unleash.js',
'node_modules/portal-unleashed/dist/unleash.d.ts'
];
const test_modules = [
'node_modules/jasmine-core/lib/jasmine-core/boot.js',
Expand Down
6 changes: 4 additions & 2 deletions package.json → extension/package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "BFPortalUnleashed",
"name": "bfportal-unleashed-extension",
"version": "0.0.1",
"description": "A Battlefield Portal scripting tool",
"repository": {
Expand All @@ -18,6 +18,8 @@
"homepage": "https://github.com/Ludonope/BFPortalUnleashed#readme",
"dependencies": {
"monaco-editor": "~0.20.0",
"portal-unleashed": "../portal-unleashed-generator/portal-unleashed/",
"portal-unleashed-generator": "../portal-unleashed-generator/",
"requirejs": "^2.3.6"
},
"devDependencies": {
Expand All @@ -31,4 +33,4 @@
"jasmine": "^3.6.1",
"sinon-chrome": "^3.0.1"
}
}
}
134 changes: 134 additions & 0 deletions extension/src/background/background.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
'use strict';

const tabIdToContentType = {};

// Populate the extension's context menu with relevant items. Right-click on the
// page action icon to open it.
chrome.storage.local.get(['disabled', 'theme'], function(state) {
const theme = state['theme'];

addNormalMenu(getDisabledStateLabel(state['disabled']), 'disabled');
addMenuSeparator('separator1');
addRadioMenu('Light Theme', 'vs', theme === 'vs');
addRadioMenu('Dark Theme', 'vs-dark', theme === 'vs-dark');
addRadioMenu('High Contrast Theme', 'hc-black', theme === 'hc-black');
addMenuSeparator('separator2');
addNormalMenu('Homepage', 'homepage');
addNormalMenu('License', 'license');
addMenuSeparator('separator3');
});

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
console.log('message:', request)
if (typeof sender !== 'undefined') {
if (request.action === 'show_page_action') {
chrome.pageAction.show(sender.tab.id);
} else if (request.action === 'get_content_type') {
sendResponse({
contentType: tabIdToContentType[sender.tab.id]
});
} else if (request.action === 'download_content') {
chrome.tabs.query({
active: true,
currentWindow: true
},
function(tabs) {
// Encode contents and prepare for local download.
const blob = new Blob([request.content], { type: 'text/plain' });
const downloadUrl = URL.createObjectURL(blob);
const tabUrl = tabs[0].url;
chrome.downloads.download({
url: downloadUrl,
filename: tabUrl.substr(tabUrl.lastIndexOf('/') + 1)
});
}
);
}
}
});

// Store the content-types headers, which will help us select the editor's
// language. Note: this feature requires a persistent background in
// manifest.json until declarativeWebRequest goes stable or support for event
// pages is added to webRequest.
chrome.webRequest.onHeadersReceived.addListener(
function(details) {
for (const header of details.responseHeaders) {
if (header.name.toLowerCase() === 'content-type') {
tabIdToContentType[details.tabId] = header.value;
return;
}
}
}, {
urls: ['<all_urls>'],
types: ['main_frame']
}, ['responseHeaders']
);

chrome.contextMenus.onClicked.addListener(function(event) {
if (event.menuItemId === 'homepage') {
window.open('https://github.com/Ludonope/BFPortalUnleashed');
} else if (event.menuItemId === 'license') {
window.open('https://github.com/Ludonope/BFPortalUnleashed/blob/master/LICENSE');
} else if (event.menuItemId === 'disabled') {
chrome.storage.local.get('disabled', function(state) {
const newState = state['disabled'] === 'true' ? 'false' : 'true';
// Persist new state and update action label in context menu.
chrome.storage.local.set({
disabled: newState
});
chrome.contextMenus.update('disabled', {
title: getDisabledStateLabel(newState)
});
});
}
});

chrome.runtime.onInstalled.addListener(function(details) {
if (details.reason === 'update') {
chrome.notifications.create('update_notification', {
title: 'Extension update',
message: `Portal Unleashed updated to version ${chrome.runtime.getManifest().version}`,
type: 'basic',
iconUrl: 'images/portal_unchained_logo.png'
});
}
});

function selectTheme(info, tab) {
chrome.storage.local.set({
theme: info.menuItemId
});
chrome.tabs.sendMessage(tab.id, { action: 'set_theme', content: info.menuItemId });
}

function addNormalMenu(menuTitle, menuId) {
chrome.contextMenus.create({
title: menuTitle,
id: menuId,
contexts: ['page_action']
});
}

function addRadioMenu(menuTitle, menuId, checked) {
chrome.contextMenus.create({
title: menuTitle,
type: 'radio',
checked: checked,
id: menuId,
contexts: ['page_action'],
onclick: selectTheme
});
}

function addMenuSeparator(separatorId) {
chrome.contextMenus.create({
type: 'separator',
id: separatorId,
contexts: ['page_action']
});
}

function getDisabledStateLabel(state) {
return `${state === 'true' ? 'Enable' : 'Disable'} extension`;
}
144 changes: 144 additions & 0 deletions extension/src/content/content.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
'use strict';

if (shouldLaunchEditor(document.body)) {
const interval = setInterval(() => {
const app = document.getElementsByClassName('app')[0];
if (app) {
clearInterval(interval);
prepareEditorLaunch(app);
}
}, 100);
}

const req = document.createElement('script')
req.src = 'require.js'
document.body.appendChild(req)

function prepareEditorLaunch(app) {
// Hide contents to avoid flickering while the rest of the script loads
// asynchronously.
// element.style.setProperty('display', 'none', '');
chrome.storage.local.get('disabled', function(state) {
if (state['disabled'] === 'true') {
// element.style.removeProperty('display');
} else {
listenToEditorMessages(app);
toggleEditor(app);
}
});
// Notify the background to show the page action for the current tab.
chrome.runtime.sendMessage({
action: 'show_page_action'
});
}

function shouldLaunchEditor(body) {
// Only handle documents with a unique <pre> element.
return true;
// return body && body.getElementsByTagName('pre').length === 1 && body.childNodes.length === 1;
}

function listenToEditorMessages(element) {
window.addEventListener('message', function(message) {
// Wait for editor frame to signal that it has loaded.
if (message.data === 'loaded') {
// element.parentNode.removeChild(element);
const response = {
code: `import * as portal from 'portal-unleashed'
import { logic, eventPayloads, gameplay } from 'portal-unleashed'
const mod = new portal.Mod()
mod.onPlayerDied({
name: 'New Rule',
conditions: [
logic.Equals(portal.MeleeAlexandria.Knife_BF3, eventPayloads.EventPlayer()),
logic.Equals(portal.Factions.Alexandria_RU, eventPayloads.EventPlayer()),
],
actions: (player, otherPlayer) => {
return [
portal.player.EnableAllInputRestrictions(player, new portal.BBoolean(true)),
gameplay.UnspawnPlayer(otherPlayer),
logic.While(portal.logic.Equals(portal.Factions.Alexandria_RU, player), [
portal.player.EnableAllInputRestrictions(player, new portal.BBoolean(false)),
gameplay.UnspawnPlayer(otherPlayer)
])
]
}
})`,
filename: 'main.ts'
};
message.source.postMessage(response, chrome.runtime.getURL(''));
} else if (message.data.startsWith('run+')) {
console.log(message)
let source = `import * as __portal from '${chrome.runtime.getURL('../lib/portal-unleashed/dist/unleash.js')}'\n` +
message.data.substring(4).replaceAll("portal-unleashed", chrome.runtime.getURL('../lib/portal-unleashed/dist/unleash.js'))
var s = document.createElement('script');
s.type = 'module'
s.innerHTML = `
import prettier from "https://unpkg.com/[email protected]/esm/standalone.mjs";
import parserBabel from "https://unpkg.com/[email protected]/esm/parser-babel.mjs";
import * as __portal from '${chrome.runtime.getURL('../lib/portal-unleashed/dist/unleash.js')}'
const code = prettier.format(__portal.preprocess(${JSON.stringify(source)}), {
parser: "babel",
plugins: [parserBabel],
})
console.log('generated code:', code)
var s = document.createElement('script');
s.type = 'module'
s.innerHTML = \`\${code}
setTimeout(function() {
_Blockly.Xml.clearWorkspaceAndLoadFromXml(_Blockly.Xml.textToDom(mod.toXML()), _Blockly.mainWorkspace)
}, 0);\`
s.onload = function() {
this.remove()
};
(document.head || document.documentElement).appendChild(s);
`;
s.onload = function() {
this.remove();
};
(document.head || document.documentElement).appendChild(s);
}
});
}

function getFilename() {
let filename = location.href;
// Remove path.
let index = filename.lastIndexOf('/');
if (index !== -1) {
filename = filename.substring(index + 1);
}
// Remove fragment identifier.
index = filename.indexOf('#');
if (index !== -1) {
filename = filename.substring(0, index);
}
// Remove query parameters.
index = filename.indexOf('?');
if (index !== -1) {
filename = filename.substring(0, index);
}
return filename;
}

function toggleEditor(app) {
const checkMonaco = document.getElementById('unleashed-editor');
console.log(`app ${app}`);
console.log(`checkMonaco ${checkMonaco}`);
if (checkMonaco) {
app.style.gridTemplateColumns = '1fr';
app.removeChild(checkMonaco);
} else {
app.style.gridTemplateColumns = '1fr 1fr';

const iframe = document.createElement('iframe');
iframe.id = 'unleashed-editor';
iframe.setAttribute('src', chrome.runtime.getURL('editor/editor.html'));
iframe.setAttribute('style', 'border: 0px none; width: 100%; height: 100%; grid-row: 1;');
app.appendChild(iframe);
}
}
15 changes: 15 additions & 0 deletions extension/src/editor/editor.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>

<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
</head>

<body>
<div id="container" style="position: fixed; top: 0; left: 0; right: 0; bottom: 0"></div>
<script src="../lib/monaco-editor/min/vs/loader.js"></script>
<script src="../lib/requirejs/require.js"></script>
<script src="editor.js"></script>
</body>

</html>
Loading

0 comments on commit 5ef4482

Please sign in to comment.