feat: SurfSense extension is now migrated to Plasmo. It supports all the browsers now.

This commit is contained in:
DESKTOP-RTLN3BA\$punk 2024-08-24 02:11:17 -07:00
parent bd91c5800a
commit 47a88f558f
39 changed files with 4 additions and 11596 deletions

3
.gitmodules vendored
View file

@ -1,3 +1,6 @@
[submodule "SurfSense-Frontend"]
path = SurfSense-Frontend
url = https://github.com/MODSetter/SurfSense-Frontend.git
[submodule "ss-cross-browser-extension"]
path = ss-cross-browser-extension
url = https://github.com/MODSetter/ss-cross-browser-extension.git

View file

@ -1,4 +0,0 @@
npm-debug.log
node_modules/
dist/
tmp/

View file

@ -1,12 +0,0 @@
{
"typescript.tsdk": "./node_modules/typescript/lib",
"files.eol": "\n",
"json.schemas": [
{
"fileMatch": [
"/manifest.json"
],
"url": "http://json.schemastore.org/chrome-manifest"
}
]
}

View file

@ -1,33 +0,0 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"command": "npm",
"tasks": [
{
"label": "install",
"type": "shell",
"command": "npm",
"args": ["install"]
},
{
"label": "update",
"type": "shell",
"command": "npm",
"args": ["update"]
},
{
"label": "test",
"type": "shell",
"command": "npm",
"args": ["run", "test"]
},
{
"label": "build",
"type": "shell",
"group": "build",
"command": "npm",
"args": ["run", "watch"]
}
]
}

