Skip to content

Commit

Permalink
Merge pull request #19 from codecentric/migrate-to-background
Browse files Browse the repository at this point in the history
replace legacy logic with background script
  • Loading branch information
ejbyne authored Mar 4, 2022
2 parents 3492bce + 5a96c06 commit 605a7c9
Show file tree
Hide file tree
Showing 29 changed files with 143 additions and 609 deletions.
2 changes: 1 addition & 1 deletion dev/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ function renderApp(session: Session) {
ReactDOM.render(
<PageContent
close={() => alert('cannot close in dev mode')}
legacySession={session}
sessionInfo={session.info}
/>,
container
);
Expand Down
3 changes: 3 additions & 0 deletions jest.setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,7 @@ global.chrome = {
runtime: {
sendMessage: jest.fn(),
},
identity: {
getRedirectURL: () => 'https://redirect-url.test',
},
};
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "webclip-chrome-ext",
"version": "0.5.1",
"version": "0.6.0",
"description": "",
"main": "src/content.tsx",
"scripts": {
Expand Down
20 changes: 5 additions & 15 deletions src/background.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,15 @@
import { SolidApi } from './api/SolidApi';
import { activateWebClipForTab } from './background/activate';
import { MessageHandler } from './background/MessageHandler';
import { createMessageHandler } from './background/createMessageHandler';
import { sendMessageToActiveTab } from './background/sendMessageToActiveTab';
import { MessageType } from './messages';
import { Session } from './solid-client-authn-chrome-ext/Session';
import { Store } from './store/Store';

const session = new Session();

function createMessageHandler() {
const store = new Store();
return new MessageHandler(
new SolidApi(session, store, chrome.identity.getRedirectURL()),
store
);
}

let messageHandler = createMessageHandler();
let messageHandler = createMessageHandler(session);

chrome.browserAction.onClicked.addListener(function (tab) {
activateWebClipForTab(tab);
activateWebClipForTab(tab, session.info);
});

chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
Expand All @@ -28,7 +18,7 @@ chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
});

