Support for different color schemes
This commit is contained in:
parent
e616f23e4c
commit
116395766e
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
@ -3,5 +3,6 @@
|
||||
"extension/background.js": true,
|
||||
"extension/content.js": true,
|
||||
"extension/help.js": true,
|
||||
"extension/options.js": true,
|
||||
}
|
||||
}
|
@ -258,8 +258,9 @@ var overrides: LabelMap = null;
|
||||
|
||||
var accepted = false;
|
||||
var installationId: string = null;
|
||||
var theme: string = '';
|
||||
|
||||
browser.storage.local.get(['overrides', 'accepted', 'installationId'], v => {
|
||||
browser.storage.local.get(['overrides', 'accepted', 'installationId', 'theme'], v => {
|
||||
if (!v.installationId) {
|
||||
installationId = (Math.random() + '.' + Math.random() + '.' + Math.random()).replace(/\./g, '');
|
||||
browser.storage.local.set({ installationId: installationId });
|
||||
@ -269,6 +270,7 @@ browser.storage.local.get(['overrides', 'accepted', 'installationId'], v => {
|
||||
|
||||
accepted = v.accepted
|
||||
overrides = v.overrides || {}
|
||||
theme = v.theme;
|
||||
|
||||
const migration = overrides[MIGRATION] || 0;
|
||||
if (migration < CURRENT_VERSION) {
|
||||
@ -312,13 +314,26 @@ async function loadBloomFilter(name: LabelKind) {
|
||||
|
||||
|
||||
browser.runtime.onMessage.addListener<ShinigamiEyesMessage, ShinigamiEyesMessage | LabelMap>((message, sender, sendResponse) => {
|
||||
if (message.setTheme) {
|
||||
theme = message.setTheme;
|
||||
browser.storage.local.set({ theme: message.setTheme });
|
||||
chrome.tabs.query({}, function (tabs) {
|
||||
for (var i = 0; i < tabs.length; ++i) {
|
||||
try {
|
||||
browser.tabs.sendMessage(tabs[i].id, <ShinigamiEyesCommand>{ updateAllLabels: true });
|
||||
} catch (e) { }
|
||||
}
|
||||
});
|
||||
}
|
||||
if (message.acceptClicked !== undefined) {
|
||||
accepted = message.acceptClicked;
|
||||
browser.storage.local.set({ accepted: accepted });
|
||||
browser.tabs.remove(sender.tab.id);
|
||||
if (accepted && uncommittedResponse)
|
||||
saveLabel(uncommittedResponse)
|
||||
uncommittedResponse = null;
|
||||
}
|
||||
if (message.closeCallingTab) {
|
||||
browser.tabs.remove(sender.tab.id);
|
||||
return;
|
||||
}
|
||||
const response: LabelMap = {};
|
||||
@ -340,6 +355,7 @@ browser.runtime.onMessage.addListener<ShinigamiEyesMessage, ShinigamiEyesMessage
|
||||
if (bloomFilter.test(id)) response[id] = bloomFilter.name;
|
||||
}
|
||||
}
|
||||
response[':theme'] = <any>theme;
|
||||
sendResponse(response);
|
||||
});
|
||||
|
||||
@ -373,6 +389,8 @@ function createContextMenu(text: string, id: ContextMenuCommand) {
|
||||
createContextMenu('Mark as anti-trans', 'mark-transphobic');
|
||||
createContextMenu('Mark as t-friendly', 'mark-t-friendly');
|
||||
createContextMenu('Clear', 'mark-none');
|
||||
browser.contextMenus.create({ type: 'separator' });
|
||||
createContextMenu('Settings', 'options');
|
||||
createContextMenu('Help', 'help');
|
||||
|
||||
var uncommittedResponse: ShinigamiEyesSubmission = null;
|
||||
@ -440,12 +458,21 @@ function openHelp() {
|
||||
}
|
||||
|
||||
|
||||
function openOptions() {
|
||||
browser.tabs.create({
|
||||
url: browser.extension.getURL('options.html')
|
||||
})
|
||||
}
|
||||
|
||||
browser.contextMenus.onClicked.addListener(function (info, tab) {
|
||||
if (info.menuItemId == 'help') {
|
||||
openHelp();
|
||||
return;
|
||||
}
|
||||
if (info.menuItemId == 'options') {
|
||||
openOptions();
|
||||
return;
|
||||
}
|
||||
|
||||
const tabId = tab.id;
|
||||
const frameId = info.frameId;
|
||||
|
@ -1,5 +1,25 @@
|
||||
.assigned-label-transphobic, a.assigned-label-transphobic { color: #991515 !important; }
|
||||
.assigned-label-t-friendly, a.assigned-label-t-friendly { color: #77B91E !important; }
|
||||
body {
|
||||
--ShinigamiEyesTFriendly: #77B91E;
|
||||
--ShinigamiEyesTransphobic: #991515;
|
||||
}
|
||||
|
||||
.shinigami-eyes-theme-green-red-max {
|
||||
--ShinigamiEyesTFriendly: #00FF00;
|
||||
--ShinigamiEyesTransphobic: #FF0000;
|
||||
}
|
||||
|
||||
.shinigami-eyes-theme-purple-yellow {
|
||||
--ShinigamiEyesTFriendly: rgb(153, 0, 255);
|
||||
--ShinigamiEyesTransphobic: rgb(179, 152, 0);
|
||||
}
|
||||
|
||||
.shinigami-eyes-theme-cyan-orange {
|
||||
--ShinigamiEyesTFriendly: rgb(98, 161, 197);
|
||||
--ShinigamiEyesTransphobic: #FB6A4A;
|
||||
}
|
||||
|
||||
.assigned-label-transphobic, a.assigned-label-transphobic { color: var(--ShinigamiEyesTransphobic) !important; }
|
||||
.assigned-label-t-friendly, a.assigned-label-t-friendly { color: var(--ShinigamiEyesTFriendly) !important; }
|
||||
|
||||
.has-assigned-label * { color: inherit !important; }
|
||||
.shinigami-eyes-debug-snippet-highlight {
|
||||
|
@ -26,13 +26,13 @@ function fixupSiteStyles() {
|
||||
`);
|
||||
} else if (domainIs(hostname, 'tumblr.com')) {
|
||||
addStyleSheet(`
|
||||
.assigned-label-transphobic { outline: 2px solid #991515 !important; }
|
||||
.assigned-label-t-friendly { outline: 1px solid #77B91E !important; }
|
||||
.assigned-label-transphobic { outline: 2px solid var(--ShinigamiEyesTransphobic) !important; }
|
||||
.assigned-label-t-friendly { outline: 1px solid var(--ShinigamiEyesTFriendly) !important; }
|
||||
`);
|
||||
} else if (hostname.indexOf('wiki') != -1) {
|
||||
addStyleSheet(`
|
||||
.assigned-label-transphobic { outline: 1px solid #991515 !important; }
|
||||
.assigned-label-t-friendly { outline: 1px solid #77B91E !important; }
|
||||
.assigned-label-transphobic { outline: 1px solid var(--ShinigamiEyesTransphobic) !important; }
|
||||
.assigned-label-t-friendly { outline: 1px solid var(--ShinigamiEyesTFriendly) !important; }
|
||||
`);
|
||||
} else if (hostname == 'twitter.com') {
|
||||
myself = getIdentifier(<HTMLAnchorElement>document.querySelector('.DashUserDropdown-userInfo a'));
|
||||
@ -167,6 +167,7 @@ function updateAllLabels(refresh?: boolean) {
|
||||
}
|
||||
|
||||
var knownLabels: LabelMap = {};
|
||||
var currentlyAppliedTheme = '_none_';
|
||||
|
||||
var labelsToSolve: LabelToSolve[] = [];
|
||||
function solvePendingLabels() {
|
||||
@ -175,8 +176,14 @@ function solvePendingLabels() {
|
||||
var tosolve = labelsToSolve;
|
||||
labelsToSolve = [];
|
||||
browser.runtime.sendMessage<ShinigamiEyesCommand, LabelMap>({ ids: uniqueIdentifiers, myself: <string>myself }, (response: LabelMap) => {
|
||||
const theme = response[':theme'];
|
||||
if (theme != currentlyAppliedTheme) {
|
||||
if (currentlyAppliedTheme) document.body.classList.remove('shinigami-eyes-theme-' + currentlyAppliedTheme);
|
||||
if (theme) document.body.classList.add('shinigami-eyes-theme-' + theme);
|
||||
currentlyAppliedTheme = theme;
|
||||
}
|
||||
for (const item of tosolve) {
|
||||
var label = response[item.identifier];
|
||||
const label = response[item.identifier];
|
||||
knownLabels[item.identifier] = label || '';
|
||||
applyLabel(item.element, item.identifier);
|
||||
}
|
||||
|
4
extension/definitions.d.ts
vendored
4
extension/definitions.d.ts
vendored
@ -30,10 +30,12 @@ interface ShinigamiEyesCommand {
|
||||
myself?: string
|
||||
ids?: string[]
|
||||
updateAllLabels?: boolean
|
||||
closeCallingTab?: boolean
|
||||
setTheme?: string
|
||||
}
|
||||
type LabelMap = { [identifier: string]: LabelKind };
|
||||
|
||||
interface ShinigamiEyesMessage extends ShinigamiEyesSubmission, ShinigamiEyesCommand {
|
||||
}
|
||||
|
||||
type ContextMenuCommand = 'mark-t-friendly' | 'mark-transphobic' | 'mark-none' | 'help';
|
||||
type ContextMenuCommand = 'mark-t-friendly' | 'mark-transphobic' | 'mark-none' | 'help' | 'options';
|
||||
|
@ -7,9 +7,10 @@ body {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
||||
.assigned-label-transphobic { color: #991515 !important; }
|
||||
.assigned-label-t-friendly { color: #77B91E !important; }
|
||||
.assigned-label-unknown {
|
||||
color: rgb(56, 88, 152); /* Facebook default link color */
|
||||
cursor: help;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 40pt;
|
||||
@ -52,9 +53,8 @@ section {
|
||||
.section-faq {
|
||||
background-color: rgb(213, 183, 255);
|
||||
}
|
||||
.section-guidelines {
|
||||
.section-guidelines, .section-options {
|
||||
background-color: white;
|
||||
/*background-color: rgb(190, 245, 151);*/
|
||||
}
|
||||
|
||||
.section-footer {
|
||||
@ -123,4 +123,24 @@ section {
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
.website-checkbox {
|
||||
display: block;
|
||||
user-select: none;
|
||||
}
|
||||
.website-checkbox i {
|
||||
color: gray;
|
||||
}
|
||||
#theme-settings label {
|
||||
user-select: none;
|
||||
font-weight: bold;
|
||||
display: block;
|
||||
}
|
||||
|
||||
#save-button {
|
||||
font-weight: bold;
|
||||
background-color: rgb(108, 212, 76);
|
||||
}
|
||||
|
||||
label, button {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
<head>
|
||||
<title>Shinigami Eyes</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="content.css" rel="stylesheet">
|
||||
<link href="help.css" rel="stylesheet">
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
|
@ -1,8 +1,8 @@
|
||||
var browser: Browser = browser || chrome;
|
||||
|
||||
document.getElementById('cancelButton').addEventListener('click', () => {
|
||||
browser.runtime.sendMessage({ acceptClicked: false }, () => { });
|
||||
browser.runtime.sendMessage(<ShinigamiEyesCommand>{ acceptClicked: false, closeCallingTab: true }, () => { });
|
||||
})
|
||||
document.getElementById('acceptButton').addEventListener('click', () => {
|
||||
browser.runtime.sendMessage({ acceptClicked: true }, () => { });
|
||||
browser.runtime.sendMessage(<ShinigamiEyesCommand>{ acceptClicked: true, closeCallingTab: true }, () => { });
|
||||
})
|
@ -63,7 +63,7 @@
|
||||
]
|
||||
},
|
||||
"options_ui": {
|
||||
"page": "help.html",
|
||||
"page": "options.html",
|
||||
"open_in_tab": true
|
||||
},
|
||||
"permissions": [
|
||||
|
97
extension/options.html
Normal file
97
extension/options.html
Normal file
@ -0,0 +1,97 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Settings - Shinigami Eyes</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="help.css" rel="stylesheet">
|
||||
<link href="content.css" rel="stylesheet">
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
button {
|
||||
margin-top: 10px;
|
||||
padding: 10px 15px;
|
||||
font-size: 12pt;
|
||||
}
|
||||
|
||||
.section-top {
|
||||
background-color: rgb(213, 183, 255);
|
||||
}
|
||||
|
||||
.section-top h2 {
|
||||
margin: 5px !important;
|
||||
}
|
||||
|
||||
.section-confirmation {
|
||||
padding-bottom: 70px;
|
||||
padding-top: 40px;
|
||||
}
|
||||
|
||||
.footer {
|
||||
margin-top: 80px;
|
||||
font-size: 10pt;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="page-content">
|
||||
|
||||
<section class="section-top">
|
||||
<div class="section-inner">
|
||||
<h2>Shinigami Eyes settings</h2>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
<section class="section-options">
|
||||
<div class="section-inner">
|
||||
|
||||
<h3>Colors</h3>
|
||||
<div id="theme-settings">
|
||||
</div>
|
||||
|
||||
<!--
|
||||
<h3>Websites</h3>
|
||||
Color users and pages on the following websites:
|
||||
<br><br>
|
||||
<label class="website-checkbox"><input type="checkbox" data-site="disqus.com">Disqus <i>(embedded
|
||||
comments)</i></label>
|
||||
<label class="website-checkbox"><input type="checkbox" data-site="facebook.com">Facebook</label>
|
||||
<label class="website-checkbox"><input type="checkbox" data-site="medium.com">Medium</label>
|
||||
<label class="website-checkbox"><input type="checkbox" data-site="rationalwiki.org">RationalWiki
|
||||
<i>(topics)</i></label>
|
||||
<label class="website-checkbox"><input type="checkbox" data-site="reddit.com">Reddit</i></label>
|
||||
<label class="website-checkbox"><input type="checkbox" data-site="search-engines">Google, Bing,
|
||||
DuckDuckGo <i>(search results)</i></label>
|
||||
<label class="website-checkbox"><input type="checkbox" data-site="tumblr.com">Tumblr</label>
|
||||
<label class="website-checkbox"><input type="checkbox" data-site="twitter.com">Twitter</label>
|
||||
<label class="website-checkbox"><input type="checkbox" data-site="wikipedia.org">Wikipedia
|
||||
<i>(topics)</i></label>
|
||||
<label class="website-checkbox"><input type="checkbox" data-site="youtube.com">YouTube</label>
|
||||
-->
|
||||
|
||||
<h3>Guidelines</h3>
|
||||
Go to <a href="help.html" target="_blank">Guidelines</a> for an overview of what kind of content should be marked one
|
||||
way or the other.
|
||||
|
||||
<br><br>
|
||||
<button id="save-button">Save</button>
|
||||
<button id="cancel-button">Cancel</button>
|
||||
<br><br><br>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
<section class="section-footer">
|
||||
Don't forget to follow us on <a href="https://twitter.com/ShinigamiEyesT">Twitter</a> or <a
|
||||
href="https://www.facebook.com/ShinigamiEyesT">Facebook</a>!
|
||||
</section>
|
||||
|
||||
</div>
|
||||
<script src="options.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
27
extension/options.js
Normal file
27
extension/options.js
Normal file
@ -0,0 +1,27 @@
|
||||
var browser = browser || chrome;
|
||||
browser.storage.local.get(['theme'], obj => {
|
||||
var theme = obj.theme || 'green-red';
|
||||
var themeSettingsContainer = document.getElementById('theme-settings');
|
||||
[
|
||||
'green-red',
|
||||
'purple-yellow',
|
||||
'cyan-orange',
|
||||
].map(x => {
|
||||
themeSettingsContainer.insertAdjacentHTML('beforeend', `
|
||||
<label class="shinigami-eyes-theme shinigami-eyes-theme-${x}">
|
||||
<input type="radio" name="selected-theme" ${x == theme ? 'checked' : ''} data-theme="${x}">
|
||||
<span class="assigned-label-t-friendly">T-Friendly</span>,
|
||||
<span class="assigned-label-transphobic">Anti-trans</span>,
|
||||
<span class="assigned-label-unknown" title="Using Facebook as an example for unknown links.">Unknown (fb)</span>
|
||||
</label>
|
||||
`);
|
||||
});
|
||||
});
|
||||
document.getElementById('save-button').addEventListener('click', async () => {
|
||||
var theme = [...document.querySelectorAll('.shinigami-eyes-theme input')]
|
||||
.filter(x => x.checked)[0].dataset.theme;
|
||||
browser.runtime.sendMessage({ closeCallingTab: true, setTheme: theme }, () => { });
|
||||
});
|
||||
document.getElementById('cancel-button').addEventListener('click', async () => {
|
||||
browser.runtime.sendMessage({ closeCallingTab: true }, () => { });
|
||||
});
|
36
extension/options.ts
Normal file
36
extension/options.ts
Normal file
@ -0,0 +1,36 @@
|
||||
var browser: Browser = browser || chrome;
|
||||
|
||||
browser.storage.local.get(['theme'], obj => {
|
||||
|
||||
var theme: string = obj.theme || 'green-red';
|
||||
var themeSettingsContainer = document.getElementById('theme-settings');
|
||||
|
||||
[
|
||||
'green-red',
|
||||
'purple-yellow',
|
||||
'cyan-orange',
|
||||
].map(x => {
|
||||
themeSettingsContainer.insertAdjacentHTML('beforeend', `
|
||||
<label class="shinigami-eyes-theme shinigami-eyes-theme-${x}">
|
||||
<input type="radio" name="selected-theme" ${x == theme ? 'checked' : ''} data-theme="${x}">
|
||||
<span class="assigned-label-t-friendly">T-Friendly</span>,
|
||||
<span class="assigned-label-transphobic">Anti-trans</span>,
|
||||
<span class="assigned-label-unknown" title="Using Facebook as an example for unknown links.">Unknown (fb)</span>
|
||||
</label>
|
||||
`);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
document.getElementById('save-button').addEventListener('click', async () => {
|
||||
var theme = (<HTMLInputElement>
|
||||
[...document.querySelectorAll('.shinigami-eyes-theme input')]
|
||||
.filter(x => (<HTMLInputElement>x).checked)[0]
|
||||
).dataset.theme;
|
||||
browser.runtime.sendMessage(<ShinigamiEyesCommand>{ closeCallingTab: true, setTheme: theme }, () => { });
|
||||
});
|
||||
|
||||
|
||||
document.getElementById('cancel-button').addEventListener('click', async () => {
|
||||
browser.runtime.sendMessage(<ShinigamiEyesCommand>{ closeCallingTab: true }, () => { });
|
||||
});
|
14
extension/webextensions.d.ts
vendored
14
extension/webextensions.d.ts
vendored
@ -18,16 +18,18 @@ declare type Browser = {
|
||||
create(options: {
|
||||
url: string
|
||||
}): void
|
||||
query(query: {}, callback: (tabs: { id: number }[]) => void): void;
|
||||
}
|
||||
extension: {
|
||||
getURL(relativeUrl: string): string
|
||||
}
|
||||
contextMenus: {
|
||||
create(options: {
|
||||
id: string
|
||||
title: string
|
||||
contexts: 'link'[]
|
||||
targetUrlPatterns: string[]
|
||||
id?: string
|
||||
title?: string
|
||||
contexts?: 'link'[]
|
||||
targetUrlPatterns?: string[]
|
||||
type?: 'normal' | 'separator'
|
||||
}): void
|
||||
onClicked: {
|
||||
addListener(listener: (info: {
|
||||
@ -41,12 +43,12 @@ declare type Browser = {
|
||||
}
|
||||
}
|
||||
type MessageSender = {
|
||||
tab?: {id: number};
|
||||
tab?: { id: number };
|
||||
frameId?: number;
|
||||
id?: string;
|
||||
url?: string;
|
||||
tlsChannelId?: string;
|
||||
};
|
||||
};
|
||||
declare type BrowserStorage = {
|
||||
get(names: string[], callback: (obj: any) => void): void
|
||||
set(obj: { [name: string]: any }): void;
|
||||
|
Loading…
Reference in New Issue
Block a user