switch to bulma and remove pure css, improve the messaging

Cette révision appartient à :
arabcoders
2025-05-23 01:45:24 +03:00
Parent 7d32fd8340
révision bf8c0f3d44
7 fichiers modifiés avec 25031 ajouts et 173 suppressions
+31 -38
Voir le fichier
@@ -49,17 +49,17 @@ const getOption = async key => {
} }
} }
const sendRequest = async user_url => { const sendRequest = async (path, data) => {
const instanceUrl = await getOption("instance_url"); let instanceUrl = await getOption("instance_url");
if (!instanceUrl) { if (!instanceUrl) {
notify('YTPTube instance url not configured.'); throw new Error('YTPTube instance url not configured.');
return; }
if (instanceUrl.endsWith('/')) {
instanceUrl = instanceUrl.slice(0, -1);
} }
let headers = {}; let headers = {};
let data = {
url: user_url,
}
const auth_username = await getOption("username"); const auth_username = await getOption("username");
const auth_password = await getOption("password"); const auth_password = await getOption("password");
@@ -67,41 +67,34 @@ const sendRequest = async user_url => {
headers['Authorization'] = 'Basic ' + btoa(`${auth_username}:${auth_password}`); headers['Authorization'] = 'Basic ' + btoa(`${auth_username}:${auth_password}`);
} }
const preset = await getOption("preset"); const url = new URL(instanceUrl);
if (preset) { url.pathname = path;
data['preset'] = preset;
}
const template = await getOption("template");
if (template) {
data['template'] = template;
}
const folder = await getOption("folder");
if (folder) {
data['folder'] = folder;
}
console.debug(`Sending to '${instanceUrl}'.`, data, headers.length > 0 ? 'with auth header' : 'without auth header'); console.debug(`Sending to '${instanceUrl}'.`, data, headers.length > 0 ? 'with auth header' : 'without auth header');
const url = new URL(instanceUrl); let opts = {method: data.length > 0 ? 'POST' : 'GET', headers: headers};
url.pathname = '/api/history';
const req = await fetch(url, { if (data) {
method: 'POST', opts.headers['Content-Type'] = 'application/json';
headers: { opts.body = JSON.stringify(data);
...headers,
'Content-Type': 'application/json',
},
body: JSON.stringify(data)
});
if (200 === req.status) {
notify('Request sent successfully.');
return
} }
notify(`Failed to send request. '${req.status}: ${req.statusText}'.`); const req = await fetch(url, opts);
return {status: req.status, statusText: req.statusText, data: req};
};
const sendUrl = async user_url => {
try {
const data = await sendRequest('/api/history', {url: user_url});
if (200 === data.status) {
notify('Request sent successfully.');
return
}
notify(`Failed to send request. '${data.status}: ${data.statusText}'.`);
}catch (e) {
console.error(e);
notify(`Failed to send request. '${e.message}'.`);
}
}; };
chrome.contextMenus.onClicked.addListener(async (info, _) => { chrome.contextMenus.onClicked.addListener(async (info, _) => {
@@ -113,7 +106,7 @@ chrome.contextMenus.onClicked.addListener(async (info, _) => {
return; return;
} }
await sendRequest(info.linkUrl); await sendUrl(info.linkUrl);
}); });
chrome.runtime.onMessage.addListener(async (message) => { chrome.runtime.onMessage.addListener(async (message) => {
@@ -128,7 +121,7 @@ chrome.runtime.onMessage.addListener(async (message) => {
return; return;
} }
await sendRequest(url); await sendUrl(url);
}); });
+24826
Voir le fichier
Fichier diff supprimé car celui-ci est trop grand Voir la Diff
-11
Voir le fichier
Diff de fichier supprimé car une ou plusieurs lignes sont trop longues
+4 -1
Voir le fichier
@@ -7,7 +7,7 @@
] ]
}, },
"name": "YTPTube Extension", "name": "YTPTube Extension",
"version": "0.0.3", "version": "1.0.0",
"description": "Add URLs to YTPTube instance", "description": "Add URLs to YTPTube instance",
"permissions": [ "permissions": [
"activeTab", "activeTab",
@@ -41,5 +41,8 @@
"id": "ytptube@arabcoders.org", "id": "ytptube@arabcoders.org",
"strict_min_version": "113.0" "strict_min_version": "113.0"
} }
},
"content_security_policy": {
"extension_pages": "script-src 'self'; object-src 'self';"
} }
} }
+66 -59
Voir le fichier
@@ -4,75 +4,82 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>Options menu for YTPTube Extension</title> <title>Options menu for YTPTube Extension</title>
<link rel="stylesheet" href="css/pure.css"/> <link rel="stylesheet" href="css/bulma.css"/>
<style>
@media (prefers-color-scheme: dark) {
body {
color: white;
background-color: #19191c;
}
input {
background-color: #19191c;
color: white;
}
fieldset > legend {
color: white !important;
}
}
</style>
</head> </head>
<body> <body class="container">
<form id="ytptube_options" class="pure-form pure-form-stacked"> <div class="columns is-multiline">
<fieldset style="padding:1em"> <div class="column is-12">
<legend>Settings</legend> <form id="ytptube_options" class="content m-1">
<div class="field">
<label class="label" for="instance_url">YTPTube URL</label>
<div class="control">
<input type="text" class="input" id="instance_url" placeholder="https://ytptube.example.org">
</div>
<span class="help">URL to your YTPTube instance</span>
</div>
<div class="pure-control-group"> <div class="field">
<label for="instance_url">YTPTube URL</label> <label class="label" for="preset">Preset</label>
<input type="text" class="pure-input-1" id="instance_url" placeholder="https://ytptube.example.org"> <div class="control">
<span class="pure-form-message">URL to your YTPTube instance</span><br> <input type="text" class="input" id="preset" placeholder="Leave empty to use default preset.">
</div> </div>
<span class="help">Preset to use for the URL</span>
</div>
<div class="pure-control-group"> <div class="field">
<label for="preset">Preset</label> <label class="label" for="template">Output Template</label>
<input type="text" class="pure-input-1" id="preset" placeholder="Leave empty to use default preset."> <div class="control">
<span class="pure-form-message">Preset to use for the URL</span><br> <input type="text" class="input" id="template"
</div> placeholder="Leave empty to use default output template.">
</div>
<span class="help">Filename template to use for the output file.</span>
</div>
<div class="pure-control-group"> <div class="field">
<label for="template">Output Template</label> <label class="label" for="folder">Download Folder</label>
<input type="text" class="pure-input-1" id="template" <div class="control">
placeholder="Leave empty to use default output template."> <input type="text" class="input" id="folder"
<span class="pure-form-message">Filename template to use for the output file.</span><br> placeholder="Leave empty to use default download path.">
</div> </div>
<span class="help">Where to save downloaded files.</span>
</div>
<div class="pure-control-group"> <div class="field">
<label for="folder">Download Folder</label> <label class="label" for="username">Auth Username</label>
<input type="text" class="pure-input-1" id="folder" placeholder="Leave empty to use default download path."> <div class="control">
<span class="pure-form-message">Where to save downloaded files.</span><br> <input type="text" class="input" id="username" placeholder="Auth username">
</div> </div>
<span class="help">Leave empty if you have not configured a authentication.</span>
</div>
<div class="pure-control-group"> <div class="field">
<label for="username">Auth Username</label> <label class="label" for="password">Auth Password</label>
<input type="text" class="pure-input-1" id="username" <div class="control">
placeholder="Leave empty if you have not configured a authentication."> <input type="password" class="input" id="password" placeholder="Auth Password">
<span class="pure-form-message">Username to use for authentication.</span><br> </div>
</div> <span class="help">Leave empty if you have not configured a authentication.</span>
</div>
<div class="pure-control-group"> <label class="checkbox mb-1" for="showContextMenu">
<label for="password">Auth Password</label> <input type="checkbox" id="showContextMenu"/> Show context menu in supported sites
<input type="password" class="pure-input-1" id="password" </label>
placeholder="Leave empty if you have not configured a authentication.">
<span class="pure-form-message">Password to use for authentication.</span><br>
</div>
<label for="showContextMenu"> <div class="field has-text-danger">
<input type="checkbox" id="showContextMenu"/> Show context menu in supported sites <p id="error_msg"></p>
</label><br> </div>
<button class="pure-button pure-input-1 pure-button-primary" type="submit">Save</button> <div class="field is-grouped">
</fieldset> <div class="control is-expanded">
</form> <button class="button is-primary is-fullwidth" type="submit">Save</button>
</div>
<div class="control is-expanded">
<button class="button is-info is-fullwidth" type="button" id="test_config">Test</button>
</div>
</div>
</form>
</div>
</div>
<script src="options.js"></script> <script src="options.js"></script>
</body> </body>
+71 -9
Voir le fichier
@@ -3,10 +3,63 @@
const str_keys = ["instance_url", "preset", "template", "folder", "username", "password"] const str_keys = ["instance_url", "preset", "template", "folder", "username", "password"]
if (typeof chrome === 'undefined') { if (typeof chrome === 'undefined') {
// noinspection JSUnusedLocalSymbols
let chrome = browser let chrome = browser
} }
const notify = (message, no_inline) => {
if (!no_inline) {
document.querySelector('#error_msg').innerText = message;
}
chrome.notifications.create({
"type": "basic",
"iconUrl": chrome.runtime.getURL("icons/icon-128.png"),
"title": 'YTPTube Extension',
"message": message,
});
}
const testConfig = async () => {
document.querySelector('#error_msg').innerText = "";
let instance_url = document.querySelector("#instance_url").value;
if (!instance_url) {
notify("Please enter a valid YTPTube instance URL.");
return false;
}
if (instance_url.endsWith('/')) {
instance_url = instance_url.slice(0, -1);
}
let username = document.querySelector("#username").value;
let password = document.querySelector("#password").value;
let headers = {}
if (username && password) {
headers['Authorization'] = 'Basic ' + btoa(username + ':' + password);
}
try {
const req = await fetch(`${instance_url}/api/ping`, {
method: 'GET',
headers: headers
});
if (200 === req.status) {
notify("Connection successful.", true);
return true;
}
const json = await req.json();
notify(json.error ?? "Unknown error.");
} catch (e) {
notify("Error: " + e);
}
return false;
}
document.addEventListener("DOMContentLoaded", () => { document.addEventListener("DOMContentLoaded", () => {
function onError(error) { function onError(error) {
console.log(`Error: ${error}`); console.log(`Error: ${error}`);
@@ -19,9 +72,13 @@ document.addEventListener("DOMContentLoaded", () => {
chrome.storage.sync.get("showContextMenu").then(r => document.querySelector("#showContextMenu").checked = r.showContextMenu || false); chrome.storage.sync.get("showContextMenu").then(r => document.querySelector("#showContextMenu").checked = r.showContextMenu || false);
}); });
document.getElementById("ytptube_options").addEventListener("submit", (e) => { document.getElementById("ytptube_options").addEventListener("submit", async e => {
e.preventDefault(); e.preventDefault();
if (false === (await testConfig())) {
return false;
}
let showContextMenu = document.querySelector("#showContextMenu").checked; let showContextMenu = document.querySelector("#showContextMenu").checked;
let data = {presets: {presets: ['default'], last_updated: 0}} let data = {presets: {presets: ['default'], last_updated: 0}}
@@ -31,12 +88,17 @@ document.getElementById("ytptube_options").addEventListener("submit", (e) => {
chrome.storage.sync.set(data); chrome.storage.sync.set(data);
chrome.contextMenus.update("send-to-ytptube", {visible: showContextMenu}); chrome.contextMenus.update("send-to-ytptube", {visible: showContextMenu});
chrome.notifications.create({ notify("Options saved.", true);
"type": "basic",
"iconUrl": chrome.runtime.getURL("icons/icon-128.png"),
"title": 'YTPTube Extension',
"message": "Options saved."
});
setTimeout(() => window.close(), 1000); setTimeout(() => {
try {
window.close()
} catch (e) {
}
}, 1000);
});
document.getElementById("test_config").addEventListener("click", async e => {
e.preventDefault();
await testConfig();
}); });
+33 -55
Voir le fichier
@@ -3,64 +3,42 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>YTPTube Extension</title> <title>YTPTube Extension</title>
<link rel="stylesheet" href="css/pure.css"/> <link rel="stylesheet" href="css/bulma.css"/>
<style>
#ytptube_popup {
min-width: 250px;
min-height: 120px;
margin: 1em;
}
body {
font-size: 100%;
}
@media (prefers-color-scheme: dark) {
body {
color: white;
background-color: #19191c;
}
input {
background-color: #19191c;
color: white;
}
fieldset > legend {
color: white !important;
}
}
.button-secondary {
background: rgb(66, 184, 221);
}
</style>
</head> </head>
<body> <body class="container">
<form id="ytptube_popup" class="pure-form pure-form-stacked"> <div class="columns is-multiline">
<div class="pure-control-group"> <div class="column is-12">
<label for="preset">Preset</label> <form id="ytptube_popup" class="pl-2 pr-2 pt-2">
<select id="preset" class="pure-input-1" style="padding-top:0;padding-bottom:0"> <div class="field">
<option value="default">default</option> <label class="label" for="preset">Preset</label>
</select> <div class="select is-fullwidth">
<span class="pure-form-message">Select preset to use with the URL.</span> <select id="preset" class="is-fullwidth">
<option value="default">default</option>
</select>
</div>
<span class="help">Select preset to use with the URL.</span>
</div>
<div class="field">
<label class="label" for="user_url">URL:</label>
<div class="control">
<input id="user_url" class="input" type="text" placeholder="https://..">
</div>
<span class="help">The URL to send.</span>
</div>
<div class="field is-grouped">
<div class="control is-expanded">
<button class="button is-primary is-fullwidth" type="submit">Send to YTPTube</button>
</div>
<div class="control is-expanded">
<button class="button is-info is-fullwidth" type="button" id="go-to-options">
Open options page
</button>
</div>
</div>
</form>
</div> </div>
<div class="pure-control-group"> </div>
<label for="user_url">URL:</label>
<input id="user_url" class="pure-input-1" type="text" placeholder="https://..">
<span class="pure-form-message">The URL to send to YTPTube instance</span>
</div>
<div class="pure-control-group">
<button class="pure-button pure-input-1 pure-button-primary" type="submit">Send to YTPTube</button>
</div>
<br>
<div class="pure-control-group">
<button class="pure-button pure-input-1 button-secondary" type="button" id="go-to-options">
Open options page
</button>
</div>
</form>
<script src="popup.js"></script> <script src="popup.js"></script>