Skip to content

Commit

Permalink
feat(extensions): implement login / logout flow
Browse files Browse the repository at this point in the history
  • Loading branch information
edmundhung committed Aug 13, 2021
1 parent 2be9353 commit de9502e
Show file tree
Hide file tree
Showing 8 changed files with 347 additions and 9 deletions.
91 changes: 91 additions & 0 deletions packages/extensions/package-lock.json

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

1 change: 1 addition & 0 deletions packages/extensions/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"@babel/runtime": "^7.14.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-query": "^3.19.0",
"tailwindcss": "^2.2.4",
"webextension-polyfill-ts": "^0.25.0"
},
Expand Down
87 changes: 84 additions & 3 deletions packages/extensions/src/background.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,86 @@
import { config, decrypt, readMessage } from 'openpgp/lightweight';
import { browser } from 'webextension-polyfill-ts';
import { Status, Config, GET_STATUS_EVENT } from './types';

browser.runtime.onInstalled.addListener((): void => {
console.log('extension installed');
});
interface Context {
repository: string | null;
passpharse: string | null;
config: any;
}

type Event = GET_STATUS_EVENT;

async function request<T>(path: string): T {
const response = await fetch(
`${process.env.WEB_URL ?? 'http://localhost:3000'}${path}`,
);
const body = await response.json();
const { data, error } = body ?? {};

if (!response.ok) {
throw new Error(error?.message ?? response.statusText);
}

return data;
}

async function getStatus(
context: Context,
event: GET_STATUS_EVENT,
): Promise<Status | null> {
console.log('getStatus', JSON.stringify(context));

try {
const { repos: options } = await request<{ repos: string[] }>(
'/api/session',
);

if (context.repository === null) {
context.repository = options[0];
}

let configByDomain: Record<string, Config> | null = null;
let emails: string[] = [];

if (context.config) {
configByDomain = Object.fromEntries(
Object.keys(context.config.domains).map<[string, Config]>((domain) => [
domain,
{ recipents: [] },
]),
);
}

return {
repository: context.repository,
options,
configByDomain,
emails,
};
} catch (e) {
if (e.message === 'Unauthorized') {
return null;
}

throw e;
}
}

function main() {
let context: Context = {
repository: null,
passpharse: null,
config: null,
};

browser.runtime.onMessage.addListener((event: Event, sender) => {
switch (event.type) {
case 'GET_STATUS':
return getStatus(context, event);
default:
return;
}
});
}

main();
2 changes: 1 addition & 1 deletion packages/extensions/src/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,6 @@

"background": {
"scripts": ["js/background.bundle.js"],
"__chrome|opera__persistent": false
"__chrome|opera__persistent": true
}
}
62 changes: 62 additions & 0 deletions packages/extensions/src/popup/NavigationScreen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import React from 'react';

interface NavigationScreenProps {
repository: string | null;
options: string[];
onSelect: (repo: string) => void;
onInstall: () => void;
onLogout: () => void;
}

function NavigationScreen({
repository,
options,
onSelect,
onInstall,
onLogout,
}: Props): React.ReactElement {
return (
<main className="flex flex-col w-72 h-96 bg-primary">
<header className="pt-10 pb-4 px-6">
<h1 className="text-base text-white">Select a repository</h1>
</header>
<div className="flex flex-col divide-dotted divide-y divide-white text-white h-full pb-6">
<div className="flex-grow py-6">
<ul>
{options.slice(0, 5).map((option) => (
<li key={option} className="py-1 pr-6">
<button
className={`inline-block w-full text-left px-6 py-1 rounded-r focus:outline-white ${
option === repository
? 'bg-white text-primary'
: 'hover:bg-white hover:text-primary hover:opacity-50 focus:bg-white focus:text-primary focus:opacity-50'
}`}
type="button"
onClick={() => onSelect(option)}
>
{option.split('/').join(' / ')}
</button>
</li>
))}
</ul>
</div>
<button
className="block w-full py-2 px-6 text-left focus:outline-white"
type="button"
onClick={onInstall}
>
Install additional repository
</button>
<button
className="block w-full py-2 px-6 text-left focus:outline-white"
type="button"
onClick={onLogout}
>
Logout
</button>
</div>
</main>
);
}

export default NavigationScreen;
Loading

0 comments on commit de9502e

Please sign in to comment.