View file

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2018 Tomofumi Chiba
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -1,70 +0,0 @@
# Chrome Extension TypeScript Starter
![build](https://github.com/chibat/chrome-extension-typescript-starter/workflows/build/badge.svg)
Chrome Extension, TypeScript and Visual Studio Code
## Prerequisites
* [node + npm](https://nodejs.org/) (Current Version)
## Option
* [Visual Studio Code](https://code.visualstudio.com/)
## Includes the following
* TypeScript
* Webpack
* React
* Jest
* Example Code
* Chrome Storage
* Options Version 2
* content script
* count up badge number
* background
## Project Structure
* src/typescript: TypeScript source files
* src/assets: static files
* dist: Chrome Extension directory
* dist/js: Generated JavaScript files
## Setup
```
npm install
```
## Import as Visual Studio Code project
...
## Build
```
npm run build
```
## Build in watch mode
### terminal
```
npm run watch
```
### Visual Studio Code
Run watch mode.
type `Ctrl + Shift + B`
## Load extension to chrome
Load `dist` directory
## Test
`npx jest` or `npm run test`

View file

@ -1,8 +0,0 @@
module.exports = {
"roots": [
"src"
],
"transform": {
"^.+\\.ts$": ["ts-jest", { tsconfig: "tsconfig.test.json" }]
},
};

File diff suppressed because it is too large Load diff

View file

@ -1,52 +0,0 @@
{
"name": "chrome-extension-typescript-starter",
"version": "1.0.0",
"description": "chrome-extension-typescript-starter",
"main": "index.js",
"scripts": {
"watch": "webpack --config webpack/webpack.dev.js --watch",
"build": "webpack --config webpack/webpack.prod.js",
"clean": "rimraf dist",
"test": "npx jest",
"style": "prettier --write \"src/**/*.{ts,tsx}\""
},
"author": "",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/chibat/chrome-extension-typescript-starter.git"
},
"dependencies": {
"dom-to-semantic-markdown": "^1.2.0",
"postcss-loader": "^8.1.1",
"react": "^18.2.0",
"react-chrome-extension-router": "^1.4.0",
"react-dom": "^18.2.0",
"react-hooks-global-state": "^2.1.0",
"react-router-dom": "^6.26.0",
"react-toastify": "^10.0.5"
},
"devDependencies": {
"@types/chrome": "0.0.158",
"@types/jest": "^29.5.0",
"@types/json2md": "^1.5.4",
"@types/react": "^18.0.29",
"@types/react-dom": "^18.0.11",
"autoprefixer": "^10.4.19",
"copy-webpack-plugin": "^9.0.1",
"css-loader": "^7.1.2",
"glob": "^7.1.6",
"jest": "^29.5.0",
"postcss": "^8.4.40",
"prettier": "^2.2.1",
"rimraf": "^3.0.2 ",
"style-loader": "^4.0.0",
"tailwindcss": "^3.4.7",
"ts-jest": "^29.1.0",
"ts-loader": "^8.0.0",
"typescript": "^5.0.4",
"webpack": "^5.76.0",
"webpack-cli": "^4.0.0",
"webpack-merge": "^5.0.0"
}
}

4622
extension/pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

@ -1,6 +0,0 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 587 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

View file

@ -1,38 +0,0 @@
{
"manifest_version": 3,
"name": "SurfSense",
"description": "Extension to collect Browsing History for SurfSense.",
"version": "0.0.3",
"action": {
"default_popup": "popup.html"
},
"icons": {
"16": "icon-16.png",
"32": "icon-32.png",
"48": "icon-48.png",
"128": "icon-128.png"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["js/content_script.js"]
}
],
"background": {
"service_worker": "js/background.js"
},
"permissions": [
"storage",
"scripting",
"unlimitedStorage"
],
"host_permissions": [
"<all_urls>"
]
}

View file

@ -1,12 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>My Test Extension Options</title>
<script src="js/vendor.js"></script>
</head>
<body>
<div id="root"></div>
<script src="js/options.js"></script>
</body>
</html>

View file

@ -1,13 +0,0 @@
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Getting Started Extension's Popup</title>
<script src="js/vendor.js"></script>
</head>
<body>
<div id="root"></div>
<script src="js/popup.js"></script>
</body>
</html>

View file

@ -1,9 +0,0 @@
import { sum } from "../sum";
test("1 + 1 = 2", () => {
expect(sum(1, 1)).toBe(2);
});
test("1 + 2 != 2", () => {
expect(sum(1, 2)).not.toBe(2);
});

View file

@ -1,39 +0,0 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
.loading{
margin: 0;
box-sizing: border-box;
display: flex;
justify-content: center;
align-items: center;
height: 80vh;
}
body {
min-width: 400px;
}
.btn1 {
width: 50px;
height: 50px;
border-radius: 25px;
border: none;
background-color: hotpink;
color: white;
font-size: 1.2em;
}
@keyframes move {
25% {
transform: translateY(50px);
}
50% {
background-color: dodgerblue;
transform: translateY(0px);
}
75% {
transform: translateY(-50px);
}
}

View file

@ -1,454 +0,0 @@
import {
initWebHistory,
getRenderedHtml,
initQueues,
} from "./commons";
import { WebHistory } from "./interfaces";
chrome.tabs.onCreated.addListener(async (tab: any) => {
try {
await initWebHistory(tab.id);
await initQueues(tab.id);
} catch (error) {
console.log(error);
}
});
chrome.tabs.onUpdated.addListener(
async (tabId: number, changeInfo: any, tab: any) => {
if (changeInfo.status === "complete" && tab.url) {
await initWebHistory(tab.id);
await initQueues(tab.id);
const result = await chrome.scripting.executeScript({
// @ts-ignore
target: { tabId: tab.id },
// @ts-ignore
function: getRenderedHtml,
});
let toPushInTabHistory = result[0].result; // const { renderedHtml, title, url, entryTime } = result[0].result;
let urlQueueListObj = await chrome.storage.local.get(["urlQueueList"]);
let timeQueueListObj = await chrome.storage.local.get(["timeQueueList"]);
urlQueueListObj.urlQueueList
.find((data: WebHistory) => data.tabsessionId === tabId)
.urlQueue.push(toPushInTabHistory.url);
timeQueueListObj.timeQueueList
.find((data: WebHistory) => data.tabsessionId === tabId)
.timeQueue.push(toPushInTabHistory.entryTime);
await chrome.storage.local.set({
urlQueueList: urlQueueListObj.urlQueueList,
});
await chrome.storage.local.set({
timeQueueList: timeQueueListObj.timeQueueList,
});
}
}
);
chrome.tabs.onRemoved.addListener(async (tabId: number, removeInfo: object) => {
let urlQueueListObj = await chrome.storage.local.get(["urlQueueList"]);
let timeQueueListObj = await chrome.storage.local.get(["timeQueueList"]);
if(urlQueueListObj.urlQueueList && timeQueueListObj.timeQueueList){
const urlQueueListToSave = urlQueueListObj.urlQueueList.map((element: WebHistory) => {
if(element.tabsessionId !== tabId){
return element
}
})
const timeQueueListSave = timeQueueListObj.timeQueueList.map((element: WebHistory) => {
if(element.tabsessionId !== tabId){
return element
}
})
await chrome.storage.local.set({
urlQueueList: urlQueueListToSave.filter((item: any) => item),
});
await chrome.storage.local.set({
timeQueueList: timeQueueListSave.filter((item: any) => item),
});
}
});
///// IGONRE THESE COMMENTS THESE CONTAINS SOME IDEAS THAT NEVER WORKED AS INTENTDED
// await initWebHistory(tabId);
// console.log("tab", tab);
// if (tab.status === "loading") {
// if (tab.url) {
// const autotrackerFlag = await chrome.storage.local.get(["autoTracker"]);
// const lastUrlObj = await chrome.storage.local.get(["lastUrl"]);
// if (autotrackerFlag.autoTracker) {
// if (lastUrlObj.lastUrl[tabId] !== "START") {
// console.log("loading");
// console.log(lastUrlObj.lastUrl[tabId]);
// //update last entry duration
// try {
// const lastEntryTimeObj = await chrome.storage.local.get([
// "lastEntryTime",
// ]);
// let webhistoryObj = await chrome.storage.local.get([
// "webhistory",
// ]);
// const webHistoryLength = webhistoryObj.webhistory.find(
// (data: WebHistory) => data.tabsessionId === tabId
// ).tabHistory.length;
// if(webHistoryLength > 0){
// webhistoryObj.webhistory.find(
// (data: WebHistory) => data.tabsessionId === tabId
// ).tabHistory[webHistoryLength - 1].duration =
// Date.now() - lastEntryTimeObj.lastEntryTime[tabId];
// }
// await chrome.storage.local.set({
// webhistory: webhistoryObj.webhistory,
// });
// } catch (error) {
// console.log(error);
// }
// }
// }
// }
// }
// const autotrackerFlag = await chrome.storage.local.get(["autoTracker"]);
// if (!autotrackerFlag.autoTracker) {
// await initURlQueue(tab.id);
// }
// const lastUrl = {
// // @ts-ignore
// [tab.id]: "START",
// };
// // console.log(lastUrl);
// await chrome.storage.local.set({
// lastUrl: lastUrl,
// });
// const lastEntryTime = {
// // @ts-ignore
// [tab.id]: Date.now(),
// };
// // console.log(lastUrl);
// await chrome.storage.local.set({
// lastEntryTime: lastEntryTime,
// });
// let webhistoryObj = await chrome.storage.local.get(["webhistory"]);
// const webHistoryOfTabId = webhistoryObj.webhistory.filter(
// (data: WebHistory) => {
// return data.tabsessionId === tab.id;
// }
// );
// let tabhistory = webHistoryOfTabId[0].tabHistory;
// if (tabhistory.length === 0) {
// toPushInTabHistory.reffererUrl = "START";
// } else {
// toPushInTabHistory.reffererUrl = tabhistory[tabhistory.length - 1].url;
// tabhistory[tabhistory.length - 1].duration =
// toPushInTabHistory.entryTime -
// tabhistory[tabhistory.length - 1].entryTime;
// }
// tabhistory.push(toPushInTabHistory);
// //Update Webhistory
// try {
// webhistoryObj.webhistory.find(
// (data: WebHistory) => data.tabsessionId === tab.id
// ).tabHistory = tabhistory;
// await chrome.storage.local.set({
// webhistory: webhistoryObj.webhistory,
// });
// } catch (error) {
// console.log(error);
// }
// const autotrackerFlag = await chrome.storage.local.get(["autoTracker"]);
// if (autotrackerFlag.autoTracker) {
// const result = await chrome.scripting.executeScript({
// // @ts-ignore
// target: { tabId: tab.id },
// // @ts-ignore
// function: getRenderedHtml,
// });
// let toPushInTabHistory = result[0].result; // const { renderedHtml, title, url, entryTime } = result[0].result;
// // //Updates 'tabhistory'
// let webhistoryObj = await chrome.storage.local.get(["webhistory"]);
// const webHistoryOfTabId = webhistoryObj.webhistory.filter(
// (data: WebHistory) => {
// return data.tabsessionId === tab.id;
// }
// );
// let tabhistory = webHistoryOfTabId[0].tabHistory;
// // let lastUrlObj = await chrome.storage.local.get(["lastUrl"]);
// const lastEntryTimeObj = await chrome.storage.local.get([
// "lastEntryTime",
// ]);
// lastEntryTimeObj.lastEntryTime[tabId] = Date.now();
// await chrome.storage.local.set({
// lastEntryTime: lastEntryTimeObj.lastEntryTime,
// });
// //When first entry
// if (tabhistory.length === 0) {
// let lastUrlObj = await chrome.storage.local.get(["lastUrl"]);
// lastUrlObj.lastUrl[tabId] = tab.url;
// await chrome.storage.local.set({
// lastUrl: lastUrlObj.lastUrl,
// });
// toPushInTabHistory.reffererUrl = "START";
// toPushInTabHistory.entryTime = Date.now();
// tabhistory.push(toPushInTabHistory);
// try {
// webhistoryObj.webhistory.find(
// (data: WebHistory) => data.tabsessionId === tab.id
// ).tabHistory = tabhistory;
// await chrome.storage.local.set({
// webhistory: webhistoryObj.webhistory,
// });
// } catch (error) {
// console.log(error);
// }
// } else {
// const lastUrlObj = await chrome.storage.local.get(["lastUrl"]);
// toPushInTabHistory.reffererUrl = lastUrlObj.lastUrl[tabId];
// toPushInTabHistory.entryTime = Date.now();
// tabhistory.push(toPushInTabHistory);
// try {
// webhistoryObj.webhistory.find(
// (data: WebHistory) => data.tabsessionId === tab.id
// ).tabHistory = tabhistory;
// // console.log("webhistory",webhistoryObj);
// await chrome.storage.local.set({
// webhistory: webhistoryObj.webhistory,
// });
// } catch (error) {
// console.log(error);
// }
// lastUrlObj.lastUrl[tabId] = tab.url;
// await chrome.storage.local.set({
// lastUrl: lastUrlObj.lastUrl,
// });
// }
// } else {
// await initURlQueue(tab.id);
// let urlQueue = await chrome.storage.local.get(["urlQueue"]);
// // console.log("urlQueue", urlQueue);
// urlQueue.urlQueue[tabId].push(tab.url)
// urlQueue.urlQueue[tabId] = [...new Set(urlQueue.urlQueue[tabId])]
// await chrome.storage.local.set({
// urlQueue: urlQueue.urlQueue,
// });
// const lastEntryTimeObj = await chrome.storage.local.get([
// "lastEntryTime",
// ]);
// lastEntryTimeObj.lastEntryTime[tabId] = Date.now();
// await chrome.storage.local.set({
// lastEntryTime: lastEntryTimeObj.lastEntryTime,
// });
// }
// chrome.tabs.onRemoved.addListener(async (tabId: number, removeInfo: object) => {
// const autotrackerFlag = await chrome.storage.local.get(["autoTracker"]);
// //duration, referURL edge conditions
// let webhistoryObj = await chrome.storage.local.get(["webhistory"]);
// const webHistoryLength = webhistoryObj.webhistory.find(
// (data: WebHistory) => data.tabsessionId === tabId
// ).tabHistory.length;
// if (webHistoryLength > 0) {
// if (
// !webhistoryObj.webhistory.find(
// (data: WebHistory) => data.tabsessionId === tabId
// ).tabHistory[webHistoryLength - 1].duration
// ) {
// webhistoryObj.webhistory.find(
// (data: WebHistory) => data.tabsessionId === tabId
// ).tabHistory[webHistoryLength - 1].duration =
// Date.now() -
// webhistoryObj.webhistory.find(
// (data: WebHistory) => data.tabsessionId === tabId
// ).tabHistory[webHistoryLength - 1].entryTime;
// }
// }
// let urlQueueLocal = await chrome.storage.local.get(["urlQueue"]);
// let timeQueueLocal = await chrome.storage.local.get(["timeQueue"]);
// delete urlQueueLocal.urlQueue[tabId]
// delete timeQueueLocal.timeQueue[tabId]
// await chrome.storage.local.set({
// urlQueue: urlQueueLocal.urlQueue,
// });
// await chrome.storage.local.set({
// timeQueue: timeQueueLocal.timeQueue,
// });
// // if (autotrackerFlag.autoTracker) {
// // try {
// // const lastEntryTimeObj = await chrome.storage.local.get([
// // "lastEntryTime",
// // ]);
// // let webhistoryObj = await chrome.storage.local.get(["webhistory"]);
// // const webHistoryLength = webhistoryObj.webhistory.find(
// // (data: WebHistory) => data.tabsessionId === tabId
// // ).tabHistory.length;
// // if (webHistoryLength > 0) {
// // webhistoryObj.webhistory.find(
// // (data: WebHistory) => data.tabsessionId === tabId
// // ).tabHistory[webHistoryLength - 1].duration =
// // Date.now() - lastEntryTimeObj.lastEntryTime[tabId];
// // }
// // await chrome.storage.local.set({
// // webhistory: webhistoryObj.webhistory,
// // });
// // } catch (error) {
// // console.log(error);
// // }
// // } else {
// // await initURlQueue(tabId);
// // let urlQueue = await chrome.storage.local.get(["urlQueue"]);
// // delete urlQueue.urlQueue[tabId];
// // chrome.storage.local.set({
// // urlQueue: urlQueue.urlQueue,
// // });
// // }
// });
// if (tabhistory.length > 0) {
// //updates duration of last entry in 'tabhistory'
// tabhistory[tabhistory.length - 1].duration =
// toPushInTabHistory.entryTime -
// tabhistory[tabhistory.length - 1].entryTime;
// //Update refferer Url
// toPushInTabHistory.reffererUrl = tabhistory[tabhistory.length - 1].url;
// if (tabhistory.length == 1) {
// tabhistory[0].reffererUrl = "START";
// }
// }
// tabhistory.push(toPushInTabHistory);
// //Set Updated tabhistory
// try {
// webhistoryObj.webhistory.find(
// (data: WebHistory) => data.tabsessionId === tab.id
// ).tabHistory = tabhistory;
// // console.log("webhistory",webhistoryObj);
// await chrome.storage.local.set({
// webhistory: webhistoryObj.webhistory,
// });
// } catch (error) {
// console.log(error);
// }
// try {
// let webhistoryObj = await chrome.storage.local.get(["webhistory"]);
// const webHistoryLength = webhistoryObj.webhistory.find(
// (data: WebHistory) => data.tabsessionId === tabId
// ).tabHistory.length;
// const lastWebPageEntryTime = webhistoryObj.webhistory.find(
// (data: WebHistory) => data.tabsessionId === tabId
// ).tabHistory[webHistoryLength - 1].entryTime;
// webhistoryObj.webhistory.find(
// (data: WebHistory) => data.tabsessionId === tabId
// ).tabHistory[webHistoryLength - 1].duration =
// Date.now() - lastWebPageEntryTime;
// //Edge Condition of reffererUrl
// if (webHistoryLength == 1) {
// webhistoryObj.webhistory.find(
// (data: WebHistory) => data.tabsessionId === tabId
// ).tabHistory[0].reffererUrl = "START";
// }
// //Sets 'webhistory'
// try {
// await chrome.storage.local.set({ webhistory: webhistoryObj.webhistory });
// // const result = await chrome.storage.local.get(["webhistory"]);
// // console.log("webhistoryinRemoved",result);
// } catch (error) {
// console.log(error);
// }
// } catch (error) {
// console.log(error);
// }
// await chrome.storage.local.set({ id: tab.id });
// await chrome.storage.local.set({ tabhistory: [] });
// const result = await chrome.storage.local.get(["id"]);
// console.log(result);
// const tabid = await chrome.storage.local.get(["id"]);
// const toPushinWebHostory = {
// tabsessionId: tabid.id,
// tabHistory: tabhistory,
// };
// //Updates 'webhistory'
// const webhistoryObj = await chrome.storage.local.get(["webhistory"]);
// // console.log("WEBH", webhistoryObj);
// const webhistory = webhistoryObj.webhistory;
// webhistory.push(toPushinWebHostory);
// //Sets 'webhistory'
// try {
// await chrome.storage.local.set({ webhistory: webhistory });
// const result = await chrome.storage.local.get(["webhistory"]);
// console.log("RES",result)
// } catch (error) {
// console.log(error);
// }
// try {
// let lastUrlObj = await chrome.storage.local.get(["lastUrl"]);
// // console.log("Before Update", lastUrlObj);
// if(tab.url !== lastUrlObj.lastUrl[tabId]){
// // console.log("Before Update", lastUrlObj);
// lastUrlObj.lastUrl[tabId] = tab.url;
// // console.log("After Update", lastUrlObj);
// await chrome.storage.local.set({
// lastUrl: lastUrlObj.lastUrl,
// });
// //Update DURATION of old url
// }
// // // const lastUrl = await chrome.storage.local.get(["lastUrl"]);
// // await chrome.storage.local.set({
// // lastUrl: lastUrlObj.lastUrl,
// // });
// } catch (error) {
// console.log(error);
// }

View file

@ -1,126 +0,0 @@
import { WebHistory } from "./interfaces";
export const emptyArr: any[] = [];
export const initQueues = async (tabId: number) => {
let urlQueueListObj = await chrome.storage.local.get(["urlQueueList"]);
let timeQueueListObj = await chrome.storage.local.get(["timeQueueList"]);
if(!urlQueueListObj.urlQueueList && !timeQueueListObj.timeQueueList){
await chrome.storage.local.set({
urlQueueList: [{tabsessionId: tabId, urlQueue: []}],
});
await chrome.storage.local.set({
timeQueueList: [{tabsessionId: tabId, timeQueue: []}],
});
return
}
if(urlQueueListObj.urlQueueList && timeQueueListObj.timeQueueList){
const isUrlQueueThere = urlQueueListObj.urlQueueList.find((data: WebHistory) => data.tabsessionId === tabId)
const isTimeQueueThere = timeQueueListObj.timeQueueList.find((data: WebHistory) => data.tabsessionId === tabId)
if(!isUrlQueueThere){
urlQueueListObj.urlQueueList.push({tabsessionId: tabId, urlQueue: []})
await chrome.storage.local.set({
urlQueueList: urlQueueListObj.urlQueueList,
});
}
if(!isTimeQueueThere){
timeQueueListObj.timeQueueList.push({tabsessionId: tabId, timeQueue: []})
await chrome.storage.local.set({
timeQueueList: timeQueueListObj.timeQueueList,
});
}
return
}
};
export function getRenderedHtml() {
return {
url: window.location.href,
entryTime: Date.now(),
title: document.title,
renderedHtml: document.documentElement.outerHTML,
};
}
export const initWebHistory = async (tabId: number) => {
const result = await chrome.storage.local.get(["webhistory"]);
if (!result.webhistory) {
await chrome.storage.local.set({ webhistory: emptyArr });
return
}
const ifIdExists = result.webhistory.find(
(data: WebHistory) => data.tabsessionId === tabId
);
if (ifIdExists === undefined) {
let webHistory = result.webhistory;
const initData = {
tabsessionId: tabId,
tabHistory: emptyArr,
};
webHistory.push(initData)
try {
await chrome.storage.local.set({ webhistory: webHistory });
return ;
} catch (error) {
console.log(error)
}
} else {
return;
}
};
export function toIsoString(date: Date) {
var tzo = -date.getTimezoneOffset(),
dif = tzo >= 0 ? '+' : '-',
pad = function (num: number) {
return (num < 10 ? '0' : '') + num;
};
return date.getFullYear() +
'-' + pad(date.getMonth() + 1) +
'-' + pad(date.getDate()) +
'T' + pad(date.getHours()) +
':' + pad(date.getMinutes()) +
':' + pad(date.getSeconds()) +
dif + pad(Math.floor(Math.abs(tzo) / 60)) +
':' + pad(Math.abs(tzo) % 60);
}
export const webhistoryToLangChainDocument = (tabId: number, tabHistory: any[]) => {
let toSaveFinally = []
for (let j = 0; j < tabHistory.length; j++) {
const mtadata = {
"BrowsingSessionId": `${tabId}`,
"VisitedWebPageURL": `${tabHistory[j].url}`,
"VisitedWebPageTitle": `${tabHistory[j].title}`,
"VisitedWebPageDateWithTimeInISOString": `${toIsoString(new Date(tabHistory[j].entryTime))}`,
"VisitedWebPageReffererURL": `${tabHistory[j].reffererUrl}`,
"VisitedWebPageVisitDurationInMilliseconds": tabHistory[j].duration,
}
toSaveFinally.push({
metadata: mtadata,
pageContent: tabHistory[j].pageContentMarkdown
})
}
return toSaveFinally
}

View file

@ -1,2 +0,0 @@
export const API_SECRET_KEY = "surfsense"
export const BACKEND_URL = "http://127.0.0.1:8000"

View file

@ -1,4 +0,0 @@
export interface WebHistory {
tabsessionId: number;
tabHistory: any[];
}

View file

@ -1,77 +0,0 @@
// import React, { useEffect, useState } from "react";
// import { createRoot } from "react-dom/client";
// const Options = () => {
// const [color, setColor] = useState<string>("");
// const [status, setStatus] = useState<string>("");
// const [like, setLike] = useState<boolean>(false);
// useEffect(() => {
// // Restores select box and checkbox state using the preferences
// // stored in chrome.storage.
// chrome.storage.sync.get(
// {
// favoriteColor: "red",
// likesColor: true,
// },
// (items) => {
// setColor(items.favoriteColor);
// setLike(items.likesColor);
// }
// );
// }, []);
// const saveOptions = () => {
// // Saves options to chrome.storage.sync.
// chrome.storage.sync.set(
// {
// favoriteColor: color,
// likesColor: like,
// },
// () => {
// // Update status to let user know options were saved.
// setStatus("Options saved.");
// const id = setTimeout(() => {
// setStatus("");
// }, 1000);
// return () => clearTimeout(id);
// }
// );
// };
// return (
// <>
// <div>
// Favorite color: <select
// value={color}
// onChange={(event) => setColor(event.target.value)}
// >
// <option value="red">red</option>
// <option value="green">green</option>
// <option value="blue">blue</option>
// <option value="yellow">yellow</option>
// </select>
// </div>
// <div>
// <label>
// <input
// type="checkbox"
// checked={like}
// onChange={(event) => setLike(event.target.checked)}
// />
// I like colors.
// </label>
// </div>
// <div>{status}</div>
// <button onClick={saveOptions}>Save</button>
// </>
// );
// };
// const root = createRoot(document.getElementById("root")!);
// root.render(
// <React.StrictMode>
// <Options />
// </React.StrictMode>
// );

View file

@ -1,75 +0,0 @@
import React, { useState } from "react";
import { goTo } from "react-chrome-extension-router";
import { Popup } from "../popup";
export const FillEnvVariables = () => {
const [neourl, setNeourl] = useState('');
const [neouser, setNeouser] = useState('');
const [neopass, setNeopass] = useState('');
const [openaikey, setOpenaiKey] = useState('');
const [error, setError] = useState('');
const [loading, setLoading] = useState(false);
const validateForm = () => {
if (!neourl || !neouser || !neopass || !openaikey) {
setError('All values are required');
return false;
}
setError('');
return true;
};
const handleSubmit = async (event: { preventDefault: () => void; }) => {
event.preventDefault();
if (!validateForm()) return;
setLoading(true);
localStorage.setItem('neourl', neourl);
localStorage.setItem('neouser', neouser);
localStorage.setItem('neopass', neopass);
localStorage.setItem('openaikey', openaikey);
setLoading(false);
goTo(Popup)
};
return (
<section className="dark bg-gray-50 dark:bg-gray-900">
<div className="flex flex-col items-center justify-center px-6 py-8 mx-auto md:h-screen lg:py-0">
<a href="#" className="flex items-center mb-6 text-2xl font-semibold text-gray-900 dark:text-white">
<img className="w-8 h-8 mr-2" src="./icon-128.png" alt="logo" />
SurfSense
</a>
<div className="w-full bg-white rounded-lg shadow dark:border md:mt-0 sm:max-w-md xl:p-0 dark:bg-gray-800 dark:border-gray-700">
<div className="p-6 space-y-4 md:space-y-6 sm:p-8">
<h1 className="text-xl font-bold leading-tight tracking-tight text-gray-900 md:text-2xl dark:text-white">
Required Values
</h1>
<form className="space-y-4 md:space-y-6" onSubmit={handleSubmit}>
<div>
<label className="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Neo4J URL</label>
<input type="text" value={neourl} onChange={(e) => setNeourl(e.target.value)} name="neourl" id="neourl" className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="neo4j url" />
</div>
<div>
<label className="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Neo4J Username</label>
<input type="text" value={neouser} onChange={(e) => setNeouser(e.target.value)} name="neouser" id="neouser" className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="neo4j username" />
</div>
<div>
<label className="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Neo4J Password</label>
<input type="text" value={neopass} onChange={(e) => setNeopass(e.target.value)} name="neopass" id="neopass" placeholder="••••••••" className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" />
</div>
<div>
<label className="block mb-2 text-sm font-medium text-gray-900 dark:text-white">OpenAI API Key</label>
<input type="text" value={openaikey} onChange={(e) => setOpenaiKey(e.target.value)} name="openaikey" id="openaikey" className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="OpenAI API Key" />
</div>
<button type="submit" className="mt-4 w-full text-white bg-primary-600 hover:bg-primary-700 focus:ring-4 focus:outline-none focus:ring-primary-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800">{loading ? 'Saving....' : 'Save & Proceed'}</button>
{error && <p style={{ color: 'red' }}>{error}</p>}
</form>
</div>
</div>
</div>
</section>
)
}

View file

@ -1,28 +0,0 @@
import React from 'react'
const Loading = () => {
return (
<><div className="flex flex-col items-center justify-center px-6 pt-2 pb-12 mx-auto md:h-screen lg:py-0">
<div className="flex items-center mb-6 text-2xl font-semibold text-gray-900 dark:text-white">
<img className="w-8 h-8 mr-2" src="./icon-128.png" alt="logo" />
SurfSense
</div>
<div className="loading">
{"S A V I N G".split(" ").map((v, i) => (
<button
className="btn1"
style={{ animation: `move linear 0.9s infinite ${i / 10}s` }}
key={v}
>
{v}
</button>
))}
</div>
</div>
</>
)
}
export default Loading

View file

@ -1,95 +0,0 @@
import React, { useState } from "react";
import { goTo } from "react-chrome-extension-router";
import { Popup } from "../popup";
import { BACKEND_URL } from "../env";
export const LoginForm = () => {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const [error, setError] = useState('');
const [loading, setLoading] = useState(false);
const validateForm = () => {
if (!username || !password) {
setError('Username and password are required');
return false;
}
setError('');
return true;
};
const handleSubmit = async (event: { preventDefault: () => void; }) => {
event.preventDefault();
if (!validateForm()) return;
setLoading(true);
const formDetails = new URLSearchParams();
formDetails.append('username', username);
formDetails.append('password', password);
try {
const response = await fetch(`${BACKEND_URL}/token`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: formDetails,
});
setLoading(false);
if (response.ok) {
const data = await response.json();
localStorage.setItem('token', data.access_token);
goTo(Popup);
} else {
const errorData = await response.json();
setError(errorData.detail || 'Authentication failed!');
}
} catch (error) {
setLoading(false);
setError('An error occurred. Please try again later.');
}
};
// const goToRegister = async () => {
// console.log("Reg")
// goTo(RegisterForm)
// }
return (
<>
<section className="dark bg-gray-50 dark:bg-gray-900">
{/* <div onClick={() => clearMem}>CLEAR MEM</div> */}
<div className="flex flex-col items-center justify-center px-6 py-8 mx-auto md:h-screen lg:py-0">
<a href="#" className="flex items-center mb-6 text-2xl font-semibold text-gray-900 dark:text-white">
<img className="w-8 h-8 mr-2" src={"./icon-128.png"} alt="logo" />
SurfSense
</a>
<div className="w-full bg-white rounded-lg shadow dark:border md:mt-0 sm:max-w-md xl:p-0 dark:bg-gray-800 dark:border-gray-700">
<div className="p-6 space-y-4 md:space-y-6 sm:p-8">
<h1 className="text-xl font-bold leading-tight tracking-tight text-gray-900 md:text-2xl dark:text-white">
Sign in to your account
</h1>
<form className="space-y-4 md:space-y-6" onSubmit={handleSubmit}>
<div>
<label className="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Username</label>
<input type="text" value={username} onChange={(e) => setUsername(e.target.value)} name="email" id="email" className="bg-gray-50 border border-gray-300 text-gray-900 rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="name" />
</div>
<div>
<label className="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Password</label>
<input type="password" value={password} onChange={(e) => setPassword(e.target.value)} name="password" id="password" placeholder="••••••••" className="bg-gray-50 border border-gray-300 text-gray-900 rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" />
</div>
<button type="submit" disabled={loading} className="w-full text-white bg-primary-600 hover:bg-primary-700 focus:ring-4 focus:outline-none focus:ring-primary-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800">{loading ? 'Logging in...' : 'Login'}</button>
<p className="text-sm font-light text-gray-500 dark:text-gray-400">
Dont have an account yet? <a href="https://www.surfsense.net/signup" className="font-medium text-primary-600 hover:underline dark:text-primary-500" >Sign up</a>
</p>
{error && <p style={{ color: 'red' }}>{error}</p>}
</form>
</div>
</div>
</div>
</section>
</>
);
}

