|
|
@ -1,11 +1,12 @@ |
|
|
|
let api = {}; |
|
|
|
let api = {}; |
|
|
|
|
|
|
|
let serverApi = {}; |
|
|
|
// chrome bookmark api wrapper
|
|
|
|
// chrome bookmark api wrapper
|
|
|
|
(function(api) { |
|
|
|
(function (api) { |
|
|
|
/** |
|
|
|
/** |
|
|
|
* 获得整个书签树 |
|
|
|
* 获得整个书签树 |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
const getTree = () => { |
|
|
|
const getTree = () => { |
|
|
|
return new Promise(resolve => { |
|
|
|
return new Promise((resolve) => { |
|
|
|
chrome.bookmarks.getTree(resolve); |
|
|
|
chrome.bookmarks.getTree(resolve); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}; |
|
|
|
}; |
|
|
@ -18,12 +19,12 @@ let api = {}; |
|
|
|
* 返回的书签数组中是不包含children字段的,即不包含子节点以下的节点 |
|
|
|
* 返回的书签数组中是不包含children字段的,即不包含子节点以下的节点 |
|
|
|
* @param {String} id 父书签组id |
|
|
|
* @param {String} id 父书签组id |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
const getChildren = id => { |
|
|
|
const getChildren = (id) => { |
|
|
|
return new Promise(resolve => { |
|
|
|
return new Promise((resolve) => { |
|
|
|
chrome.bookmarks.getChildren(id, resolve); |
|
|
|
chrome.bookmarks.getChildren(id, resolve); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}; |
|
|
|
}; |
|
|
|
const getChildrenAsync = async id => { |
|
|
|
const getChildrenAsync = async (id) => { |
|
|
|
return await getChildren(id); |
|
|
|
return await getChildren(id); |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
@ -32,12 +33,12 @@ let api = {}; |
|
|
|
* 返回的书签数组中包含children字段,即包含子节点以下的节点 |
|
|
|
* 返回的书签数组中包含children字段,即包含子节点以下的节点 |
|
|
|
* @param {String} id 父书签组id |
|
|
|
* @param {String} id 父书签组id |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
const getSubTree = id => { |
|
|
|
const getSubTree = (id) => { |
|
|
|
return new Promise(resolve => { |
|
|
|
return new Promise((resolve) => { |
|
|
|
chrome.bookmarks.getSubTree(id, resolve); |
|
|
|
chrome.bookmarks.getSubTree(id, resolve); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}; |
|
|
|
}; |
|
|
|
const getSubTreeAsync = async id => { |
|
|
|
const getSubTreeAsync = async (id) => { |
|
|
|
return await getSubTree(id); |
|
|
|
return await getSubTree(id); |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
@ -45,12 +46,12 @@ let api = {}; |
|
|
|
* 删除指定id的书签 |
|
|
|
* 删除指定id的书签 |
|
|
|
* @param {String} id 需要删除的书签的id |
|
|
|
* @param {String} id 需要删除的书签的id |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
const remove = id => { |
|
|
|
const remove = (id) => { |
|
|
|
return new Promise(resolve => { |
|
|
|
return new Promise((resolve) => { |
|
|
|
chrome.bookmarks.remove(id, resolve); |
|
|
|
chrome.bookmarks.remove(id, resolve); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}; |
|
|
|
}; |
|
|
|
const removeAsync = async id => { |
|
|
|
const removeAsync = async (id) => { |
|
|
|
return await remove(id); |
|
|
|
return await remove(id); |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
@ -58,12 +59,12 @@ let api = {}; |
|
|
|
* 删除指定id的空书签组,如果书签组下有子书签或子书签组,删除将失败 |
|
|
|
* 删除指定id的空书签组,如果书签组下有子书签或子书签组,删除将失败 |
|
|
|
* @param {String} id 需要删除的书签文件夹id |
|
|
|
* @param {String} id 需要删除的书签文件夹id |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
const removeTree = id => { |
|
|
|
const removeTree = (id) => { |
|
|
|
return new Promise(resolve => { |
|
|
|
return new Promise((resolve) => { |
|
|
|
chrome.bookmarks.removeTree(id, resolve); |
|
|
|
chrome.bookmarks.removeTree(id, resolve); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}; |
|
|
|
}; |
|
|
|
const removeTreeAsync = async id => { |
|
|
|
const removeTreeAsync = async (id) => { |
|
|
|
await removeTree(id); |
|
|
|
await removeTree(id); |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
@ -75,12 +76,12 @@ let api = {}; |
|
|
|
* string (optional) title |
|
|
|
* string (optional) title |
|
|
|
* string (optional) url 如果为NULL或者不填,则代表一个书签组文件夹 |
|
|
|
* string (optional) url 如果为NULL或者不填,则代表一个书签组文件夹 |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
const create = bookmark => { |
|
|
|
const create = (bookmark) => { |
|
|
|
return new Promise(resolve => { |
|
|
|
return new Promise((resolve) => { |
|
|
|
chrome.bookmarks.create(bookmark, resolve); |
|
|
|
chrome.bookmarks.create(bookmark, resolve); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}; |
|
|
|
}; |
|
|
|
const createAsync = async bookmark => { |
|
|
|
const createAsync = async (bookmark) => { |
|
|
|
return await create(bookmark); |
|
|
|
return await create(bookmark); |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
@ -92,6 +93,65 @@ let api = {}; |
|
|
|
api.createAsync = createAsync; |
|
|
|
api.createAsync = createAsync; |
|
|
|
})(api); |
|
|
|
})(api); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// backend server api wrapper
|
|
|
|
|
|
|
|
(function (api) { |
|
|
|
|
|
|
|
const API_VERSION = "v1"; |
|
|
|
|
|
|
|
let serverAddress = ""; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const setServerAddress = (address) => { |
|
|
|
|
|
|
|
serverAddress = address; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const getServerAddress = () => { |
|
|
|
|
|
|
|
return serverAddress; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const getVersion = () => { |
|
|
|
|
|
|
|
return new Promise((resolve, reject) => { |
|
|
|
|
|
|
|
$.getJSON(`${serverAddress}/${API_VERSION}/version`, (response) => { |
|
|
|
|
|
|
|
const { code, message, data } = response; |
|
|
|
|
|
|
|
if (code === 20000) { |
|
|
|
|
|
|
|
resolve(data); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
reject(new Error(message)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const uploadBookmarks = data => { |
|
|
|
|
|
|
|
return new Promise((resolve, reject) => { |
|
|
|
|
|
|
|
$.post(`${serverAddress}/${API_VERSION}/bookmark`, data, (response) => { |
|
|
|
|
|
|
|
const { code, message, data } = response; |
|
|
|
|
|
|
|
if (code === 20000) { |
|
|
|
|
|
|
|
resolve(data); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
reject(new Error(message)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}, 'json'); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const downloadBookmarks = () => { |
|
|
|
|
|
|
|
return new Promise((resolve, reject) => { |
|
|
|
|
|
|
|
$.getJSON(`${serverAddress}/${API_VERSION}/bookmark`, (response) => { |
|
|
|
|
|
|
|
const { code, message, data } = response; |
|
|
|
|
|
|
|
if (code === 20000) { |
|
|
|
|
|
|
|
resolve(data); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
reject(new Error(message)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
api.setServerAddress = setServerAddress; |
|
|
|
|
|
|
|
api.getServerAddress = getServerAddress; |
|
|
|
|
|
|
|
api.getVersion = getVersion; |
|
|
|
|
|
|
|
api.uploadBookmarks = uploadBookmarks; |
|
|
|
|
|
|
|
api.downloadBookmarks = downloadBookmarks; |
|
|
|
|
|
|
|
})(serverApi); |
|
|
|
|
|
|
|
|
|
|
|
function Node() { |
|
|
|
function Node() { |
|
|
|
/** |
|
|
|
/** |
|
|
|
* id ( string ) |
|
|
|
* id ( string ) |
|
|
@ -105,11 +165,11 @@ function Node() { |
|
|
|
/** |
|
|
|
/** |
|
|
|
* 书签节点创建时的时间戳 |
|
|
|
* 书签节点创建时的时间戳 |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
this.dateAdded = 0; |
|
|
|
this.dateAdded = undefined; |
|
|
|
/** |
|
|
|
/** |
|
|
|
* 书签文件夹内容的最后更新时间戳,书签节点没有此属性 |
|
|
|
* 书签文件夹内容的最后更新时间戳,书签节点没有此属性 |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
this.dateGroupModified = 0; |
|
|
|
this.dateGroupModified = undefined; |
|
|
|
/** |
|
|
|
/** |
|
|
|
* 书签在父节点中的索引,根节点没有此属性 |
|
|
|
* 书签在父节点中的索引,根节点没有此属性 |
|
|
|
*/ |
|
|
|
*/ |
|
|
@ -143,7 +203,7 @@ let BookmarkTreeNodeList = []; |
|
|
|
const BOOKMARK = 0; |
|
|
|
const BOOKMARK = 0; |
|
|
|
const BOOKEMARK_FOLDER = 1; |
|
|
|
const BOOKEMARK_FOLDER = 1; |
|
|
|
const PROTO = "http"; |
|
|
|
const PROTO = "http"; |
|
|
|
const SERVER_ADDRESS = "127.0.0.1"; |
|
|
|
const SERVER_ADDRESS = "192.168.31.161"; |
|
|
|
const SERVER_PORT = "3000"; |
|
|
|
const SERVER_PORT = "3000"; |
|
|
|
const SERVER_URL = `${PROTO}://${SERVER_ADDRESS}:${SERVER_PORT}`; |
|
|
|
const SERVER_URL = `${PROTO}://${SERVER_ADDRESS}:${SERVER_PORT}`; |
|
|
|
|
|
|
|
|
|
|
@ -162,8 +222,6 @@ async function getBookmarkMap() { |
|
|
|
let bookmarkNode = new Node(); |
|
|
|
let bookmarkNode = new Node(); |
|
|
|
bookmarkNode.id = node.id; |
|
|
|
bookmarkNode.id = node.id; |
|
|
|
bookmarkNode.parentId = node.parentId; |
|
|
|
bookmarkNode.parentId = node.parentId; |
|
|
|
// bookmarkNode.dateAdded = node.dateAdded;
|
|
|
|
|
|
|
|
// bookmarkNode.dateGroupModified = node.dateGroupModified;
|
|
|
|
|
|
|
|
bookmarkNode.index = node.index; |
|
|
|
bookmarkNode.index = node.index; |
|
|
|
bookmarkNode.title = node.title; |
|
|
|
bookmarkNode.title = node.title; |
|
|
|
bookmarkNode.url = node.url; |
|
|
|
bookmarkNode.url = node.url; |
|
|
@ -200,76 +258,84 @@ async function getBookmarkMap() { |
|
|
|
return localMap; |
|
|
|
return localMap; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
function tree2List(tree) { |
|
|
|
* 获得浏览器书签的数组 |
|
|
|
let cacheMap = {}; |
|
|
|
*/ |
|
|
|
function add2Map(tree) { |
|
|
|
async function getBookmarkList() { |
|
|
|
for (let item of tree) { |
|
|
|
let localTree = await api.getTreeAsync(); |
|
|
|
// 给书签文件创建group属性
|
|
|
|
let localList = []; |
|
|
|
if (item.id === "0" || item.id === "1" || item.id === "2" || typeof item.dateGroupModified === 'number') { |
|
|
|
|
|
|
|
item.group = true |
|
|
|
async function addToList(localTree) { |
|
|
|
|
|
|
|
for (let i = 0; i < localTree.length; i++) { |
|
|
|
|
|
|
|
let node = localTree[i]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let bookmarkNode = new Node(); |
|
|
|
|
|
|
|
bookmarkNode.id = node.id; |
|
|
|
|
|
|
|
bookmarkNode.parentId = node.parentId; |
|
|
|
|
|
|
|
// bookmarkNode.dateAdded = node.dateAdded;
|
|
|
|
|
|
|
|
// bookmarkNode.dateGroupModified = node.dateGroupModified;
|
|
|
|
|
|
|
|
bookmarkNode.index = node.index; |
|
|
|
|
|
|
|
bookmarkNode.title = node.title; |
|
|
|
|
|
|
|
bookmarkNode.url = node.url; |
|
|
|
|
|
|
|
bookmarkNode.type = |
|
|
|
|
|
|
|
typeof node.dateGroupModified === "undefined" |
|
|
|
|
|
|
|
? BOOKMARK |
|
|
|
|
|
|
|
: BOOKEMARK_FOLDER; |
|
|
|
|
|
|
|
bookmarkNode.root = typeof node.parentId === "undefined"; |
|
|
|
|
|
|
|
// 根节点没有 dateGroupModified 属性,但是应该是个书签组类型
|
|
|
|
|
|
|
|
if (bookmarkNode.root) { |
|
|
|
|
|
|
|
bookmarkNode.type = BOOKEMARK_FOLDER; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
cacheMap[item.id] = item; |
|
|
|
|
|
|
|
if (Array.isArray(item.children)) { |
|
|
|
|
|
|
|
add2Map(item.children); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
add2Map(tree); |
|
|
|
|
|
|
|
|
|
|
|
localList.push(bookmarkNode); |
|
|
|
for (let key in cacheMap) { |
|
|
|
|
|
|
|
let item = cacheMap[key]; |
|
|
|
if (Array.isArray(node.children) && node.children.length > 0) { |
|
|
|
if (typeof item.parentId === "string") { |
|
|
|
await addToList(node.children) |
|
|
|
if (!Array.isArray(cacheMap[item.parentId].nodes)) { |
|
|
|
|
|
|
|
cacheMap[item.parentId].nodes = []; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
cacheMap[item.parentId].nodes.push(item.id); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
await addToList(localTree); |
|
|
|
let list = []; |
|
|
|
return localList; |
|
|
|
for (let key in cacheMap) { |
|
|
|
|
|
|
|
const item = cacheMap[key]; |
|
|
|
|
|
|
|
list.push({ |
|
|
|
|
|
|
|
id: item.id, |
|
|
|
|
|
|
|
parentId: item.parentId, |
|
|
|
|
|
|
|
title: item.title, |
|
|
|
|
|
|
|
url: item.url, |
|
|
|
|
|
|
|
index: item.index, |
|
|
|
|
|
|
|
group: item.group, |
|
|
|
|
|
|
|
nodes: item.nodes, |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return list; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* 获得浏览器书签的数组 |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
async function getBookmarkList() { |
|
|
|
|
|
|
|
let localTree = await api.getTreeAsync(); |
|
|
|
|
|
|
|
return tree2List(localTree); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* 数组转map表 |
|
|
|
* 数组转map表 |
|
|
|
* @param {Object} bookmarkList
|
|
|
|
* @param {Object} bookmarkList |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
function listToMap(bookmarkList) { |
|
|
|
function listToMap(bookmarkList) { |
|
|
|
let map = {} |
|
|
|
let map = {}; |
|
|
|
for(let i = 0; i < bookmarkList.length; i++) { |
|
|
|
for (let i = 0; i < bookmarkList.length; i++) { |
|
|
|
let bookmark = bookmarkList[i] |
|
|
|
let bookmark = bookmarkList[i]; |
|
|
|
map[bookmark.id] = bookmark |
|
|
|
map[bookmark.id] = bookmark; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function getDepth(bookmark, depth) { |
|
|
|
function getDepth(bookmark, depth) { |
|
|
|
if (parseInt(bookmark.id) === 0) { |
|
|
|
if (parseInt(bookmark.id) === 0) { |
|
|
|
return depth |
|
|
|
return depth; |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
return getDepth(map[bookmark.parentId], depth + 1) |
|
|
|
return getDepth(map[bookmark.parentId], depth + 1); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
let finalMap = {} |
|
|
|
let finalMap = {}; |
|
|
|
for(let i = 0; i < bookmarkList.length; i++) { |
|
|
|
for (let i = 0; i < bookmarkList.length; i++) { |
|
|
|
let bookmark = bookmarkList[i] |
|
|
|
let bookmark = bookmarkList[i]; |
|
|
|
let finalDepth = getDepth(bookmark, 0) |
|
|
|
let finalDepth = getDepth(bookmark, 0); |
|
|
|
if (!Array.isArray(finalMap[finalDepth])) { |
|
|
|
if (!Array.isArray(finalMap[finalDepth])) { |
|
|
|
finalMap[finalDepth] = [] |
|
|
|
finalMap[finalDepth] = []; |
|
|
|
} |
|
|
|
} |
|
|
|
finalMap[finalDepth].push(bookmark) |
|
|
|
finalMap[finalDepth].push(bookmark); |
|
|
|
} |
|
|
|
} |
|
|
|
return finalMap |
|
|
|
return finalMap; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
async function removeAllBookmarks() { |
|
|
|
async function removeAllBookmarks() { |
|
|
@ -304,7 +370,7 @@ async function restore(remoteBookmarkArray) { |
|
|
|
parentId: getNewbookmarkId(array[depth - 1], bookmark.parentId), |
|
|
|
parentId: getNewbookmarkId(array[depth - 1], bookmark.parentId), |
|
|
|
index: bookmark.index, |
|
|
|
index: bookmark.index, |
|
|
|
title: bookmark.title, |
|
|
|
title: bookmark.title, |
|
|
|
url: bookmark.url |
|
|
|
url: bookmark.url, |
|
|
|
}); |
|
|
|
}); |
|
|
|
bookmark.newId = newBookmark.id; |
|
|
|
bookmark.newId = newBookmark.id; |
|
|
|
console.log( |
|
|
|
console.log( |
|
|
@ -319,30 +385,25 @@ async function restore(remoteBookmarkArray) { |
|
|
|
|
|
|
|
|
|
|
|
$("#upload").on("click", async () => { |
|
|
|
$("#upload").on("click", async () => { |
|
|
|
let bookmarkArray = await getBookmarkList(); |
|
|
|
let bookmarkArray = await getBookmarkList(); |
|
|
|
$.ajax({ |
|
|
|
console.log(bookmarkArray) |
|
|
|
type: "POST", |
|
|
|
serverApi.uploadBookmarks({ |
|
|
|
url: `${SERVER_URL}/bookmarks`, |
|
|
|
bookmarks: bookmarkArray |
|
|
|
contentType: "application/json;charset=utf-8", |
|
|
|
|
|
|
|
dataType: "json", |
|
|
|
|
|
|
|
data: JSON.stringify(bookmarkArray), |
|
|
|
|
|
|
|
success: function() {}, |
|
|
|
|
|
|
|
error: function() {} |
|
|
|
|
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
$("#download").on("click", function() { |
|
|
|
$("#download").on("click", async () => { |
|
|
|
$.ajax({ |
|
|
|
const bookmarkArray = await serverApi.downloadBookmarks(); |
|
|
|
type: "GET", |
|
|
|
console.log(bookmarkArray); |
|
|
|
url: `${SERVER_URL}/bookmarks`, |
|
|
|
|
|
|
|
success: function(result) { |
|
|
|
|
|
|
|
if (result.code === 0) { |
|
|
|
|
|
|
|
restore(result.data); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
$("#test").on("click", async () => { |
|
|
|
$("#test").on("click", async () => { |
|
|
|
let array = await getBookmarkList(); |
|
|
|
let array = await getBookmarkList(); |
|
|
|
console.log(array); |
|
|
|
console.log(array); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$("#connect").on("click", async () => { |
|
|
|
|
|
|
|
const serverAddress = $("#server").val() || SERVER_URL; |
|
|
|
|
|
|
|
serverApi.setServerAddress(serverAddress); |
|
|
|
|
|
|
|
const version = await serverApi.getVersion(); |
|
|
|
|
|
|
|
$("#version").html(version); |
|
|
|
|
|
|
|
}); |