Formatting popup

This commit is contained in:
Jean Viscogliosi-Pate 2024-12-19 23:25:13 -08:00
parent 4ed39f9e23
commit 404f1a92a3
4 changed files with 283 additions and 335 deletions

View File

@ -9,10 +9,10 @@
"browser_action": { "browser_action": {
"default_title": "MetamorPOV", "default_title": "MetamorPOV",
"default_icon": { "default_icon": {
"32": "icons/icon-32.png", "32": "img/mpov-32.png",
"48": "icons/icon-48.png" "48": "img/mpov-48.png"
}, },
"default_popup": "popup.html" "default_popup": "popup/popup.html"
}, },
"permissions": [ "permissions": [
"storage", "storage",
@ -20,12 +20,12 @@
], ],
"icons": { "icons": {
"16": "icons/icon-16.png", "16": "img/mpov-16.png",
"32": "icons/icon-32.png", "32": "img/mpov-32.png",
"48": "icons/icon-48.png", "48": "img/mpov-48.png",
"64": "icons/icon-64.png", "64": "img/mpov-64.png",
"96": "icons/icon-96.png", "96": "img/mpov-96.png",
"128": "icons/icon-128.png" "128": "img/mpov-128.png"
}, },
"content_scripts": [ "content_scripts": [
@ -39,9 +39,8 @@
] ]
} }
], ],
"incognito": "split",
"background": { "background": {
"page": "popup.html" "page": "popup/popup.html"
}, },
"homepage_url": "https://git.viscogliosi-pate.com/jean/metamorpov" "homepage_url": "https://git.viscogliosi-pate.com/jean/metamorpov"
} }

View File

@ -1,100 +1,88 @@
:root {
--background-color: white;
--text-color: black;
}
body { body {
background-color: white; background-color: var(--background-color);
color: #2C3531; color: var(--text-color);
width: 380px; width: 350px;
font-family: 'Inter', sans-serif; padding-left: 10px;
padding:10px; padding-right: 10px;
margin: 8px; font-family: 'Inter', sans-serif;
font-size: 12pt;
} }
h1 { #hostname {
font-size: 16px; font-size: 14pt;
font-weight: 400;
text-align: center;
} }
#display-enabled {
display: grid;
grid-template-columns: 1fr 2fr;
}
#display-enabled img {
width: 50%;
justify-self: center;
align-self: center;
cursor: pointer;
}
#display-enabled h2 {
font-size: 14pt;
font-weight: 400;
margin-right: 15%;
}
#display-features {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px;
text-align: center;
}
#display-features img {
width: 50%;
}
#display-features p {
margin-top: 0;
}
button {
display: flex;
justify-content: center;
align-items: center;
border: 0;
border-radius: 30px;
width: 100%;
font-size: 12pt;
padding: 6px;
margin-top: 6px;
margin-bottom: 6px;
gap: 8px;
text-align: center;
cursor: pointer;
}
button:hover {
transition-duration: 0.3s;
}
ul {
text-align: right;
list-style: none;
}
a{ a{
color: #51A99C; color: var(--text-color);
transition-duration: 0.5s; text-decoration: none;
transition-duration: 0.3s;
} }
a:hover{ a:hover{
color: #1E7669; text-decoration: underline;
}
label *:not([type="checkbox"]){
display:block;
}
.other-words input:not([type="checkbox"]){
margin-top:0.5em;
width:100%;
}
.other-words .other, .other-words .replace-with{
width:98%;
}
.other-words .change{
margin-right:0;
}
.change {
border-color: rgb(49, 47, 47);
border-width: 1px;
border-radius: 0.3em;
transition-duration: 0.3s;
}
.change:hover {
background-color: #84DCCF;
cursor: pointer;
}
#clear-name, #refresh-replacements{
margin-top:0.5em;
margin-bottom: 0.5em;
width:96%;
}
#refresh-replacements {
font-size: 1.005em;
background-color: #EF626C;
border-radius: 0.5em;
color: white;
border-color: rgba(0, 0, 0, 0);
transition-duration: 0.3s;
}
#refresh-replacements:hover {
background-color: #D64953;
cursor: pointer;
}
input[type="text"]{
width:70%;
}
.strikethrough{
text-decoration: line-through;
}
.one-saved-item:hover{
background-color: #e74c3c;
color: white;
cursor: pointer;
}
.saved-items-list-wrapper{
height:100px;
overflow: auto;
}
details {
margin-top: 0.8em;
}
summary {
cursor: pointer;
}
input[type="button"]{
margin-top: 0.8em;
margin-bottom: 0.8em;
}
input[type="checkbox"]:hover{
cursor:pointer;
}
#src-code {
font-size: 0.8em;
text-align: right;
} }

