Files
bookmark_sync/js/popup.js
2026-04-19 19:58:17 +08:00

586 lines
24 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
$(function () {
const isFirefox = typeof window.browser !== "undefined";
const browserAPI = window.browser || window.chrome;
const storageAPI = {
get: function (keys, cb) {
if (isFirefox) {
browserAPI.storage.local.get(keys).then(cb);
} else {
browserAPI.storage.local.get(keys, cb);
}
},
set: function (obj, cb) {
if (isFirefox) {
browserAPI.storage.local.set(obj).then(function () {
cb && cb();
});
} else {
browserAPI.storage.local.set(obj, cb);
}
},
clear: function (cb) {
if (isFirefox) {
browserAPI.storage.local.clear().then(function () {
cb && cb();
});
} else {
browserAPI.storage.local.clear(cb);
}
}
};
const bookmarksAPI = {
getTree: function (cb) {
if (isFirefox) {
browserAPI.bookmarks.getTree().then(cb);
} else {
browserAPI.bookmarks.getTree(cb);
}
},
getSubTree: function (id, cb) {
if (isFirefox) {
browserAPI.bookmarks.getSubTree(id).then(cb);
} else {
browserAPI.bookmarks.getSubTree(id, cb);
}
},
getChildren: function (id, cb) {
if (isFirefox) {
browserAPI.bookmarks.getChildren(id).then(cb);
} else {
browserAPI.bookmarks.getChildren(id, cb);
}
},
removeTree: function (id, cb) {
if (isFirefox) {
browserAPI.bookmarks.removeTree(id).then(cb);
} else {
browserAPI.bookmarks.removeTree(id, cb);
}
},
create: function (options, cb) {
if (isFirefox) {
browserAPI.bookmarks.create(options).then(cb);
} else {
browserAPI.bookmarks.create(options, cb);
}
}
};
sync = {
/**
* 初始化函数
*/
init: function () {
let that = this;
that.base64 = new Base64();
// 码云的API根地址现在从表单读取
that.baseUrl = $("#tbServer").val().endsWith('/') ? $("#tbServer").val() : $("#tbServer").val() + '/';
that.getCacheUserInfo();
that.bindEvent();
},
/**
* 表单收集
*/
createFormObj: function () {
let formObj = {};
formObj.server = $("#tbServer").val();
formObj.access_token = $("#tbAccessToken").val();
formObj.owner = $("#tbOwner").val();
formObj.repo = $("#tbRepo").val();
formObj.path = $("#tbPath").val();
formObj.branch = $("#tbBranch").val();
return formObj;
},
/**
* 弹出窗开始时从缓存读取已经存储的数据
*/
getCacheUserInfo: function () {
let that = this;
// 从缓存中读取数据并设置到表单中
storageAPI.get(["server", "access_token", "owner", "repo", "path", "branch", "remember"], function (obj) {
// 插件最开始的状态是记住开关打开了但是chrome本地缓存中还没有设置值
if (!obj.remember) {
if ($("#rememberDot").hasClass("green")) {
that.saveRememberState("on");
} else {
that.saveRememberState("off");
}
} else if (obj.remember == "on") {
$("#rememberDot").addClass("green");
} else {
$("#rememberDot").removeClass("green");
}
if ($("#rememberDot").hasClass("green")) {
if (obj.server || obj.access_token || obj.owner || obj.repo || obj.path || obj.branch) {
$("#tbServer").val(obj.server || "https://gitee.com/api/v5/");
that.baseUrl = ($("#tbServer").val().endsWith('/') ? $("#tbServer").val() : $("#tbServer").val() + '/');
$("#tbAccessToken").val(obj.access_token);
$("#tbOwner").val(obj.owner);
$("#tbRepo").val(obj.repo);
$("#tbPath").val(obj.path);
$("#tbBranch").val(obj.branch);
that.rememberOn();
}
}
});
},
rememberOn: function () {
let that = this;
$("#rememberText").addClass("grey");
$("#rememberDot").addClass("green");
that.saveRememberState("on");
},
rememberOff: function () {
let that = this;
$("#rememberText").removeClass("grey");
$("#rememberDot").removeClass("green");
that.saveRememberState("off");
},
/**
* 清除用户信息
*/
clearUserInfo: function () {
storageAPI.clear(function () {
console.log('clear user info success');
});
},
/**
* 保存用户信息
*/
saveUserInfo: function () {
let that = this;
let formObj = that.createFormObj();
storageAPI.set(formObj, function () {
console.log('save user info success');
});
},
/**
* 保存记住按钮的状态
* stateon记住off不记住
*/
saveRememberState: function (state) {
let rememberObj = {};
rememberObj.remember = state;
storageAPI.set(rememberObj, function () {
console.log('save remember state success');
});
},
/**
* 获取书签栏根节点 ID
*/
getBookmarkBarId: function (fn) {
let that = this;
if (!isFirefox) {
fn("1");
return;
}
bookmarksAPI.getTree(function (tree) {
let root = Array.isArray(tree) ? tree[0] : tree;
if (!root || !root.children) {
fn("toolbar_____");
return;
}
let toolbar = root.children.find(function (node) {
return node.id === "toolbar_____" || node.title === "Bookmarks Toolbar" || (node.title && node.title.toLowerCase().indexOf("toolbar") !== -1);
});
fn(toolbar ? toolbar.id : "toolbar_____");
});
},
/**
* 获取浏览器的书签数据
*/
getBookmarks: function (fn) {
let that = this;
that.getBookmarkBarId(function (rootId) {
bookmarksAPI.getSubTree(rootId, function (bookmarks) {
console.log('Retrieved bookmarks:', bookmarks);
fn(bookmarks);
});
});
},
/**
* 清空书签栏文件夹(不能直接清除根书签栏,只能遍历一个一个文件夹清除)
*/
emptyBookmarks: function (fn) {
let that = this;
that.getBookmarkBarId(function (rootId) {
bookmarksAPI.getChildren(rootId, function (children) {
// 需要判断书签栏是否原来就是空的
if (!children || children.length <= 0) {
fn();
return;
}
for (let i = 0; i < children.length; i++) {
let item = children[i];
bookmarksAPI.removeTree(item.id, function () {
// 判断是不是已经删除到最后一个了,是的话就调用回调函数
if (i == (children.length - 1)) {
fn();
}
});
}
});
});
},
bindEvent: function () {
let that = this;
// 记住按钮点击事件
$("#rememberDot").on("click", function () {
// 先判断当前记住按钮的状态,假如已经记住则不再记住,清空缓存
if ($("#rememberDot").hasClass("green")) {
that.clearUserInfo();
that.rememberOff();
} else {
// 获取表单数据,有则保存到缓存中
let formObj = that.createFormObj();
let existRes = that.checkFormExist(formObj);
if (existRes) {
that.saveUserInfo();
}
that.rememberOn();
}
});
// 输入框的输入事件,用来记忆表单数据
$(".input").on("input", function () {
if ($("#rememberDot").hasClass("green")) {
that.saveUserInfo();
that.rememberOn();
}
});
// 点击上传按钮
$("#btnUpload").on("click", function () {
console.log('Upload button clicked');
let formObj = that.createFormObj();
console.log('Form object:', formObj);
let formRes = that.checkForm(formObj);
if (formRes != "ok") {
$("#toast").text(formRes).show();
return;
}
// 更新baseUrl
that.baseUrl = formObj.server.endsWith('/') ? formObj.server : formObj.server + '/';
console.log('Base URL set to:', that.baseUrl);
// 假如记住按钮已经点击了
if ($("#rememberDot").hasClass("green")) {
that.saveUserInfo();
that.rememberOn();
} else {
that.clearUserInfo();
that.rememberOff();
}
$("#loaderWrap").show();
// 从码云上获取书签内容
console.log('Calling getGit');
that.getGit(formObj, function (getState, getRes) {
console.log('getGit callback:', getState, getRes);
// 获取浏览器的书签
that.getBookmarks(function (bookmarks) {
console.log('getBookmarks callback');
// 获取码云的内容存在则更新文件,否则更新文件
if (getState) {
let sha = getRes.sha;
that.updateGit(formObj, bookmarks, sha, function (updState, updRes) {
// 更新成功,则提示,否则提示错误
if (updState) {
$("#successWrap").show();
$(".successText").text("Upload Success");
} else {
$("#toast").text(updRes).show();
}
$("#loaderWrap").hide();
});
} else {
that.createGit(formObj, bookmarks, function (createState, createRes) {
// 创建成功,则提示,否则提示错误
if (createState) {
$("#successWrap").show();
$(".successText").text("Upload Success");
} else {
$("#toast").text(createRes).show();
}
$("#loaderWrap").hide();
});
}
});
});
});
// 点击下载按钮事件
$("#btnDownload").on("click", function () {
let formObj = that.createFormObj();
let formRes = that.checkForm(formObj);
if (formRes != "ok") {
$("#toast").text(formRes).show();
return;
}
// 更新baseUrl
that.baseUrl = formObj.server.endsWith('/') ? formObj.server : formObj.server + '/';
// 假如记住按钮已经点击了
if ($("#rememberDot").hasClass("green")) {
that.saveUserInfo();
that.rememberOn();
} else {
that.clearUserInfo();
that.rememberOff();
}
$("#loaderWrap").show();
// 从码云上获取书签内容
that.getGit(formObj, function (getState, getRes) {
// 获取码云的内容存在则创建文件,否则提示文件不存在
if (getState) {
let gitContent = that.base64.decode(getRes["content"]);
let bookmarksParent = JSON.parse(gitContent);
let bookmarks = bookmarksParent[0];
// 清空书签栏
that.emptyBookmarks(function () {
// 等所有书签都清空后开始设置书签
that.getBookmarkBarId(function (rootId) {
that.setBookmarks(rootId, bookmarks);
$("#successWrap").show();
$(".successText").text("Download Success");
});
});
} else {
$("#toast").text("Git文件不存在").show();
}
$("#loaderWrap").hide();
});
});
},
/**
* 将git获取的内容设置到浏览器书签上去
*/
setBookmarks: function (parentId, bookmarks) {
let that = this;
if (!bookmarks.children || bookmarks.children.length <= 0) {
return;
}
for (let i = 0; i < bookmarks.children.length; i++) {
let item = bookmarks.children[i];
bookmarksAPI.create({
parentId: parentId,
index: item.index,
title: item.title,
url: item.url
}, function (res) {
// 判断假如还有子元素则递归调用自身添加
if (item.children && item.children.length > 0) {
that.setBookmarks(res.id, item);
}
});
}
},
/**
* 校验表单
*/
checkForm: function (formObj) {
if (!formObj.server) {
$("#tbServer").addClass('error');
return 'server is required';
}
$("#tbServer").removeClass('error');
if (!formObj.access_token) {
$("#tbAccessToken").addClass('error');
return 'access_token is required';
}
$("#tbAccessToken").removeClass('error');
if (!formObj.owner) {
$("#tbOwner").addClass('error');
return 'owner is required';
}
$("#tbOwner").removeClass('error');
if (!formObj.repo) {
$("#tbRepo").addClass('error');
return 'repo is required';
}
$("#tbRepo").removeClass('error');
if (!formObj.path) {
$("#tbPath").addClass('error');
return 'path is required';
}
$("#tbPath").removeClass('error');
if (!formObj.branch) {
$("#tbBranch").addClass('error');
return 'branch is required';
}
$("#tbBranch").removeClass('error');
return "ok";
},
/**
* 查看表单是否至少有一个值
*/
checkFormExist: function (formObj) {
if (formObj.server != '') {
return true;
}
if (formObj.access_token != '') {
return true;
}
if (formObj.owner != '') {
return true;
}
if (formObj.repo != '') {
return true;
}
if (formObj.path != '') {
return true;
}
if (formObj.branch != '') {
return true;
}
return false;
},
/**
* 获取Gitee上的数据
* curl -X GET --header 'Content-Type: application/json;charset=UTF-8' 'https://gitee.com/api/v5/repos/xieyf00/chrome/contents/bookmark/bookmark-4.json?access_token=16c6176faea12d4b2dba667872d9b21c&ref=master'
*/
getGit: function (formObj, fn) {
let that = this;
let getUrl = that.baseUrl + "repos/" + formObj.owner + "/" + formObj.repo + "/contents/" + formObj.path + "?ref=" + formObj.branch;
$.ajax({
type: "GET",
url: getUrl,
headers: {
'Authorization': 'token ' + formObj.access_token
},
crossDomain: true,
success: function (res) {
fn && fn(true, res);
},
error: function (xhr, textStatus, error) {
fn && fn(false, error);
}
});
},
/**
* 创建Git文件
* curl -X POST --header 'Content-Type: application/json;charset=UTF-8' 'https://gitee.com/api/v5/repos/xieyf00/chrome/contents/bookmark/bookmark-copy.json' -d '{"access_token":"16c6176faea12d4b2dba667872d9b21c","content":"xxx","message":"xieyangfan commit","branch":"master"}'
* createContentRaw文件内容, 要用 base64 编码
*/
createGit: function (formObj, createContentRaw, fn) {
let that = this;
if (createContentRaw == null) {
console.error('createGit missing contentRaw');
fn && fn(false, 'No bookmark data to upload');
return;
}
console.log('createContentRaw:', createContentRaw);
let jsonStr = JSON.stringify(createContentRaw);
console.log('JSON string:', jsonStr);
let createContent = that.base64.encode(jsonStr);
console.log('Base64 encoded:', createContent);
// Git提交信息
let createMessage = "Chrome Browser Bookmark Created" + new Date();
// 构建
let createData = {};
createData.access_token = formObj.access_token;
createData.content = createContent;
createData.message = createMessage;
createData.branch = formObj.branch;
let createUrl = that.baseUrl + "repos/" + formObj.owner + "/" + formObj.repo + "/contents/" + formObj.path;
console.log('Create URL:', createUrl);
console.log('Create data:', createData);
$.ajax({
type: "POST",
url: createUrl,
contentType: 'application/json',
headers: {
'Authorization': 'token ' + formObj.access_token
},
data: JSON.stringify(createData),
crossDomain: true,
success: function (res) {
console.log('Create success:', res);
fn && fn(true, res);
},
error: function (xhr, textStatus, error) {
console.log('Create error:', xhr, textStatus, error);
fn && fn(false, error);
}
});
},
/**
* 更新Git文件
* curl -X PUT --header 'Content-Type: application/json;charset=UTF-8' 'https://gitee.com/api/v5/repos/xieyf00/chrome/contents/bookmark/bookmark-6.json' -d '{"access_token":"16c6176faea12d4b2dba667872d9b21c","content":"InhpZXlhbmdmYW4gMjAxOTA3MjQgMTU0OCI=","sha":"dce85293664c50792d2ebcfc4ede23bf3e1197c2","message":"xieyangfan 20190724 1736","branch":"master"}'
* updateContentRaw文件内容, 要用 base64 编码
* sha文件的 Blob SHA可通过 [获取仓库具体路径下的内容] API 获取
*/
updateGit: function (formObj, updateContentRaw, sha, fn) {
let that = this;
if (updateContentRaw == null) {
console.error('updateGit missing updateContentRaw');
fn && fn(false, 'No bookmark data to update');
return;
}
console.log('updateContentRaw:', updateContentRaw);
let jsonStr = JSON.stringify(updateContentRaw);
console.log('JSON string:', jsonStr);
let updateContent = that.base64.encode(jsonStr);
console.log('Base64 encoded:', updateContent);
// Git提交信息
let updateMessage = "Chrome Browser Bookmark Updated" + new Date();
// 构建
let updateData = {};
updateData.access_token = formObj.access_token;
updateData.content = updateContent;
updateData.message = updateMessage;
updateData.sha = sha;
updateData.branch = formObj.branch;
let updateUrl = that.baseUrl + "repos/" + formObj.owner + "/" + formObj.repo + "/contents/" + formObj.path;
console.log('Update URL:', updateUrl);
console.log('Update data:', updateData);
$.ajax({
type: "PUT",
url: updateUrl,
contentType: 'application/json',
headers: {
'Authorization': 'token ' + formObj.access_token
},
data: JSON.stringify(updateData),
crossDomain: true,
success: function (res) {
console.log('Update success:', res);
fn && fn(true, res);
},
error: function (xhr, textStatus, error) {
console.log('Update error:', xhr, textStatus, error);
fn && fn(false, error);
}
});
},
/**
* 删除Git文件
* curl -X DELETE --header 'Content-Type: application/json;charset=UTF-8' 'https://gitee.com/api/v5/repos/xieyf00/chrome/contents/bookmark/bookmark-6.json?access_token=16c6176faea12d4b2dba667872d9b21c&sha=dce85293664c50792d2ebcfc4ede23bf3e1197c2&message=Chrome%20Browser%20Bookmark%20Deleted&branch=master'
* sha文件的 Blob SHA可通过 [获取仓库具体路径下的内容] API 获取
*/
deleteGit: function (formObj, sha, fn) {
let that = this;
// Git提交信息
let deleteMessage = "Chrome Browser Bookmark Deleted" + new Date();
// 构建
let deleteData = {};
deleteData.access_token = formObj.access_token;
deleteData.message = deleteMessage;
deleteData.sha = sha;
deleteData.branch = formObj.branch;
let deleteUrl = that.baseUrl + "repos/" + formObj.owner + "/" + formObj.repo + "/contents/" + formObj.path;
$.ajax({
type: "DELETE",
url: deleteUrl,
data: deleteData,
crossDomain: true,
success: function (res) {
fn && fn(true, res);
},
error: function (xhr, textStatus, error) {
fn && fn(false, error);
}
});
}
}
sync.init();
});