session.onLogin(() => {
messageHandler = createMessageHandler();
messageHandler = createMessageHandler(session);

sendMessageToActiveTab({
type: MessageType.LOGGED_IN,
Expand All @@ -37,5 +27,5 @@ session.onLogin(() => {
});

session.onLogout(() => {
messageHandler = createMessageHandler();
messageHandler = createMessageHandler(session);
});
13 changes: 9 additions & 4 deletions src/background/activate.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import { ISessionInfo } from '@inrupt/solid-client-authn-browser';
import { MessageType } from '../messages';
import Tab = chrome.tabs.Tab;

export function activateWebClipForTab(tab: Tab) {
chrome.tabs.sendMessage(tab.id, { type: MessageType.ACTIVATE }, function () {
return null;
});
export function activateWebClipForTab(tab: Tab, sessionInfo: ISessionInfo) {
chrome.tabs.sendMessage(
tab.id,
{ type: MessageType.ACTIVATE, payload: sessionInfo },
function () {
return null;
}
);
}
12 changes: 12 additions & 0 deletions src/background/createMessageHandler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { SolidApi } from '../api/SolidApi';
import { Session } from '../solid-client-authn-chrome-ext/Session';
import { Store } from '../store/Store';
import { MessageHandler } from './MessageHandler';

export function createMessageHandler(session: Session) {
const store = new Store();
return new MessageHandler(
new SolidApi(session, store, chrome.identity.getRedirectURL()),
store
);
}
28 changes: 6 additions & 22 deletions src/content.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
import {
getDefaultSession,
handleIncomingRedirect,
Session,
} from '@inrupt/solid-client-authn-browser';
import { ISessionInfo } from '@inrupt/solid-client-authn-browser';
import React from 'react';
import ReactDOM from 'react-dom';

import contentCss from './assets/content.css';
import { ChromeMessageListener } from './content/ChromeMessageListener';
import { PageContent } from './content/PageContent';
import { WebClip } from './content/WebClip';
import { MessageType } from './messages';

import contentCss from './assets/content.css';

const root = document.createElement('div');
root.id = 'webclip';
document.body.appendChild(root);
Expand All @@ -24,32 +19,21 @@ shadowRoot.appendChild(container);

const chromeMessageListener = new ChromeMessageListener();

async function handleRedirectAfterLogin() {
await handleIncomingRedirect();
return getDefaultSession();
}

handleRedirectAfterLogin().then((session: Session) => {
if (session.info.isLoggedIn) {
renderApp(session);
}
});

chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
switch (request.type) {
case MessageType.ACTIVATE:
renderApp(getDefaultSession());
renderApp(request.payload);
break;
}
sendResponse();
});

function renderApp(session: Session) {
function renderApp(sessionInfo: ISessionInfo) {
ReactDOM.render(
<WebClip
chromeMessageListener={chromeMessageListener}
close={unmountApp}
legacySession={session}
sessionInfo={sessionInfo}
/>,
container
);
Expand Down
8 changes: 4 additions & 4 deletions src/content/LoginButton.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { fireEvent, render, screen } from '@testing-library/react';
import React from 'react';
import { LoginButton } from './LoginButton';
import { useLegacyLogin } from './useLegacyLogin';
import { useLogin } from './useLogin';

jest.mock('./useLegacyLogin');
jest.mock('./useLogin');

describe('LoginButton', () => {
it('triggers login when clicked', () => {
const login = jest.fn();
(useLegacyLogin as jest.Mock).mockReturnValue({
(useLogin as jest.Mock).mockReturnValue({
login,
});
render(<LoginButton />);
Expand All @@ -18,7 +18,7 @@ describe('LoginButton', () => {
});

it('shows error, when login failed', () => {
(useLegacyLogin as jest.Mock).mockReturnValue({
(useLogin as jest.Mock).mockReturnValue({
error: 'something went wrong',
login: jest.fn(),
});
Expand Down
4 changes: 2 additions & 2 deletions src/content/LoginButton.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React from 'react';
import { useLegacyLogin } from './useLegacyLogin';
import { useLogin } from './useLogin';

export const LoginButton = () => {
const { login, error } = useLegacyLogin();
const { login, error } = useLogin();
return (
<>
<button
Expand Down
6 changes: 3 additions & 3 deletions src/content/PageContent.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Session } from '@inrupt/solid-client-authn-browser';
import { ISessionInfo } from '@inrupt/solid-client-authn-browser';
import { render, screen } from '@testing-library/react';
import React from 'react';
import { PageContent } from './PageContent';
Expand All @@ -22,7 +22,7 @@ describe('PageContent', () => {
it('is present', () => {
render(
<PageContent
legacySession={{ info: { isLoggedIn: false } } as Session}
sessionInfo={{ isLoggedIn: false } as ISessionInfo}
close={() => null}
/>
);
Expand All @@ -34,7 +34,7 @@ describe('PageContent', () => {
const close = jest.fn();
render(
<PageContent
legacySession={{ info: { isLoggedIn: false } } as Session}
sessionInfo={{ isLoggedIn: false } as ISessionInfo}
close={close}
/>
);
Expand Down
18 changes: 5 additions & 13 deletions src/content/PageContent.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
import { Session } from '@inrupt/solid-client-authn-browser';
import { ISessionInfo } from '@inrupt/solid-client-authn-browser';
import React from 'react';
import { SolidApiContext } from '../api/apiContext';
import { StoreContext } from '../store/context';
import { LoginButton } from './LoginButton';
import { ToolbarContainer } from './ToolbarContainer';
import { useSessionInfo } from './useSessionInfo';
import { useSolid } from './useSolid';

interface PageContentProps {
legacySession: Session;
sessionInfo: ISessionInfo;
close: () => void;
}

export const PageContent = ({ legacySession, close }: PageContentProps) => {
const { store, solidApi } = useSolid(legacySession);
const sessionInfo = useSessionInfo(legacySession);
export const PageContent = ({ sessionInfo, close }: PageContentProps) => {
const currentSessionInfo = useSessionInfo(sessionInfo);
return (
<div className="font-sans text-base text-gray-700 z-max fixed top-0 right-0 m-8 shadow rounded w-auto h-auto p-4 bg-white flex flex-col items-center">
<div className="flex w-full justify-end items-center">
Expand All @@ -28,11 +24,7 @@ export const PageContent = ({ legacySession, close }: PageContentProps) => {
</div>
<div className="paperclip" />
<h1 className="text-3xl mx-4 my-2">WebClip</h1>
<StoreContext.Provider value={store}>
<SolidApiContext.Provider value={solidApi}>
{sessionInfo.isLoggedIn ? <ToolbarContainer /> : <LoginButton />}
</SolidApiContext.Provider>
</StoreContext.Provider>
{currentSessionInfo.isLoggedIn ? <ToolbarContainer /> : <LoginButton />}
</div>
);
};
16 changes: 8 additions & 8 deletions src/content/Toolbar.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { usePage } from './usePage';
import { fireEvent, render, screen } from '@testing-library/react';
import { Toolbar } from './Toolbar';
import { useLegacyBookmark } from './useLegacyBookmark';
import { useBookmark } from './useBookmark';
import React from 'react';

jest.mock('./useLegacyBookmark');
jest.mock('./useBookmark');
jest.mock('./usePage');

describe('Toolbar', () => {
describe('while loading', () => {
beforeEach(() => {
(useLegacyBookmark as jest.Mock).mockReturnValue({
(useBookmark as jest.Mock).mockReturnValue({
saving: false,
loading: true,
});
Expand All @@ -35,7 +35,7 @@ describe('Toolbar', () => {

beforeEach(() => {
addBookmark = jest.fn();
(useLegacyBookmark as jest.Mock).mockReturnValue({
(useBookmark as jest.Mock).mockReturnValue({
saving: false,
loading: false,
addBookmark,
Expand All @@ -55,7 +55,7 @@ describe('Toolbar', () => {
name: 'An interesting article',
});
render(<Toolbar profile={{ name: 'Jane Doe' }} />);
expect(useLegacyBookmark).toHaveBeenCalledWith({
expect(useBookmark).toHaveBeenCalledWith({
type: 'WebPage',
url: 'https://page.example/article',
name: 'An interesting article',
Expand All @@ -75,7 +75,7 @@ describe('Toolbar', () => {
});

it('disables the clip it button and shows a saving message while the bookmark is being saved', () => {
(useLegacyBookmark as jest.Mock).mockReturnValue({
(useBookmark as jest.Mock).mockReturnValue({
saving: true,
error: null,
addBookmark,
Expand All @@ -89,7 +89,7 @@ describe('Toolbar', () => {
});

it('shows an error if the bookmark cannot be saved', () => {
(useLegacyBookmark as jest.Mock).mockReturnValue({
(useBookmark as jest.Mock).mockReturnValue({
saving: false,
loading: false,
error: new Error('Pod not available'),
Expand All @@ -104,7 +104,7 @@ describe('Toolbar', () => {
});

it('shows a link to the bookmark after it has been saved', () => {
(useLegacyBookmark as jest.Mock).mockReturnValue({
(useBookmark as jest.Mock).mockReturnValue({
saving: false,
bookmark: { uri: 'https://storage.example/bookmark#it' },
addBookmark,
Expand Down
5 changes: 2 additions & 3 deletions src/content/Toolbar.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { useLegacyBookmark } from './useLegacyBookmark';
import { useBookmark } from './useBookmark';
import { usePage } from './usePage';

interface Props {
Expand All @@ -10,8 +10,7 @@ interface Props {

export const Toolbar = ({ profile }: Props) => {
const page = usePage();
const { addBookmark, loading, saving, error, bookmark } =
useLegacyBookmark(page);
const { addBookmark, loading, saving, error, bookmark } = useBookmark(page);
const waiting = loading || saving;
return (
<>
Expand Down
Loading

0 comments on commit 605a7c9

Please sign in to comment.