You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
310 lines
9.7 KiB
310 lines
9.7 KiB
1 month ago
|
// helpers {{{
|
||
|
|
||
|
function htmlEsc(str) {
|
||
|
return str.replace(/&/g,"&").replace(/>/g,">").replace(/</g,"<");
|
||
|
}
|
||
|
|
||
|
function setPopupMode(mode) {
|
||
|
$("body").removeClass("clip info config").addClass(mode);
|
||
|
}
|
||
|
|
||
|
function showSuccessMsg(msg) {
|
||
|
$("#info").html(msg);
|
||
|
setPopupMode("info");
|
||
|
setTimeout( function() { window.close() }, 3000 );
|
||
|
}
|
||
|
|
||
|
function showErrMsg(msg) {
|
||
|
$("#info").html(msg);
|
||
|
setPopupMode("info");
|
||
|
}
|
||
|
|
||
|
function g(){return((1+Math.random())*65536|0).toString(16).substring(1)}
|
||
|
|
||
|
function generateUUID(){return g()+g()+"-"+g()+"-"+g()+"-"+g()+"-"+g()+g()+g()}
|
||
|
|
||
|
// }}}
|
||
|
|
||
|
console = chrome.extension.getBackgroundPage().console;
|
||
|
|
||
|
const contentTypes = {
|
||
|
"bookmark": [
|
||
|
{
|
||
|
urlPattern: /^xxx$/,
|
||
|
fields: {},
|
||
|
workflowyFormat: function(data, tab) {
|
||
|
return {
|
||
|
name: tab.title,
|
||
|
description: tab.url
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
],
|
||
|
"tab": [
|
||
|
{
|
||
|
urlPattern: /^https?:\/\/tabs.ultimate-guitar.com\/tab\//,
|
||
|
fields: {
|
||
|
title: { selector: 'h1', attribute: 'textContent' },
|
||
|
artist: { selector: 'h1 + span', attribute: 'textContent' },
|
||
|
tab: { selector: 'article pre', attribute: 'textContent' }
|
||
|
},
|
||
|
workflowyFormat: function(data, tab) {
|
||
|
return {
|
||
|
name: "<span class='colored c-gray'>" + data.title.trim() + "</span>",
|
||
|
description: data.artist + "\n\n" + "<i>" + data.tab + "</i>"
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
],
|
||
|
};
|
||
|
|
||
|
function initConfigPopup(tab) { // {{{
|
||
|
setPopupMode("config");
|
||
|
|
||
|
var status;
|
||
|
if (!localStorage.userid) {
|
||
|
status = "Not synchronized";
|
||
|
} else {
|
||
|
status = "Synchronized";
|
||
|
}
|
||
|
|
||
|
$("#status").html("Status: " + status);
|
||
|
|
||
|
// Clear existing buttons
|
||
|
$("#content-type-buttons").empty();
|
||
|
|
||
|
// Create a button for each content type
|
||
|
Object.keys(contentTypes).forEach(function(type) {
|
||
|
var button = $('<button>')
|
||
|
.text("Set '" + type + "' inbox")
|
||
|
.on('click', function() {
|
||
|
setInboxForContentType(type, tab);
|
||
|
});
|
||
|
|
||
|
$("#content-type-buttons").append(button);
|
||
|
});
|
||
|
|
||
|
$("#resetbutton").on("click", function() {
|
||
|
chrome.extension.getBackgroundPage().refreshWorkflowyData(function(err) {
|
||
|
if (err) {
|
||
|
showErrorMsg("Error syncing to WorkFlowy.");
|
||
|
} else {
|
||
|
$("#status").html("Sync successful!");
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
// }}}
|
||
|
|
||
|
function setInboxForContentType(type, tab) { // {{{
|
||
|
console.log("Setting inbox for type: " + type);
|
||
|
chrome.tabs.executeScript(
|
||
|
{ code: "document.getElementsByClassName(\"project selected\")[0].getAttribute(\"projectid\");" },
|
||
|
function(response) {
|
||
|
console.log("Page responded with " + response);
|
||
|
if (response && response[0] != "None") {
|
||
|
var inbox = getInboxObject(); // Get the current inbox object
|
||
|
inbox[type] = response[0]; // Set the inbox for the specific type
|
||
|
setInboxObject(inbox); // Update the inbox object in localStorage
|
||
|
|
||
|
showSuccessMsg(type.charAt(0).toUpperCase() + type.slice(1) + " inbox set successfully.");
|
||
|
} else {
|
||
|
showErrMsg("Problem setting inbox location for " + type + ".");
|
||
|
}
|
||
|
}
|
||
|
);
|
||
|
}
|
||
|
|
||
|
function getInboxObject() {
|
||
|
try {
|
||
|
return JSON.parse(localStorage.inbox || '{}');
|
||
|
} catch (e) {
|
||
|
console.error("Error parsing inbox from localStorage:", e);
|
||
|
return {};
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function setInboxObject(inboxObj) {
|
||
|
localStorage.inbox = JSON.stringify(inboxObj);
|
||
|
}
|
||
|
|
||
|
// }}}
|
||
|
|
||
|
function initClipperPopup(tab) { // {{{
|
||
|
|
||
|
if (! localStorage.userid || ! localStorage.inbox) {
|
||
|
showErrMsg("Extension not configured. "
|
||
|
+ "<a href=\"https://workflowy.com\">Navigate "
|
||
|
+ "to WorkFlowy</a> then press this button again.");
|
||
|
console.log("extension not configured");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var contentType = "bookmark";
|
||
|
var contentInfo = contentTypes[contentType][0];
|
||
|
|
||
|
for (let i = 0; i < Object.keys(contentTypes).length; i++) {
|
||
|
var key = Object.keys(contentTypes)[i];
|
||
|
contentTypes[key].forEach(function(content){
|
||
|
if (tab.url.match(content['urlPattern'])){
|
||
|
contentType = key;
|
||
|
contentInfo = content;
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
var fieldSelectors = contentInfo['fields'];
|
||
|
|
||
|
// contentType = Object.keys(contentTypes).find(key => tab.url.match(contentTypes[key].urlPattern));
|
||
|
console.log("contentType", contentType);
|
||
|
|
||
|
if (contentType === undefined) {
|
||
|
contentType = "bookmark";
|
||
|
console.log("contentType", contentType);
|
||
|
}
|
||
|
|
||
|
var inboxObject = getInboxObject();
|
||
|
|
||
|
if (!(contentType in inboxObject)) {
|
||
|
showErrMsg("Inbox not set for " + contentType);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
let extractionScript = `var extractedData = {};`;
|
||
|
for (let field in fieldSelectors) {
|
||
|
let selector = fieldSelectors[field].selector;
|
||
|
let attribute = fieldSelectors[field].attribute;
|
||
|
extractionScript += `
|
||
|
var element = document.querySelector('${selector}');
|
||
|
extractedData['${field}'] = element ? element['${attribute}'].trim() : '';
|
||
|
`;
|
||
|
}
|
||
|
extractionScript += 'extractedData;';
|
||
|
|
||
|
setPopupMode("clip");
|
||
|
|
||
|
chrome.tabs.executeScript(tab.id, { code: extractionScript }, function(results) {
|
||
|
if (results && results[0]) {
|
||
|
let extractedData = results[0];
|
||
|
let formattedData = contentInfo.workflowyFormat(extractedData, tab);
|
||
|
$("#name").val(formattedData["name"]);
|
||
|
$("#description").val(formattedData["description"]);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
$("#name").focus();
|
||
|
$("#inboxlink").attr("href", "https://workflowy.com/#/" + inboxObject[contentType] );
|
||
|
$("#inboxlink").html("Go to " + contentType + " inbox");
|
||
|
$("#clipbutton").html("Save " + contentType)
|
||
|
$("#clipbutton").on("click", function () { clipToWorkflowy( $("#name").val(), $("#description").val(), inboxObject[contentType]); });
|
||
|
|
||
|
}
|
||
|
|
||
|
// }}}
|
||
|
|
||
|
function clipToWorkflowy(name, description, inboxId) { // {{{
|
||
|
var newuuid = generateUUID();
|
||
|
var timestamp = Math.floor((new Date()).getTime()/1000) - localStorage.joined;
|
||
|
|
||
|
var request = [{
|
||
|
"most_recent_operation_transaction_id": localStorage.transid,
|
||
|
"operations": [
|
||
|
{ "type": "create",
|
||
|
"data": {
|
||
|
"projectid": newuuid,
|
||
|
"parentid": inboxId,
|
||
|
"priority": 9999
|
||
|
},
|
||
|
"client_timestamp": timestamp,
|
||
|
"undo_data": {}
|
||
|
},
|
||
|
{ "type":"edit",
|
||
|
"data": {
|
||
|
"projectid": newuuid,
|
||
|
"name": name,
|
||
|
"description": description
|
||
|
},
|
||
|
"client_timestamp": timestamp,
|
||
|
"undo_data": {
|
||
|
"previous_last_modified": timestamp,
|
||
|
"previous_name": "",
|
||
|
"previous_description": ""
|
||
|
}
|
||
|
}
|
||
|
]
|
||
|
}];
|
||
|
|
||
|
console.log("Trying to save to workflowy:",
|
||
|
{ timestamp: timestamp,
|
||
|
name: name,
|
||
|
description: description,
|
||
|
name: name,
|
||
|
description: description,
|
||
|
client_id: "2015-11-17 19:25:15.397732",
|
||
|
client_version: 15,
|
||
|
push_poll_id: localStorage.pollid,
|
||
|
push_poll_data: JSON.stringify(request),
|
||
|
crosscheck_user_id: localStorage.userid,
|
||
|
localstorage: localStorage }
|
||
|
);
|
||
|
|
||
|
var data = new FormData();
|
||
|
data.append("client_id", "2015-11-17 19:25:15.397732");
|
||
|
data.append("client_version", 15);
|
||
|
data.append("push_poll_id", localStorage.pollid);
|
||
|
data.append("push_poll_data", JSON.stringify(request));
|
||
|
data.append("crosscheck_user_id", localStorage.userid);
|
||
|
|
||
|
var xhr = new XMLHttpRequest();
|
||
|
xhr.open('POST', 'https://workflowy.com/push_and_poll', true);
|
||
|
xhr.onload = function () {
|
||
|
var respObj = JSON.parse(this.responseText);
|
||
|
console.log("XHR response from server:", respObj);
|
||
|
|
||
|
if (respObj.logged_out) {
|
||
|
showErrMsg("WorkFlowy thinks you're logged out! Make sure you're logged in, and if this message persists then try resynchronizing the extension.");
|
||
|
} else if ( ! respObj.results ) {
|
||
|
showErrMsg("Unknown error!");
|
||
|
} else if (respObj.results[0].error_encountered_in_remote_operations) {
|
||
|
showErrMsg("Unknown error!");
|
||
|
} else {
|
||
|
var oldid = localStorage.transid;
|
||
|
localStorage.transid = respObj.results[0].new_most_recent_operation_transaction_id;
|
||
|
console.log("got new transid: changed from " + oldid + " to " + localStorage.transid);
|
||
|
showSuccessMsg("Successfully clipped!<br><br>"
|
||
|
+ "<small><a href=\"https://workflowy.com/#/"
|
||
|
+ newuuid.substr(24) + "\">view in WorkFlowy</a>"
|
||
|
+ "</small>");
|
||
|
}
|
||
|
};
|
||
|
xhr.send(data);
|
||
|
|
||
|
}
|
||
|
|
||
|
// }}}
|
||
|
|
||
|
document.addEventListener('DOMContentLoaded', function() { // {{{
|
||
|
|
||
|
chrome.tabs.query({ active: true, currentWindow: true }, function(tabs) {
|
||
|
var tab = tabs[0];
|
||
|
console.log("browser action got clicked @ " + tab.url);
|
||
|
|
||
|
$("body").on("click", "a", function() {
|
||
|
chrome.tabs.create({url: $(this).attr("href") });
|
||
|
return false;
|
||
|
});
|
||
|
|
||
|
if (tab.url.match(/^https?:\/\/(?:www\.)?workflowy.com/)) {
|
||
|
initConfigPopup(tab);
|
||
|
} else {
|
||
|
initClipperPopup(tab);
|
||
|
}
|
||
|
|
||
|
});
|
||
|
|
||
|
});
|
||
|
|
||
|
// }}}
|