View File

@ -1,69 +1,52 @@
<!DOCTYPE html> <!DOCTYPE html>
<meta charset="UTF-8"> <meta charset="UTF-8">
<html> <html>
<head> <head>
<link href='popup.css' rel='stylesheet' type='text/css'> <link href='popup.css' rel='stylesheet' type='text/css'>
<script src="popup.js" type="text/javascript"></script> <script src="popup.js" type="text/javascript"></script>
</head> </head>
<body>
<h1>Website name here</h1>
<h1>MetamorPOV is <b>TODO</b> for this website</h1>
<form id="change-name-form"> <body>
<input type="text" id="change-name-form-text"/> <main>
<input type="submit" class="change" value="Change"/> <h1 id="hostname">TODO</h1>
</form>
<details> <div id="display-enabled">
<summary>Need to replace something other than Y/N?</summary> <img id="toggle" src="../img/toggle-on.svg" alt="Toggle"/>
<p><small>This change will go away when you refresh/go to another page unless you check the box next to "Store this replacement".</small></p> <h2>MetamorPOV is <b>TODO</b> for this website</h2>
<p> </div>
<form id="replace-other-words-form" class="other-words">
<label>
<span>Value (e.g. L/N, E/C, etc):</span>
<input type="text" id="replace-word" class="other"/>
</label>
<label>
<input type="checkbox" id="is-case-sensitive">Case sensitive
</label>
<br><br>
<label>
<span>Replace with:</span>
<input type="text" id="replace-with" class="replace-with"/>
</label>
<br>
<label>
<input type="checkbox" id="is-perm">Store this replacement
</label>
<input type="submit" class="change" value="Change">
</form>
</p>
</details>
<details>
<summary id="show-saved">Stored Replacements</summary>
<p><small>To remove, simply click on a replacement. To change, re-enter in the previous section.</small></p>
<div class="saved-items-list-wrapper">
<ul id="saved-items-list">
</ul>
</div>
</details>
<div> <div id="display-features">
<details> <div id="yn-usage">
<summary>⚙️ Settings</summary> <img src="../img/check.svg" alt="Check"/>
<div><input type="checkbox" id="enable-observer"> Auto-detect page changes <small>(Wattpad support)</small><br></div> <p>Y/n is used on this page</p>
<div><input type="checkbox" id="pause"> Pause extension on "<span id="this-url"></span>"<br></div> </div>
<input type="checkbox" id="deactivate"> Deactivate extension
</details>
</div>
<input type="button" id="refresh-replacements" value="Refresh replacements"/>
<ul class="links"> <div id="prn-usage">
<li><a href="https://git.viscogliosi-pate.com/jean/metamorpov/wiki" target="_blank">How to write for MetamorPOV</a></li> <img src="../img/check.svg" alt="Check"/>
<li><a href="https://git.viscogliosi-pate.com/jean/metamorpov/issues" target="_blank">Report an issue</a></li> <p>prn/ is used on this page</p>
<li><a href="https://git.viscogliosi-pate.com/jean/metamorpov" target="_blank">Source code</a></li> </div>
</ul>
</body> <div id="pov-usage">
<img src="../img/check.svg" alt="Check"/>
<p>pov/ is used on this page</p>
</div>
</div>
</main>
<button id="configure">
<img src="../img/configure.svg" alt=""/>
Configure name, pronouns, and POV
</button>
<button id="refresh">
<img src="../img/refresh.svg" alt=""/>
Refresh replacements
</button>
<ul class="links">
<li><a href="https://git.viscogliosi-pate.com/jean/metamorpov/wiki" target="_blank">How to write for MetamorPOV</a></li>
<li><a href="https://git.viscogliosi-pate.com/jean/metamorpov/issues" target="_blank">Report an issue</a></li>
<li><a href="https://git.viscogliosi-pate.com/jean/metamorpov" target="_blank">Source code</a></li>
</ul>
</body>
</html> </html>

View File

