Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix primitive value #52

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,13 @@
- Dawsonera
- ProQuest
- JStor

## Updates made by @Llyrus

- updated some dependancies
- fixed the reset button

- to install:
- `npm i webpack`
- `npm run build`
- load unpacked dist in chrom extensions
15,775 changes: 5,887 additions & 9,888 deletions package-lock.json

Large diffs are not rendered by default.

9 changes: 7 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,20 @@
"style-loader": "^0.23.1",
"ts-loader": "^5.2.2",
"ts-node": "^7.0.1",
"typescript": "^3.1.3",
"webpack": "^4.22.0",
"typescript": "^5.5.4",
"webpack": "^4.47.0",
"webpack-cli": "^3.1.2"
},
"dependencies": {
"@mapbox/node-pre-gyp": "^1.0.11",
"@types/har-format": "^1.2.15",
"@types/node": "^22.1.0",
"@types/object-hash": "^2.2.1",
"emotion": "^9.0",
"jspdf": "^2.5.1",
"node-pre-gyp": "^0.17.0",
"object-hash": "^2.2.0",
"prop-types": "^15.x.x",
"react": "16.8",
"react-dom": "16.8",
"react-spring": "^6.1.2",
Expand Down
20 changes: 16 additions & 4 deletions src/js/common/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,24 @@ export async function getURL(): Promise<false | URL> {
return tab ? new URL(tab.url) : false;
}

export function getBookURL(url: URL): string {
const site = sites.find(site => site.host === url.host);
// export function getBookURL(url: URL): string {
// const site = sites.find(site => site.host === url.host);

if (site) {
return site.constructBookURL(url);
// if (site) {
// return site.constructBookURL(url);
// }
// }
export function getBookURL(url: URL): Promise<string> {
return new Promise((resolve, reject) => {
const site = sites.find(site => site.host === url.host);

if (site){
const bookURL = site.constructBookURL(url);
resolve(bookURL);
} else {
reject("URL not found");
}
});
}

/**
Expand Down
5 changes: 2 additions & 3 deletions src/js/eventPage/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,8 @@ export const savePage = (pageImageURL: string): Promise<boolean> => {
};
const bookURL = await getBookURL(url);
if (!bookURL) {
console.error({ url, bookURL })
return reject("Could not get book URL")
};
throw new Error("Could not get active tab URL")
}
const book = await getBook(bookURL);
const bookIsValid = !!book && book.pages && Array.isArray(book.pages);
if (bookIsValid) {
Expand Down
59 changes: 38 additions & 21 deletions src/js/eventPage/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,40 +8,45 @@ import {
savePage
} from "./actions";

let lastURL;
// Listen for messages from the popup
let lastURL: string | null = null;

chrome.runtime.onInstalled.addListener(() => {
updatePageAction();

console.log("XXX");
console.log("Extension installed and pahe action updated");

// Listen to messages sent from other parts of the extension.
chrome.runtime.onMessage.addListener(
async (request: ScraperMessage, sender, sendResponse) => {
// onMessage must return "true" if response is async.
let isResponseAsync = false;

if (request.action === "ClearBook") {
isResponseAsync = true;
lastURL = null;
deleteBook(request.bookURL, () => {
sendResponse(null);
});
}
switch (request.action) {
case "ClearBook":
isResponseAsync = true;
lastURL = null;
deleteBook(request.bookURL, () => {
sendResponse(null);
});
break;

if (request.action === "SaveBook") {
isResponseAsync = true;
saveBook(request.book, () => sendResponse(request.book));
}
case "SaveBook":
isResponseAsync = true;
saveBook(request.book, () => sendResponse(request.book));
break;

if (request.action === "UpdatePageOrder") {
isResponseAsync = true;
asyncUpdatePageOrder(request, sendResponse);
}
case "UpdatePageOrder":
isResponseAsync = true;
asyncUpdatePageOrder(request, sendResponse);
break;

return isResponseAsync;
}
);
default:
console.warn("Unknown action:", request.action);
}

return isResponseAsync;
}
);

// Show page action on the right domain
chrome.declarativeContent.onPageChanged.removeRules(undefined, () => {
Expand Down Expand Up @@ -93,4 +98,16 @@ chrome.tabs.onUpdated.addListener(async function (tabId, changeInfo, tab) {
updatePageAction();
chrome.action.setBadgeBackgroundColor({ color: "#f45752" });
}
});
// Ping interval to send status message every 10 seconds
const pingInterval = setInterval(() => {
chrome.runtime.sendMessage({
status: "ping",
});
}, 10000); // Ping every 10 seconds

// Clear the interval when the extension or page is unloaded
chrome.runtime.onSuspend.addListener(() => {
clearInterval(pingInterval);
console.log("Extension unloaded, ping interval cleared.");
});
67 changes: 40 additions & 27 deletions src/js/popup/Popup.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
import * as React from "react";
import * as React from 'react';
import { useEffect, useState } from "react";
import { Heading, Box, Card, Flex, Text, Button } from "rebass";
import { getURL, getBookURL, getBook } from "../common/utils";
import { Page, ResetButton, Checkbox } from "./Components";
import { createPDF } from './pdf';
import { createPDF } from "./pdf";

function Popup() {
// const [pageNumber, setPageNumber] = useState<number>(undefined);
const [displayPages, setDisplayPages] = useState<boolean>(false);
const [book, setBook] = useState<Book>(undefined);
const [book, setBook] = useState<Book | undefined>(undefined);

useEffect(() => {
try {
fetchBook();
} catch (e) {
// No book to begin with
console.log("Error fetching book initially", e);
}

chrome.runtime.onMessage.addListener(
(request: ScraperMessage, sender, sendResponse) => {
// onMessage must return "true" if response is async.
console.log("Received message", request);
let isResponseAsync = false;

if (request.action === "BookWasUpdated") {
Expand All @@ -45,69 +45,68 @@ function Popup() {
return reject("Couldn't get URL for this book");
}

const url = getBookURL(_url);
const url = await getBookURL(_url);
let book = await getBook(url);

if (!book) {
console.log("No book", book);
book = { url, pages: [] };
const message: Messages.SaveBook = { action: "SaveBook", book };
chrome.runtime.sendMessage(message);
chrome.runtime.sendMessage(message, (response) => {
if (chrome.runtime.lastError) {
console.error("Error saving book:", chrome.runtime.lastError);
} else {
console.log("Message Response:", response);
}
});
} else {
console.log("Received book", book);
}

setBook(book);

resolve(book);
} catch (e) {
console.error("Error fetching book", e);
return reject(e);
}
});
};

const download = async () => {
if (!book.url) return;
if (!book || !book.url) return;
createPDF(book);
};

const reset = async () => {
if (!book.url) return;
if (!book || !book.url) return;
const message: Messages.ClearBook = {
action: "ClearBook",
bookURL: book.url
};
return await chrome.runtime.sendMessage(message, fetchBook);
chrome.runtime.sendMessage(message, fetchBook);
};

const updatePageOrder = async (oldIndex: number, newIndex: number) => {
if (!book.url) return;
if (!book || !book.url) return;
const message: Messages.UpdatePageOrder = {
action: "UpdatePageOrder",
bookURL: book.url,
oldIndex,
newIndex
};
return await chrome.runtime.sendMessage(message, fetchBook);
chrome.runtime.sendMessage(message, fetchBook);
};

// Determine dark mode and define colors for it
const darkMode = window.matchMedia("(prefers-color-scheme: dark)").matches;

const variableDarkModeContainer = { // we don't have to worry about the bg color here as it is managed by / inherited from the variableDarkModeRoot css
color: "#fff"
}

const variableDarkModeBox = {
backgroundColor: "#555",
color: "#fff",
}

const variableDarkModeContainer = { color: "#fff" };
const variableDarkModeBox = { backgroundColor: "#555", color: "#fff" };
const variableDarkModeReset = {
"text-align": "right",
textAlign: "right",
backgroundColor: "#242424",
border: "1px solid red"
}
};

return (
<Box width={250} style={darkMode ? variableDarkModeContainer : null}>
Expand All @@ -116,14 +115,28 @@ function Popup() {
<Box width={1}>
<Heading fontSize={2}>eBook PDF Creator 📖</Heading>
</Box>
{book && <ResetButton reset={reset} styleOverride={darkMode ? variableDarkModeReset : null}>Reset</ResetButton>}
{book && (
<ResetButton
reset={reset}
styleOverride={darkMode ? variableDarkModeReset : null}
>
Reset
</ResetButton>
)}
</Flex>
{book && (
<>
<Card bg="#EEE" borderRadius={3} my={2} style={darkMode ? variableDarkModeBox : null}>
<Card
bg="#EEE"
borderRadius={3}
my={2}
style={darkMode ? variableDarkModeBox : null}
>
<Text fontSize={1}>
<b>Book URL:</b> <br />
<a style={{ "color": "#f45752" }} href={book.url}>{book.url}</a>
<a style={{ color: "#f45752" }} href={book.url}>
{book.url}
</a>
</Text>
</Card>
{book.pages.length > 0 ? (
Expand Down
11 changes: 11 additions & 0 deletions src/js/popup/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,14 @@ import Popup from './Popup';
chrome.tabs.query({ active: true, currentWindow: true }, tab => {
ReactDOM.render(<Popup />, document.getElementById('popup'));
});

chrome.tabs.query({ active: true, currentWindow: true }, tab => {
console.log('Tab:', tab); // Check if the tab is being queried correctly
const rootElement = document.getElementById('popup');
console.log('Root Element:', rootElement); // Check if the root element is found
if (rootElement) {
ReactDOM.render(<Popup />, rootElement);
} else {
console.error('Root element not found');
}
});
2 changes: 1 addition & 1 deletion src/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@
"webRequest"
],
"host_permissions": []
}
}
11 changes: 7 additions & 4 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"rootDir": "./",
"rootDir": "./src",
"outDir": "dist/js",
"sourceMap": true,
"jsx": "react",
"lib": ["esnext", "dom"],
"experimentalDecorators": true
}
}
"experimentalDecorators": true,
"esModuleInterop": true,
"skipLibCheck": true
},
"include": ["src/**/*"]
}
4 changes: 2 additions & 2 deletions webpack.config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import webpack = require("webpack");

const path = require("path");
import * as path from "path";

const webpackConfig: webpack.Configuration = {
resolveLoader: {
Expand Down Expand Up @@ -50,7 +50,7 @@ const webpackConfig: webpack.Configuration = {
]
},
resolve: {
extensions: [".ts", ".tsx", ".js"]
extensions: [".ts", ".tsx", ".js", ".json"]
},
node: {
fs: "empty"
Expand Down
Loading