switch to bulma and remove pure css, improve the messaging
Cette révision appartient à :
+31
-38
@@ -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);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Externe
+24826
Fichier diff supprimé car celui-ci est trop grand
Voir la Diff
Diff de fichier supprimé car une ou plusieurs lignes sont trop longues
@@ -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
@@ -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
@@ -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
@@ -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>
|
||||||
|
|
||||||
|
|||||||
Référencer dans un nouveau ticket
Bloquer un utilisateur