@ -1,236 +1,214 @@
DEACTIVATE_KEY = 'deactivate-this-extension-pls-interactive-fics-yalla-bina'; DEACTIVATE_KEY = 'deactivate-this-extension-pls-interactive-fics-yalla-bina';
MUTATION_OBSERVER_KEY = 'observe-this-dom-pls-interactive-fics-yalla-bina'; MUTATION_OBSERVER_KEY = 'observe-this-dom-pls-interactive-fics-yalla-bina';
PAUSED_KEY = 'pause-this-domain-pls-interactive-fics-yalla-bina';
document.addEventListener('DOMContentLoaded', function () { document.addEventListener('DOMContentLoaded', function () {
// event listeners // event listeners
document.getElementById('change-name-form').addEventListener('submit', changeName) document.getElementById('change-name-form').addEventListener('submit', changeName)
document.getElementById('replace-other-words-form').addEventListener('submit', replaceOther) document.getElementById('replace-other-words-form').addEventListener('submit', replaceOther)
document.getElementById('show-saved').addEventListener('click', loadSaved) document.getElementById('show-saved').addEventListener('click', loadSaved)
document.getElementById('refresh-replacements').addEventListener('click', refreshReplacements) document.getElementById('refresh-replacements').addEventListener('click', refreshReplacements)
document.getElementById('deactivate').addEventListener('click', toggleDeactivate) document.getElementById('enable-observer').addEventListener('click', toggleMutationObserver)
document.getElementById('enable-observer').addEventListener('click', toggleMutationObserver) document.getElementById('toggle').addEventListener('click', togglePauseDomain)
document.getElementById('pause').addEventListener('click', togglePauseDomain)
// set settings buttons // set settings buttons
setDeactivateKey() setMutationObserverKey()
setMutationObserverKey() setPauseDomainKey()
setPauseDomainKey()
addToucanBanner()
}); });
const changeName = () => { const changeName = () => {
const person = document.getElementById('change-name-form-text').value const person = document.getElementById('change-name-form-text').value
if (person) { if (person) {
chrome.storage.sync.set({'person': person}, chrome.tabs.reload()) chrome.storage.sync.set({'person': person}, chrome.tabs.reload())
} }
} }
const replaceOther = () => { const replaceOther = () => {
const input_word = document.getElementById('replace-word').value const input_word = document.getElementById('replace-word').value
const replacement = document.getElementById('replace-with').value const replacement = document.getElementById('replace-with').value
const is_case_sensitive = document.getElementById('is-case-sensitive').checked const is_case_sensitive = document.getElementById('is-case-sensitive').checked
if (input_word && replacement) { if (input_word && replacement) {
if (document.getElementById('is-perm').checked) { if (document.getElementById('is-perm').checked) {
const obj = {} const obj = {}
obj[input_word] = replacement obj[input_word] = replacement
obj[`${input_word}_case_sensitive`] = is_case_sensitive obj[`${input_word}_case_sensitive`] = is_case_sensitive
chrome.storage.sync.set(obj) chrome.storage.sync.set(obj)
} }
chrome.tabs.query({ active: true, currentWindow: true }, tabs => { chrome.tabs.query({ active: true, currentWindow: true }, tabs => {
chrome.tabs.sendMessage( chrome.tabs.sendMessage(
tabs[0].id, tabs[0].id,
{ {
input_word: input_word, input_word: input_word,
replace_value: replacement, replace_value: replacement,
case_sensitive: is_case_sensitive case_sensitive: is_case_sensitive
}) })
}) })
} }
} }
const refreshReplacements = () => { const refreshReplacements = () => {
chrome.tabs.query({ active: true, currentWindow: true }, tabs => { chrome.tabs.query({ active: true, currentWindow: true }, tabs => {
chrome.tabs.sendMessage( chrome.tabs.sendMessage(
tabs[0].id, tabs[0].id,
{ {
refresh: true refresh: true
}) })
}) })
} }
const loadSaved = () => { const loadSaved = () => {
const list = document.getElementById('saved-items-list') const list = document.getElementById('saved-items-list')
list.innerHTML = '' list.innerHTML = ''
chrome.storage.sync.get(null, loadSavedItemsWrapper(false)) chrome.storage.sync.get(null, loadSavedItemsWrapper(false))
chrome.storage.local.get(null, loadSavedItemsWrapper(true)) chrome.storage.local.get(null, loadSavedItemsWrapper(true))
} }
const loadSavedItemsWrapper = isLocal => items => loadSavedItems(items, isLocal) const loadSavedItemsWrapper = isLocal => items => loadSavedItems(items, isLocal)
const loadSavedItems = (items, isLocal) => { const loadSavedItems = (items, isLocal) => {
const list = document.getElementById('saved-items-list') const list = document.getElementById('saved-items-list')
for (var key in items) { for (var key in items) {
if (key !== DEACTIVATE_KEY && key !== MUTATION_OBSERVER_KEY && key !== PAUSED_KEY && !key.endsWith('_case_sensitive')) { if (key !== DEACTIVATE_KEY && key !== MUTATION_OBSERVER_KEY && key !== PAUSED_KEY && !key.endsWith('_case_sensitive')) {
const label = key === 'person' ? 'Y/N' : key const label = key === 'person' ? 'Y/N' : key
const case_sensitive = !!items[`${key}_case_sensitive`] const case_sensitive = !!items[`${key}_case_sensitive`]
const case_sensitive_string = case_sensitive ? 'case sensitive' : 'not case sensitive' const case_sensitive_string = case_sensitive ? 'case sensitive' : 'not case sensitive'
const representative = `${label} -> ${items[key]} (${case_sensitive_string})` const representative = `${label} -> ${items[key]} (${case_sensitive_string})`
const list_item = createListItem(key, representative, 'one-saved-item', isLocal) const list_item = createListItem(key, representative, 'one-saved-item', isLocal)
list.appendChild(list_item) list.appendChild(list_item)
} }
} }
} }
const createListItem = (id, text, className, isLocal) => { const createListItem = (id, text, className, isLocal) => {
const text_node = document.createTextNode(text) const text_node = document.createTextNode(text)
const list_node = document.createElement('LI') const list_node = document.createElement('LI')
list_node.appendChild(text_node) list_node.appendChild(text_node)
list_node.className = className list_node.className = className
list_node.id = id list_node.id = id
list_node.addEventListener('click', () => { list_node.addEventListener('click', () => {
if (isLocal) { if (isLocal) {
chrome.storage.local.remove(id) chrome.storage.local.remove(id)
} else { } else {
chrome.storage.sync.remove(id) chrome.storage.sync.remove(id)
} }
list_node.className += ' strikethrough' list_node.className += ' strikethrough'
}) })
return list_node return list_node
} }
const setDeactivateKey = () => { const setDeactivateKey = () => {
chrome.storage.sync.get(DEACTIVATE_KEY, obj => { chrome.storage.sync.get(DEACTIVATE_KEY, obj => {
const is_deactivated = obj[DEACTIVATE_KEY] const is_deactivated = obj[DEACTIVATE_KEY]
toggleDeactivateLabel(is_deactivated) toggleDeactivateLabel(is_deactivated)
if (is_deactivated) { if (is_deactivated) {
const other_elements = document.getElementsByClassName('fade-when-deactivate') const other_elements = document.getElementsByClassName('fade-when-deactivate')
const deactivate_only_elements = document.getElementsByClassName('fade-when-deactivate-only') const deactivate_only_elements = document.getElementsByClassName('fade-when-deactivate-only')
Array.from([...other_elements, ...deactivate_only_elements]).forEach(element => { Array.from([...other_elements, ...deactivate_only_elements]).forEach(element => {
element.style.opacity = '0.5' element.style.opacity = '0.5'
}) })
const input_elements = document.getElementsByTagName('INPUT') const input_elements = document.getElementsByTagName('INPUT')
Array.from(input_elements).forEach(input => { Array.from(input_elements).forEach(input => {
if (input.id !== 'deactivate') { if (input.id !== 'deactivate') {
input.disabled = 'disabled' input.disabled = 'disabled'
} }
}) })
} }
}) })
} }
const setMutationObserverKey = () => { const setMutationObserverKey = () => {
chrome.storage.sync.get(MUTATION_OBSERVER_KEY, obj => { chrome.storage.sync.get(MUTATION_OBSERVER_KEY, obj => {
const is_enabled = obj[MUTATION_OBSERVER_KEY] const is_enabled = obj[MUTATION_OBSERVER_KEY]
toggleMutationObserverLabel(is_enabled) toggleMutationObserverLabel(is_enabled)
}) })
} }
const setPauseDomainKey = () => { const setPauseDomainKey = () => {
chrome.tabs.query({ active: true, currentWindow: true }, tabs => { chrome.tabs.query({ active: true, currentWindow: true }, tabs => {
const hostname = new URL(tabs[0].url).hostname const hostname = new URL(tabs[0].url).hostname
document.getElementById('this-url').innerHTML = hostname document.getElementById('this-url').innerHTML = hostname
const storage_key = {} const storage_key = {}
storage_key[PAUSED_KEY] = [] storage_key[PAUSED_KEY] = []
chrome.storage.sync.get(storage_key, obj => { chrome.storage.sync.get(storage_key, obj => {
const hostnames = obj[PAUSED_KEY] const hostnames = obj[PAUSED_KEY]
const is_paused = hostnames.indexOf(hostname) !== -1 const is_paused = hostnames.indexOf(hostname) !== -1
togglePauseDomainLabel(is_paused) togglePauseDomainLabel(is_paused)
if (is_paused) { if (is_paused) {
const other_elements = document.getElementsByClassName('fade-when-deactivate') const other_elements = document.getElementsByClassName('fade-when-deactivate')
const pause_only_other_elements = document.getElementsByClassName('fade-when-pause') const pause_only_other_elements = document.getElementsByClassName('fade-when-pause')
Array.from([...other_elements, ...pause_only_other_elements]).forEach(element => { Array.from([...other_elements, ...pause_only_other_elements]).forEach(element => {
element.style.opacity = '0.5' element.style.opacity = '0.5'
}) })
const input_elements = document.getElementsByTagName('INPUT') const input_elements = document.getElementsByTagName('INPUT')
Array.from(input_elements).forEach(input => { Array.from(input_elements).forEach(input => {
if (input.id !== 'pause' && input.id !== 'deactivate') { if (input.id !== 'pause' && input.id !== 'deactivate') {
input.disabled = 'disabled' input.disabled = 'disabled'
} }
}) })
} }
}) })
}) })
} }
const toggleDeactivateLabel = (isDeactivated) => { const toggleDeactivateLabel = (isDeactivated) => {
document.getElementById('deactivate').checked = isDeactivated; document.getElementById('deactivate').checked = isDeactivated;
} }
const toggleMutationObserverLabel = (isEnabled) => { const toggleMutationObserverLabel = (isEnabled) => {
document.getElementById('enable-observer').checked = isEnabled; document.getElementById('enable-observer').checked = isEnabled;
} }
const togglePauseDomainLabel = (isPaused) => { const togglePauseDomainLabel = (isPaused) => {
document.getElementById('pause').checked = isPaused; document.getElementById('pause').checked = isPaused;
}
const toggleDeactivate = () => {
chrome.storage.sync.get(DEACTIVATE_KEY, obj => {
const was_deactivated = obj[DEACTIVATE_KEY]
toggleDeactivateLabel(!was_deactivated)
if (was_deactivated) {
chrome.storage.sync.remove(DEACTIVATE_KEY)
} else {
const new_object = {}
new_object[DEACTIVATE_KEY] = true
chrome.storage.sync.set(new_object)
}
chrome.tabs.reload()
window.close()
})
} }
const toggleMutationObserver = () => { const toggleMutationObserver = () => {
chrome.storage.sync.get(MUTATION_OBSERVER_KEY, obj => { chrome.storage.sync.get(MUTATION_OBSERVER_KEY, obj => {
const was_enabled = obj[MUTATION_OBSERVER_KEY] const was_enabled = obj[MUTATION_OBSERVER_KEY]
if (was_enabled) { if (was_enabled) {
chrome.storage.sync.remove(MUTATION_OBSERVER_KEY) chrome.storage.sync.remove(MUTATION_OBSERVER_KEY)
} else { } else {
const new_object = {} const new_object = {}
new_object[MUTATION_OBSERVER_KEY] = true new_object[MUTATION_OBSERVER_KEY] = true
chrome.storage.sync.set(new_object) chrome.storage.sync.set(new_object)
} }
chrome.tabs.reload() chrome.tabs.reload()
}) })
} }
const togglePauseDomain = () => { const togglePauseDomain = () => {
chrome.tabs.query({ active: true, currentWindow: true }, tabs => { chrome.tabs.query({ active: true, currentWindow: true }, tabs => {
const hostname = new URL(tabs[0].url).hostname const hostname = new URL(tabs[0].url).hostname
const storage_key = {} const storage_key = {}
storage_key[PAUSED_KEY] = [] storage_key[PAUSED_KEY] = []
chrome.storage.sync.get(storage_key, obj => { chrome.storage.sync.get(storage_key, obj => {
const hostnames = obj[PAUSED_KEY] const hostnames = obj[PAUSED_KEY]
const was_paused = hostnames.indexOf(hostname) !== -1 const was_paused = hostnames.indexOf(hostname) !== -1
var new_hostnames; var new_hostnames;
if (was_paused) { if (was_paused) {
new_hostnames = hostnames.filter(h => h !== hostname) new_hostnames = hostnames.filter(h => h !== hostname)
} else { } else {
new_hostnames = hostnames new_hostnames = hostnames
new_hostnames.push(hostname) new_hostnames.push(hostname)
} }
const new_obj = {} const new_obj = {}
new_obj[PAUSED_KEY] = new_hostnames new_obj[PAUSED_KEY] = new_hostnames
chrome.storage.sync.set(new_obj) chrome.storage.sync.set(new_obj)
chrome.tabs.reload() chrome.tabs.reload()
window.close() window.close()
}) })
}) })
} }