Browse Source

Support for different color schemes

pull/31/head
shinigami-eyes 3 years ago
parent
commit
116395766e
  1. 1
      .vscode/settings.json
  2. 31
      extension/background.ts
  3. 24
      extension/content.css
  4. 17
      extension/content.ts
  5. 4
      extension/definitions.d.ts
  6. 30
      extension/help.css
  7. 1
      extension/help.html
  8. 4
      extension/help.ts
  9. 2
      extension/manifest.json
  10. 97
      extension/options.html
  11. 27
      extension/options.js
  12. 36
      extension/options.ts
  13. 14
      extension/webextensions.d.ts

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,
}
}

31
extension/background.ts

@ -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;

24
extension/content.css

@ -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 {

17
extension/content.ts

@ -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

@ -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';

30
extension/help.css

@ -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;
}

1
extension/help.html

@ -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>

4
extension/help.ts

@ -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 }, () => { });
})

2
extension/manifest.json

@ -63,7 +63,7 @@
]
},
"options_ui": {
"page": "help.html",
"page": "options.html",
"open_in_tab": true
},
"permissions": [

97
extension/options.html

@ -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

@ -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

@ -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

@ -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…
Cancel
Save