-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(extensions): implement login / logout flow
- Loading branch information
1 parent
2be9353
commit de9502e
Showing
8 changed files
with
347 additions
and
9 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
Oops, something went wrong.