View file

@ -1,600 +0,0 @@
import React, { useEffect, useState } from "react";
import {
goTo,
Router,
} from 'react-chrome-extension-router';
import { createRoot } from "react-dom/client";
import { ToastContainer, toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import "./assets/tailwind.css"
import { convertHtmlToMarkdown } from "dom-to-semantic-markdown";
import { WebHistory } from "./interfaces";
import { webhistoryToLangChainDocument, getRenderedHtml, emptyArr } from "./commons";
import Loading from "./pages/Loading";
import { LoginForm } from "./pages/LoginForm";
import { FillEnvVariables } from "./pages/EnvVarSettings";
import { API_SECRET_KEY, BACKEND_URL } from "./env";
export async function clearMem(): Promise<void> {
try {
let webHistory = await chrome.storage.local.get(["webhistory"]);
let urlQueue = await chrome.storage.local.get(["urlQueueList"]);
let timeQueue = await chrome.storage.local.get(["timeQueueList"]);
if (!webHistory.webhistory) {
return
}
//Main Cleanup COde
chrome.tabs.query({}, async (tabs) => {
//Get Active Tabs Ids
// console.log("Event Tabs",tabs)
let actives = tabs.map((tab) => {
if (tab.id) {
return tab.id
}
})
actives = actives.filter((item: any) => item)
//Only retain which is still active
const newHistory = webHistory.webhistory.map((element: any) => {
//@ts-ignore
if (actives.includes(element.tabsessionId)) {
return element
}
})
const newUrlQueue = urlQueue.urlQueueList.map((element: any) => {
//@ts-ignore
if (actives.includes(element.tabsessionId)) {
return element
}
})
const newTimeQueue = timeQueue.timeQueueList.map((element: any) => {
//@ts-ignore
if (actives.includes(element.tabsessionId)) {
return element
}
})
await chrome.storage.local.set({ webhistory: newHistory.filter((item: any) => item) });
await chrome.storage.local.set({ urlQueueList: newUrlQueue.filter((item: any) => item) });
await chrome.storage.local.set({ timeQueueList: newTimeQueue.filter((item: any) => item) });
toast.info("History Store Deleted!", {
position: "bottom-center"
});
});
} catch (error) {
console.log(error);
}
}
export const Popup = () => {
const [noOfWebPages, setNoOfWebPages] = useState<number>(0);
const [loading, setLoading] = useState(true);
useEffect(() => {
const verifyToken = async () => {
const token = localStorage.getItem('token');
// console.log(token)
try {
const response = await fetch(`${BACKEND_URL}/verify-token/${token}`);
if (!response.ok) {
throw new Error('Token verification failed');
}else{
const NEO4JURL = localStorage.getItem('neourl');
const NEO4JUSERNAME = localStorage.getItem('neouser');
const NEO4JPASSWORD = localStorage.getItem('neopass');
const OPENAIKEY = localStorage.getItem('openaikey');
const check = (NEO4JURL && NEO4JUSERNAME && NEO4JPASSWORD && OPENAIKEY)
if(!check){
goTo(FillEnvVariables);
}
}
} catch (error) {
localStorage.removeItem('token');
goTo(LoginForm);
}
};
verifyToken();
setLoading(false)
}, []);
useEffect(() => {
async function onLoad() {
try {
chrome.storage.onChanged.addListener(
(changes: any, areaName: string) => {
if (changes.webhistory) {
// console.log("changes.webhistory", changes.webhistory)
const webhistory = changes.webhistory.newValue;
let sum = 0
webhistory.forEach((element: any) => {
sum = sum + element.tabHistory.length
});
setNoOfWebPages(sum)
}
// console.log(changes)
// console.log(areaName)
}
);
const webhistoryObj = await chrome.storage.local.get(["webhistory"]);
if (webhistoryObj.webhistory.length) {
const webhistory = webhistoryObj.webhistory;
if (webhistoryObj) {
let sum = 0
webhistory.forEach((element: any) => {
sum = sum + element.tabHistory.length
});
setNoOfWebPages(sum)
}
} else {
setNoOfWebPages(0)
}
} catch (error) {
console.log(error);
}
}
onLoad()
}, []);
const saveData = async () => {
try {
// setLoading(true);
const webhistoryObj = await chrome.storage.local.get(["webhistory"]);
const webhistory = webhistoryObj.webhistory;
if (webhistory) {
let processedHistory: any[] = []
let newHistoryAfterCleanup: any[] = []
webhistory.forEach((element: any) => {
let tabhistory = element.tabHistory;
for (let i = 0; i < tabhistory.length; i++) {
tabhistory[i].pageContentMarkdown = convertHtmlToMarkdown(tabhistory[i].renderedHtml, {
extractMainContent: true,
enableTableColumnTracking: true,
})
delete tabhistory[i].renderedHtml
}
processedHistory.push({
tabsessionId: element.tabsessionId,
tabHistory: tabhistory,
})
newHistoryAfterCleanup.push({
tabsessionId: element.tabsessionId,
tabHistory: emptyArr,
})
});
await chrome.storage.local.set({ webhistory: newHistoryAfterCleanup });
let toSaveFinally = []
for (let i = 0; i < processedHistory.length; i++) {
const markdownFormat = webhistoryToLangChainDocument(processedHistory[i].tabsessionId, processedHistory[i].tabHistory)
toSaveFinally.push(...markdownFormat)
}
// console.log("SAVING", toSaveFinally)
const toSend = {
documents: toSaveFinally,
neourl: localStorage.getItem('neourl'),
neouser: localStorage.getItem('neouser'),
neopass: localStorage.getItem('neopass'),
openaikey: localStorage.getItem('openaikey'),
token: localStorage.getItem('token')
}
// console.log("toSend",toSend)
const requestOptions = {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(toSend),
};
toast.info("Save Job Initiated.", {
position: "bottom-center"
});
const response = await fetch(`${BACKEND_URL}/kb/`, requestOptions);
const res = await response.json();
if (res.success) {
toast.success("Save Job Completed.", {
position: "bottom-center",
autoClose: false
});
}
}
} catch (error) {
console.log(error);
}
};
// async function showMem(): Promise<void> {
// // localStorage.removeItem('token');
// // await chrome.storage.local.clear()
// const webhistoryObj = await chrome.storage.local.get(["webhistory"]);
// const urlQueue = await chrome.storage.local.get(["urlQueueList"]);
// const timeQueue = await chrome.storage.local.get(["timeQueueList"]);
// console.log("CURR MEM", webhistoryObj, urlQueue, timeQueue);
// // await chrome.storage.local.set({
// // urlQueueList: urlQueueListObj.urlQueueList,
// // });
// // await chrome.storage.local.set({
// // timeQueueList: timeQueueListObj.timeQueueList,
// // });
// // clearMem()
// }
async function logOut(): Promise<void> {
localStorage.removeItem('token');
goTo(LoginForm)
}
async function saveCurrSnapShot(): Promise<void> {
chrome.tabs.query({ active: true, currentWindow: true }, async function (tabs) {
const tab = tabs[0];
if (tab.id) {
// await initWebHistory(tab.id);
// await initQueues(tab.id);
const tabId: number = tab.id
const result = await chrome.scripting.executeScript({
// @ts-ignore
target: { tabId: tab.id },
// @ts-ignore
function: getRenderedHtml,
});
let toPushInTabHistory = result[0].result; // const { renderedHtml, title, url, entryTime } = result[0].result;
// //Updates 'tabhistory'
let webhistoryObj = await chrome.storage.local.get(["webhistory"]);
const webHistoryOfTabId = webhistoryObj.webhistory.filter(
(data: WebHistory) => {
return data.tabsessionId === tab.id;
}
);
let tabhistory = webHistoryOfTabId[0].tabHistory;
const urlQueueListObj = await chrome.storage.local.get(["urlQueueList"]);
const timeQueueListObj = await chrome.storage.local.get(["timeQueueList"]);
const isUrlQueueThere = urlQueueListObj.urlQueueList.find((data: WebHistory) => data.tabsessionId === tabId)
const isTimeQueueThere = timeQueueListObj.timeQueueList.find((data: WebHistory) => data.tabsessionId === tabId)
// console.log(isUrlQueueThere)
// console.log(isTimeQueueThere)
// console.log(isTimeQueueThere.timeQueue[isTimeQueueThere.length - 1])
toPushInTabHistory.duration = toPushInTabHistory.entryTime - isTimeQueueThere.timeQueue[isTimeQueueThere.timeQueue.length - 1]
if (isUrlQueueThere.urlQueue.length == 1) {
toPushInTabHistory.reffererUrl = 'START'
}
if (isUrlQueueThere.urlQueue.length > 1) {
toPushInTabHistory.reffererUrl = isUrlQueueThere.urlQueue[isUrlQueueThere.urlQueue.length - 2];
}
tabhistory.push(toPushInTabHistory);
// console.log(toPushInTabHistory)
//Update Webhistory
try {
webhistoryObj.webhistory.find(
(data: WebHistory) => data.tabsessionId === tab.id
).tabHistory = tabhistory;
await chrome.storage.local.set({
webhistory: webhistoryObj.webhistory,
});
} catch (error) {
console.log(error);
}
toast.success("Saved Snapshot !", {
position: "bottom-center"
});
}
});
}
if (loading) {
return <Loading />;
} else {
return (
<section className="dark bg-gray-50 dark:bg-gray-900">
{/* <div onClick={() => showMem()}>ShowMem</div> */}
<div className="flex flex-col items-center justify-center px-4 pt-4 pb-12 mx-auto md:h-screen lg:py-0">
<div className="flex items-center mb-6 text-2xl font-semibold text-gray-900 dark:text-white">
<img className="w-8 h-8 mr-2" src="./icon-128.png" alt="logo" />
SurfSense
</div>
<div className="w-full bg-white rounded-lg shadow dark:border md:mt-0 sm:max-w-md xl:p-0 dark:bg-gray-800 dark:border-gray-700">
<div className="p-6 space-y-4 md:space-y-6 sm:p-8">
<div className="flex justify-between">
<button type="button" onClick={() => goTo(FillEnvVariables)} className="px-3 py-2 text-xs font-medium text-center text-white bg-blue-700 rounded-lg hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" className="lucide lucide-settings"><path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z" /><circle cx="12" cy="12" r="3" /></svg>
</button>
<button type="button" onClick={() => logOut()} className="px-3 py-2 text-xs font-medium text-center text-white bg-blue-700 rounded-lg hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" className="lucide lucide-log-out"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" /><polyline points="16 17 21 12 16 7" /><line x1="21" x2="9" y1="12" y2="12" /></svg>
</button>
</div>
<div className="flex flex-col gap-3">
<div className="block max-w-sm p-4 bg-white border border-gray-200 rounded-lg shadow hover:bg-gray-100 dark:bg-gray-800 dark:border-gray-700 dark:hover:bg-gray-700">
<div className="flex flex-col gap-4 justify-center items-center text-2xl font-semibold text-gray-900 dark:text-white">
<img className="w-30 h-30 rounded-full" src="./brain.png" alt="brain" />
<div>
{noOfWebPages}
</div>
</div>
</div>
<button type="button" className="w-full text-white bg-gradient-to-r from-red-400 via-red-500 to-red-600 hover:bg-gradient-to-br focus:ring-4 focus:outline-none focus:ring-red-300 dark:focus:ring-red-800 font-medium rounded-lg text-sm px-5 py-2.5 text-center" onClick={() => clearMem()}>Clear Inactive History Sessions</button>
<button type="button" className="w-full text-gray-900 bg-gradient-to-r from-red-200 via-red-300 to-yellow-200 hover:bg-gradient-to-bl focus:ring-4 focus:outline-none focus:ring-red-100 dark:focus:ring-red-400 font-medium rounded-lg text-sm px-5 py-2.5 text-center" onClick={() => saveCurrSnapShot()}>Save Current Webpage SnapShot</button>
<button type="button" className="w-full text-gray-900 bg-gradient-to-r from-teal-200 to-lime-200 hover:bg-gradient-to-l hover:from-teal-200 hover:to-lime-200 focus:ring-4 focus:outline-none focus:ring-lime-200 dark:focus:ring-teal-700 font-medium rounded-lg text-sm px-5 py-2.5 text-center me-2 mb-2" onClick={() => saveData()}>Save to SurfSense</button>
</div>
</div>
</div>
</div>
</section>
)
}
};
const root = createRoot(document.getElementById("root")!);
root.render(
<React.StrictMode>
<Router>
<Popup />
</Router>
<ToastContainer autoClose={2000} />
</React.StrictMode>
);
// chrome.tabs.query({ active: true, currentWindow: true }, async function (tabs) {
// const tab = tabs[0];
// if (tab.id) {
// await initWebHistory(tab.id);
// await initQueues(tab.id);
// }
// });
// export const LoginForm = () => {
// const [username, setUsername] = useState('');
// const [password, setPassword] = useState('');
// const [error, setError] = useState('');
// const [loading, setLoading] = useState(false);
// // const navigate = useNavigate();
// const validateForm = () => {
// if (!username || !password) {
// setError('Username and password are required');
// return false;
// }
// setError('');
// return true;
// };
// const handleSubmit = async (event: { preventDefault: () => void; }) => {
// event.preventDefault();
// if (!validateForm()) return;
// setLoading(true);
// const formDetails = new URLSearchParams();
// formDetails.append('username', username);
// formDetails.append('password', password);
// try {
// const response = await fetch('http://localhost:8000/token', {
// method: 'POST',
// headers: {
// 'Content-Type': 'application/x-www-form-urlencoded',
// },
// body: formDetails,
// });
// setLoading(false);
// if (response.ok) {
// const data = await response.json();
// await chrome.storage.local.set({
// token: data.access_token,
// });
// // localStorage.setItem('token', data.access_token);
// goTo(Popup);
// } else {
// const errorData = await response.json();
// setError(errorData.detail || 'Authentication failed!');
// }
// } catch (error) {
// setLoading(false);
// setError('An error occurred. Please try again later.');
// }
// };
// const goToRegister = async () => {
// console.log("Reg")
// goTo(RegisterForm)
// }
// return (
// <>
// <section className="dark bg-gray-50 dark:bg-gray-900">
// <div onClick={() => clearMem}>CLEAR MEM</div>
// <div className="flex flex-col items-center justify-center px-6 py-8 mx-auto md:h-screen lg:py-0">
// <a href="#" className="flex items-center mb-6 text-2xl font-semibold text-gray-900 dark:text-white">
// <img className="w-8 h-8 mr-2" src={"./icon-128.png"} alt="logo" />
// SurfSense
// </a>
// <div className="w-full bg-white rounded-lg shadow dark:border md:mt-0 sm:max-w-md xl:p-0 dark:bg-gray-800 dark:border-gray-700">
// <div className="p-6 space-y-4 md:space-y-6 sm:p-8">
// <h1 className="text-xl font-bold leading-tight tracking-tight text-gray-900 md:text-2xl dark:text-white">
// Sign in to your account
// </h1>
// <form className="space-y-4 md:space-y-6" onSubmit={handleSubmit}>
// <div>
// <label className="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Your email</label>
// <input type="text" value={username} onChange={(e) => setUsername(e.target.value)} name="email" id="email" className="bg-gray-50 border border-gray-300 text-gray-900 rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="name" />
// </div>
// <div>
// <label className="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Password</label>
// <input type="password" value={password} onChange={(e) => setPassword(e.target.value)} name="password" id="password" placeholder="••••••••" className="bg-gray-50 border border-gray-300 text-gray-900 rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" />
// </div>
// <button type="submit" disabled={loading} className="w-full text-white bg-primary-600 hover:bg-primary-700 focus:ring-4 focus:outline-none focus:ring-primary-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800">{loading ? 'Logging in...' : 'Login'}</button>
// <p className="text-sm font-light text-gray-500 dark:text-gray-400">
// Dont have an account yet? <a href="#" className="font-medium text-primary-600 hover:underline dark:text-primary-500" onClick={() => goToRegister()}>Sign up</a>
// </p>
// {error && <p style={{ color: 'red' }}>{error}</p>}
// </form>
// </div>
// </div>
// </div>
// </section>
// </>
// );
// }
// import { createGlobalState } from 'react-hooks-global-state';
// const initialState = { count: 0 };
// const { useGlobalState } = createGlobalState(initialState);
// const [count, setCount] = useGlobalState('count');
// setCount(v => v - 1);
// let saveJobsObj = await chrome.storage.local.get(["savejobs"]);
// await chrome.storage.local.set({
// savejobs: saveJobsObj.savejobs - 1,
// });
// else{
// toPushInTabHistory.reffererUrl = urlQueueLocal.urlQueue[tabId][urlQueueLocal.urlQueue[tabId].length - 1]
// }
// if(!tabhistory[tabhistory.length - 1].duration){
// tabhistory[tabhistory.length - 1].duration = Date.now() - timeQueueLocal.timeQueue[tabId][timeQueueLocal.timeQueue[tabId].length - 1]
// }
// if (tabhistory.length === 0) {
// toPushInTabHistory.duration = Date.now() - timeQueueLocal.timeQueue[tabId][timeQueueLocal.timeQueue[tabId].length - 1]
// }
// else {
// }
// const lastEntryTimeObj = await chrome.storage.local.get([
// "lastEntryTime",
// ]);
// const autotrackerFlag = await chrome.storage.local.get(["autoTracker"]);
// // if (autotrackerFlag.autoTracker) {
// // let urlQueue = await chrome.storage.local.get(["urlQueue"]);
// // delete urlQueue.urlQueue[tabId];
// // }
// //When first entry
// if (tabhistory.length === 0) {
// let urlQueue = await chrome.storage.local.get(["urlQueue"]);
// if (autotrackerFlag.autoTracker) {
// toPushInTabHistory.reffererUrl = "START";
// try {
// delete urlQueue.urlQueue[tabId];
// } catch (error) {
// console.log(error);
// }
// } else {
// if (urlQueue.urlQueue[tabId].length >= 2) {
// toPushInTabHistory.reffererUrl = urlQueue.urlQueue[tabId][urlQueue.urlQueue[tabId].length - 2];
// } else {
// toPushInTabHistory.reffererUrl = "START";
// }
// }
// toPushInTabHistory.duration = Date.now() - lastEntryTimeObj.lastEntryTime[tabId];
// tabhistory.push(toPushInTabHistory);
// try {
// webhistoryObj.webhistory.find(
// (data: WebHistory) => data.tabsessionId === tab.id
// ).tabHistory = tabhistory;
// await chrome.storage.local.set({
// webhistory: webhistoryObj.webhistory,
// });
// } catch (error) {
// console.log(error);
// }
// } else {
// if (autotrackerFlag.autoTracker) {
// toPushInTabHistory.reffererUrl = tabhistory[tabhistory.length - 1].url;
// } else {
// let urlQueue = await chrome.storage.local.get(["urlQueue"]);
// toPushInTabHistory.reffererUrl = urlQueue.urlQueue[tabId][urlQueue.urlQueue[tabId].length - 2];
// }
// if (!tabhistory[tabhistory.length - 1].duration) {
// toPushInTabHistory.duration = Date.now() - tabhistory[tabhistory.length - 1].entryTime
// }
// toPushInTabHistory.duration = Date.now() - lastEntryTimeObj.lastEntryTime[tabId];
// tabhistory.push(toPushInTabHistory);
// try {
// webhistoryObj.webhistory.find(
// (data: WebHistory) => data.tabsessionId === tab.id
// ).tabHistory = tabhistory;
// await chrome.storage.local.set({
// webhistory: webhistoryObj.webhistory,
// });
// } catch (error) {
// console.log(error);
// }
// }

View file

@ -1,3 +0,0 @@
export function sum(x: number, y: number) {
return x + y;
}

View file

@ -1,60 +0,0 @@
module.exports = {
content: ["./src/*.{js,jsx,ts,tsx}"],
darkMode: "selector",
theme: {
extend: {
colors: {
primary: {
50: "#eff6ff",
100: "#dbeafe",
200: "#bfdbfe",
300: "#93c5fd",
400: "#60a5fa",
500: "#3b82f6",
600: "#2563eb",
700: "#1d4ed8",
800: "#1e40af",
900: "#1e3a8a",
950: "#172554",
},
},
},
fontFamily: {
body: [
"Inter",
"ui-sans-serif",
"system-ui",
"-apple-system",
"system-ui",
"Segoe UI",
"Roboto",
"Helvetica Neue",
"Arial",
"Noto Sans",
"sans-serif",
"Apple Color Emoji",
"Segoe UI Emoji",
"Segoe UI Symbol",
"Noto Color Emoji",
],
sans: [
"Inter",
"ui-sans-serif",
"system-ui",
"-apple-system",
"system-ui",
"Segoe UI",
"Roboto",
"Helvetica Neue",
"Arial",
"Noto Sans",
"sans-serif",
"Apple Color Emoji",
"Segoe UI Emoji",
"Segoe UI Symbol",
"Noto Color Emoji",
],
},
},
plugins: [],
};

View file

@ -1,15 +0,0 @@
{
"compilerOptions": {
"strict": true,
"target": "es6",
"moduleResolution": "bundler",
"module": "ES6",
"esModuleInterop": true,
"sourceMap": false,
"rootDir": "src",
"outDir": "dist/js",
"noEmitOnError": true,
"jsx": "react",
"typeRoots": [ "node_modules/@types" ]
}
}

View file

@ -1,6 +0,0 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"moduleResolution": "node"
}
}

