Skip to content

Commit

Permalink
Add pop-up settings menu (with live preview 🤘)
Browse files Browse the repository at this point in the history
  • Loading branch information
dannvix committed Mar 14, 2018
1 parent 19ebbe6 commit 33173c2
Show file tree
Hide file tree
Showing 8 changed files with 542 additions and 114 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "NflxMultiSubs",
"description": "Bilingual Subtitles & Enhanced Experiences for Netflix",
"author": "Dan Chen",
"version": "1.5.4",
"version": "1.6.0",
"license": "MIT",
"private": true,
"scripts": {
Expand Down
117 changes: 99 additions & 18 deletions src/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,45 +11,126 @@ chrome.webRequest.onBeforeRequest.addListener(details => {

////////////////////////////////////////////////////////////////////////////////

// TODO: dispatch configs to injected agent on Netflix player page (realtime preview)
chrome.runtime.onConnectExternal.addListener(port => {
let tabId;
if (port.sender && port.sender.tab) {
tabId = port.sender.tab.id;
}
console.log(`Connected: ${tabId} (tab)`);

// saturate our icon
const kDefaultSettings = {
centerLinePos: 0.5,
topBaselinePos: 0.15,
btmBaselinePos: 0.85,
primaryImageScale: 0.75,
primaryImageOpacity: 0.85,
primaryTextScale: 0.95,
primaryTextOpacity: 0.85,
secondaryImageScale: 0.5,
secondaryImageOpacity: 0.85,
secondaryTextScale: 1.0,
secondaryTextStroke: 2.0,
secondaryTextOpacity: 0.85,
};

let gSettings = Object.assign({}, kDefaultSettings);

chrome.storage.local.get(['settings'], (result) => {
console.dir('Loaded: settings=', result.settings);
gSettings = result.settings || gSettings;
});

function saveSettings() {
chrome.storage.local.set({ settings: gSettings }, () => {
console.log('Settings: saved into local storage');
});
}

// ----------------------------------------------------------------------------

function saturateActionIconForTab(tabId) {
chrome.browserAction.setIcon({
tabId: tabId,
path: {
'16': 'icon16.png',
'32': 'icon32.png',
},
});
}

function desaturateActionIconForTab(tabId) {
chrome.browserAction.setIcon({
tabId: tabId,
path: {
'16': 'icon16-gray.png',
'32': 'icon32-gray.png',
},
});
}

// -----------------------------------------------------------------------------

let gExtPorts = {}; // tabId -> msgPort; for config dispatching
function dispatchSettings() {
const keys = Object.keys(gExtPorts);
keys.map(k => gExtPorts[k]).forEach(port => {
try {
port.postMessage({ settings: gSettings });
}
catch (err) {
console.error('Error: cannot dispatch settings,', err);
}
});
}

chrome.runtime.onConnectExternal.addListener(port => {
const tabId = port.sender && port.sender.tab && port.sender.tab.id;

gExtPorts[tabId] = port;
saturateActionIconForTab(tabId);
console.log(`Connected: ${tabId} (tab)`);

port.postMessage({ settings: gSettings });

port.onDisconnect.addListener(() => {
delete gExtPorts[tabId];
desaturateActionIconForTab(tabId);
console.log(`Disconnected: ${tabId} (tab)`);

// reset the icon to grayscale
chrome.browserAction.setIcon({
tabId: tabId,
path: {
'16': 'icon16-gray.png',
'32': 'icon32-gray.png',
},
});
});
});


// -----------------------------------------------------------------------------

// TODO: receive configs from our pop-up/options page (realtime preview)
// return true if valid; otherwise return false
function validateSettings(settings) {
return true; // TODO
}


chrome.runtime.onConnect.addListener(port => {
const portName = port.name;
console.log(`Connected: ${portName} (internal)`);

if (portName === 'settings') {
port.postMessage({ settings: gSettings });

port.onMessage.addListener(msg => {
console.dir('Received: settings=', msg.settings);
if (!msg.settings) {
gSettings = Object.assign({}, kDefaultSettings);
port.postMessage({ settings: gSettings });
}
else {
let settings = Object.assign({}, gSettings);
settings = Object.assign(settings, msg.settings);
if (!validateSettings(settings)) {
gSettings = Object.assign({}, kDefaultSettings);
port.postMessage({ settings: gSettings });
}
else {
gSettings = settings;
}
}
saveSettings();
dispatchSettings();
});
}

port.onDisconnect.addListener(() => {
console.log(`Disconnected: ${portName} (internal)`);
});
Expand Down
5 changes: 0 additions & 5 deletions src/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,6 @@
"default_popup": "settings.html"
},

"options_ui": {
"page": "settings.html",
"chrome_style": true
},

"icons": {
"16": "icon16.png",
"32": "icon32.png",
Expand Down
20 changes: 14 additions & 6 deletions src/nflxmultisubs.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ let gSubtitles = [], gSubtitleMenu;
let gMsgPort, gRendererLoop;
let gVideoRatio = (1080 / 1920);

// TODO: sync this with configs coming from pop-up/options config UI
let gRenderOptions = {
// FIXME: dedup default settings with background script
const kDefaultSettings = {
centerLinePos: 0.5,
topBaselinePos: 0.15,
btmBaselinePos: 0.85,
Expand All @@ -31,6 +31,7 @@ let gRenderOptions = {
secondaryTextStroke: 2.0,
secondaryTextOpacity: 0.85,
};
let gRenderOptions = Object.assign({}, kDefaultSettings);


////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -426,8 +427,8 @@ class PrimaryImageTransformer {
constructor() {
}

transform(svgElem, controlsActive, forceRender) {
const selector = forceRender ? 'image' : 'image:not(.nflxmultisubs-scaled)';
transform(svgElem, controlsActive, forced) {
const selector = forced ? 'image' : 'image:not(.nflxmultisubs-scaled)';
const images = svgElem.querySelectorAll(selector);
if (images.length > 0) {
const viewBox = svgElem.getAttributeNS(null, 'viewBox');
Expand Down Expand Up @@ -475,7 +476,7 @@ class PrimaryTextTransformer {
this.lastScaledPrimaryTextContent = undefined;
}

transform(divElem, controlsActive, forceRender) {
transform(divElem, controlsActive, forced) {
let parentNode = divElem.parentNode;
if (!parentNode.classList.contains('nflxmultisubs-primary-wrapper')) {
// let's use `<style>` + `!imporant` to outrun the offical player...
Expand All @@ -496,7 +497,7 @@ class PrimaryTextTransformer {
if (!container) return;

const textContent = container.textContent;
if (this.lastScaledPrimaryTextContent === textContent && !forceRender) return;
if (this.lastScaledPrimaryTextContent === textContent && !forced) return;
this.lastScaledPrimaryTextContent = textContent;

const style = parentNode.querySelector('style');
Expand Down Expand Up @@ -695,6 +696,13 @@ class NflxMultiSubsManager {
const extensionId = window.__nflxMultiSubsExtId;
gMsgPort = chrome.runtime.connect(extensionId);
console.log(`Linked: ${extensionId}`);

gMsgPort.onMessage.addListener((msg) => {
if (msg.settings) {
gRenderOptions = Object.assign({}, msg.settings);
gRendererLoop && gRendererLoop.setRenderDirty();
}
});
}
catch (err) {
console.warn('Error: cannot talk to background,', err);
Expand Down
Loading

0 comments on commit 33173c2

Please sign in to comment.