View file

@ -1,66 +0,0 @@
const webpack = require("webpack");
const path = require("path");
const CopyPlugin = require("copy-webpack-plugin");
const srcDir = path.join(__dirname, "..", "src");
const tailwindcss = require('tailwindcss')
const autoprefixer = require('autoprefixer')
module.exports = {
entry: {
popup: path.join(srcDir, 'popup.tsx'),
background: path.join(srcDir, 'background.ts'),
content_script: path.join(srcDir, 'content_script.tsx'),
},
output: {
path: path.join(__dirname, "../dist/js"),
filename: "[name].js",
},
optimization: {
splitChunks: {
name: "vendor",
chunks(chunk) {
return chunk.name !== 'background';
}
},
},
module: {
rules: [
{
test: /\.tsx?$/,
use: "ts-loader",
exclude: /node_modules/,
},
{
test: /\.css$/i,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 1,
},
},
{
loader: 'postcss-loader', // postcss loader needed for tailwindcss
options: {
postcssOptions: {
ident: 'postcss',
plugins: [tailwindcss, autoprefixer],
},
},
},
],
},
],
},
resolve: {
extensions: [".ts", ".tsx", ".js"],
},
plugins: [
new CopyPlugin({
patterns: [{ from: ".", to: "../", context: "public" }],
options: {},
}),
],
};

View file

@ -1,7 +0,0 @@
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
devtool: 'inline-source-map',
mode: 'development'
});

View file

@ -1,6 +0,0 @@
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
mode: 'production'
});

@ -0,0 +1 @@
Subproject commit 83205acb7b9712020940461b74e0aa66f9316a77