From 1d00f3b9840003601175d5394af34b29222db4e3 Mon Sep 17 00:00:00 2001 From: Paul Frazee Date: Mon, 18 Jul 2022 15:24:37 -0500 Subject: Add mock API and reorg code for clarity --- package.json | 2 + scripts/testing-server.mjs | 17 ++- src/App.native.tsx | 3 +- src/App.web.tsx | 2 +- src/api/index.ts | 118 --------------- src/platform/auth-flow.native.ts | 2 +- src/platform/auth-flow.ts | 2 +- src/platform/desktop-web/left-column.tsx | 57 ------- src/platform/desktop-web/right-column.tsx | 19 --- src/platform/desktop-web/shell.tsx | 35 ----- src/platform/shell.tsx | 12 -- src/routes/index.tsx | 110 -------------- src/routes/types.ts | 36 ----- src/screens/Home.tsx | 21 --- src/screens/Login.tsx | 29 ---- src/screens/Menu.tsx | 16 -- src/screens/NotFound.tsx | 15 -- src/screens/Notifications.tsx | 14 -- src/screens/Profile.tsx | 16 -- src/screens/Search.tsx | 14 -- src/screens/Signup.tsx | 34 ----- src/state/auth.ts | 112 -------------- src/state/env.ts | 223 +++++++++++++++++++++++++++- src/state/index.ts | 26 ++-- src/state/lib/auth.ts | 116 +++++++++++++++ src/state/lib/storage.ts | 52 +++++++ src/state/models/me.ts | 48 ++++++ src/state/models/root-store.ts | 3 + src/state/models/session.ts | 14 +- src/state/storage.ts | 52 ------- src/view/routes/index.tsx | 110 ++++++++++++++ src/view/routes/types.ts | 36 +++++ src/view/screens/Home.tsx | 21 +++ src/view/screens/Login.tsx | 29 ++++ src/view/screens/Menu.tsx | 16 ++ src/view/screens/NotFound.tsx | 15 ++ src/view/screens/Notifications.tsx | 14 ++ src/view/screens/Profile.tsx | 16 ++ src/view/screens/Search.tsx | 14 ++ src/view/screens/Signup.tsx | 34 +++++ src/view/shell/desktop-web/left-column.tsx | 57 +++++++ src/view/shell/desktop-web/right-column.tsx | 19 +++ src/view/shell/desktop-web/shell.tsx | 35 +++++ src/view/shell/index.tsx | 12 ++ yarn.lock | 28 +++- 45 files changed, 932 insertions(+), 744 deletions(-) delete mode 100644 src/api/index.ts delete mode 100644 src/platform/desktop-web/left-column.tsx delete mode 100644 src/platform/desktop-web/right-column.tsx delete mode 100644 src/platform/desktop-web/shell.tsx delete mode 100644 src/platform/shell.tsx delete mode 100644 src/routes/index.tsx delete mode 100644 src/routes/types.ts delete mode 100644 src/screens/Home.tsx delete mode 100644 src/screens/Login.tsx delete mode 100644 src/screens/Menu.tsx delete mode 100644 src/screens/NotFound.tsx delete mode 100644 src/screens/Notifications.tsx delete mode 100644 src/screens/Profile.tsx delete mode 100644 src/screens/Search.tsx delete mode 100644 src/screens/Signup.tsx delete mode 100644 src/state/auth.ts create mode 100644 src/state/lib/auth.ts create mode 100644 src/state/lib/storage.ts create mode 100644 src/state/models/me.ts delete mode 100644 src/state/storage.ts create mode 100644 src/view/routes/index.tsx create mode 100644 src/view/routes/types.ts create mode 100644 src/view/screens/Home.tsx create mode 100644 src/view/screens/Login.tsx create mode 100644 src/view/screens/Menu.tsx create mode 100644 src/view/screens/NotFound.tsx create mode 100644 src/view/screens/Notifications.tsx create mode 100644 src/view/screens/Profile.tsx create mode 100644 src/view/screens/Search.tsx create mode 100644 src/view/screens/Signup.tsx create mode 100644 src/view/shell/desktop-web/left-column.tsx create mode 100644 src/view/shell/desktop-web/right-column.tsx create mode 100644 src/view/shell/desktop-web/shell.tsx create mode 100644 src/view/shell/index.tsx diff --git a/package.json b/package.json index de09b8214..f45a3e542 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "dependencies": { "@adxp/auth": "*", "@adxp/common": "*", + "@adxp/mock-api": "git+ssh://git@github.com:bluesky-social/adx-mock-api.git#dc669c19d46b6b98dd692f493276303667670502", "@react-native-async-storage/async-storage": "^1.17.6", "@react-navigation/bottom-tabs": "^6.3.1", "@react-navigation/native": "^6.0.10", @@ -32,6 +33,7 @@ "react-native-inappbrowser-reborn": "^3.6.3", "react-native-safe-area-context": "^4.3.1", "react-native-screens": "^3.13.1", + "react-native-url-polyfill": "^1.3.0", "react-native-web": "^0.17.7", "ucans": "0.9.1" }, diff --git a/scripts/testing-server.mjs b/scripts/testing-server.mjs index adc214cf9..f3c68e535 100644 --- a/scripts/testing-server.mjs +++ b/scripts/testing-server.mjs @@ -2,8 +2,11 @@ import {IpldStore} from '@adxp/common' import PDSServer from '@adxp/server/dist/server.js' import PDSDatabase from '@adxp/server/dist/db/index.js' import WSRelayServer from '@adxp/ws-relay/dist/index.js' +import AuthLobbyServer from '@adxp/auth-lobby' const PDS_PORT = 2583 +const AUTH_LOBBY1_PORT = 3001 +const AUTH_LOBBY2_PORT = 3002 const WSR_PORT = 3005 async function start() { @@ -15,11 +18,19 @@ async function start() { await db.createTables() PDSServer(serverBlockstore, db, PDS_PORT) + init(AuthLobbyServer, AUTH_LOBBY1_PORT, 'Auth lobby') + if (process.argv.includes('--relay')) { - WSRelayServer(WSR_PORT) - console.log(`🔁 Relay server running on port ${WSR_PORT}`) + init(AuthLobbyServer, AUTH_LOBBY2_PORT, 'Auth lobby 2') + init(WSRelayServer, WSR_PORT, 'Relay server') } else { - console.log('Include --relay to start the WS Relay') + console.log('Include --relay to start the WS Relay and second auth lobby') } } start() + +function init(fn, port, name) { + const s = fn(port) + s.on('listening', () => console.log(`✔ ${name} running on port ${port}`)) + s.on('error', e => console.log(`${name} failed to start:`, e)) +} diff --git a/src/App.native.tsx b/src/App.native.tsx index 511a8401a..1326b184b 100644 --- a/src/App.native.tsx +++ b/src/App.native.tsx @@ -1,7 +1,8 @@ +import 'react-native-url-polyfill/auto' import React, {useState, useEffect} from 'react' import {whenWebCrypto} from './platform/polyfills.native' import {RootStore, setupState, RootStoreProvider} from './state' -import * as Routes from './routes' +import * as Routes from './view/routes' function App() { const [rootStore, setRootStore] = useState(undefined) diff --git a/src/App.web.tsx b/src/App.web.tsx index 2fadf993f..34b6ac6cb 100644 --- a/src/App.web.tsx +++ b/src/App.web.tsx @@ -1,6 +1,6 @@ import React, {useState, useEffect} from 'react' import {RootStore, setupState, RootStoreProvider} from './state' -import * as Routes from './routes' +import * as Routes from './view/routes' function App() { const [rootStore, setRootStore] = useState(undefined) diff --git a/src/api/index.ts b/src/api/index.ts deleted file mode 100644 index 6f0dc0b38..000000000 --- a/src/api/index.ts +++ /dev/null @@ -1,118 +0,0 @@ -// import {MicroblogDelegator, MicroblogReader, auth} from '@adx/common' -// import * as ucan from 'ucans' - -class MicroblogReader { - constructor(public url: string, public did: any) {} -} -class MicroblogDelegator { - constructor( - public url: string, - public did: any, - public keypair: any, - public ucanStore: any, - ) {} -} -const auth = { - async claimFull(_one: any, _two: any) { - return { - encoded() { - return 'todo' - }, - } - }, -} - -export class API { - userCfg?: UserConfig - reader?: MicroblogReader - writer?: MicroblogDelegator - - setUserCfg(cfg: UserConfig) { - this.userCfg = cfg - this.createReader() - this.createWriter() - } - - private createReader() { - if (!this.userCfg?.serverUrl) { - this.reader = undefined - } else { - this.reader = new MicroblogReader( - this.userCfg.serverUrl, - this.userCfg.did, - ) - } - } - - private createWriter() { - if ( - this.userCfg?.serverUrl && - this.userCfg?.did && - this.userCfg?.keypair && - this.userCfg?.ucanStore - ) { - this.writer = new MicroblogDelegator( - this.userCfg.serverUrl, - this.userCfg.did, - this.userCfg.keypair, - this.userCfg.ucanStore, - ) - } else { - this.writer = undefined - } - } -} - -export interface SerializedUserConfig { - serverUrl?: string - secretKeyStr?: string - rootAuthToken?: string -} - -export class UserConfig { - serverUrl?: string - did?: string - keypair?: any //ucan.EdKeypair - rootAuthToken?: string - ucanStore?: any //ucan.Store - - get hasWriteCaps() { - return Boolean(this.did && this.keypair && this.ucanStore) - } - - static async createTest(serverUrl: string) { - const cfg = new UserConfig() - cfg.serverUrl = serverUrl - cfg.keypair = true //await ucan.EdKeypair.create() - cfg.did = cfg.keypair.did() - cfg.rootAuthToken = (await auth.claimFull(cfg.did, cfg.keypair)).encoded() - cfg.ucanStore = true // await ucan.Store.fromTokens([cfg.rootAuthToken]) - return cfg - } - - static async hydrate(state: SerializedUserConfig) { - const cfg = new UserConfig() - await cfg.hydrate(state) - return cfg - } - - async serialize(): Promise { - return { - serverUrl: this.serverUrl, - secretKeyStr: this.keypair - ? await this.keypair.export('base64') - : undefined, - rootAuthToken: this.rootAuthToken, - } - } - - async hydrate(state: SerializedUserConfig) { - this.serverUrl = state.serverUrl - if (state.secretKeyStr && state.rootAuthToken) { - this.keypair = true // ucan.EdKeypair.fromSecretKey(state.secretKeyStr) - this.did = this.keypair.did() - this.rootAuthToken = state.rootAuthToken - this.ucanStore = true // await ucan.Store.fromTokens([this.rootAuthToken]) - } - } -} diff --git a/src/platform/auth-flow.native.ts b/src/platform/auth-flow.native.ts index 596632f17..3c9bd09eb 100644 --- a/src/platform/auth-flow.native.ts +++ b/src/platform/auth-flow.native.ts @@ -4,7 +4,7 @@ import * as ucan from 'ucans' import {InAppBrowser} from 'react-native-inappbrowser-reborn' import {isWeb} from '../platform/detection' import {extractHashFragment, makeAppUrl} from '../platform/urls' -import {ReactNativeStore, parseUrlForUcan} from '../state/auth' +import {ReactNativeStore, parseUrlForUcan} from '../state/lib/auth' import * as env from '../env' export async function requestAppUcan( diff --git a/src/platform/auth-flow.ts b/src/platform/auth-flow.ts index b96fc58e9..fbc85a373 100644 --- a/src/platform/auth-flow.ts +++ b/src/platform/auth-flow.ts @@ -1,7 +1,7 @@ import * as auth from '@adxp/auth' import * as ucan from 'ucans' import {makeAppUrl} from '../platform/urls' -import {ReactNativeStore} from '../state/auth' +import {ReactNativeStore} from '../state/lib/auth' import * as env from '../env' export async function requestAppUcan( diff --git a/src/platform/desktop-web/left-column.tsx b/src/platform/desktop-web/left-column.tsx deleted file mode 100644 index 082231ec9..000000000 --- a/src/platform/desktop-web/left-column.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import React from 'react' -import {Pressable, View, StyleSheet} from 'react-native' -import {Link} from '@react-navigation/native' -import {useRoute} from '@react-navigation/native' - -export const NavItem: React.FC<{label: string; screen: string}> = ({ - label, - screen, -}) => { - const route = useRoute() - return ( - - [ - // @ts-ignore it does exist! (react-native-web) -prf - state.hovered && styles.navItemHovered, - ]}> - - {label} - - - - ) -} - -export const DesktopLeftColumn: React.FC = () => { - return ( - - - - - - ) -} - -const styles = StyleSheet.create({ - container: { - position: 'absolute', - left: 'calc(50vw - 500px)', - width: '200px', - height: '100%', - }, - navItemHovered: { - backgroundColor: 'gray', - }, - navItemLink: { - padding: '1rem', - }, - navItemLinkSelected: { - color: 'blue', - }, -}) diff --git a/src/platform/desktop-web/right-column.tsx b/src/platform/desktop-web/right-column.tsx deleted file mode 100644 index 5fe65cac8..000000000 --- a/src/platform/desktop-web/right-column.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import React from 'react' -import {Text, View, StyleSheet} from 'react-native' - -export const DesktopRightColumn: React.FC = () => { - return ( - - Right Column - - ) -} - -const styles = StyleSheet.create({ - container: { - position: 'absolute', - right: 'calc(50vw - 500px)', - width: '200px', - height: '100%', - }, -}) diff --git a/src/platform/desktop-web/shell.tsx b/src/platform/desktop-web/shell.tsx deleted file mode 100644 index ef880306b..000000000 --- a/src/platform/desktop-web/shell.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import React from 'react' -import {observer} from 'mobx-react-lite' -import {View, StyleSheet} from 'react-native' -import {DesktopLeftColumn} from './left-column' -import {DesktopRightColumn} from './right-column' -import {useStores} from '../../state' - -export const DesktopWebShell: React.FC = observer(({children}) => { - const store = useStores() - return ( - - {store.session.isAuthed ? ( - <> - - {children} - - - ) : ( - {children} - )} - - ) -}) - -const styles = StyleSheet.create({ - outerContainer: { - height: '100%', - }, - innerContainer: { - marginLeft: 'auto', - marginRight: 'auto', - width: '600px', - height: '100%', - }, -}) diff --git a/src/platform/shell.tsx b/src/platform/shell.tsx deleted file mode 100644 index ec8d51e1f..000000000 --- a/src/platform/shell.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import React from 'react' -import {SafeAreaView} from 'react-native' -import {isDesktopWeb} from './detection' -import {DesktopWebShell} from './desktop-web/shell' - -export const Shell: React.FC = ({children}) => { - return isDesktopWeb ? ( - {children} - ) : ( - {children} - ) -} diff --git a/src/routes/index.tsx b/src/routes/index.tsx deleted file mode 100644 index 32398e9ad..000000000 --- a/src/routes/index.tsx +++ /dev/null @@ -1,110 +0,0 @@ -import React, {useEffect} from 'react' -import {Text, Linking} from 'react-native' -import { - NavigationContainer, - LinkingOptions, - RouteProp, - ParamListBase, -} from '@react-navigation/native' -import {createNativeStackNavigator} from '@react-navigation/native-stack' -import {createBottomTabNavigator} from '@react-navigation/bottom-tabs' -import {observer} from 'mobx-react-lite' -import type {RootTabsParamList} from './types' -import {useStores} from '../state' -import * as platform from '../platform/detection' -import {Home} from '../screens/Home' -import {Search} from '../screens/Search' -import {Notifications} from '../screens/Notifications' -import {Menu} from '../screens/Menu' -import {Profile} from '../screens/Profile' -import {Login} from '../screens/Login' -import {Signup} from '../screens/Signup' -import {NotFound} from '../screens/NotFound' - -const linking: LinkingOptions = { - prefixes: [ - 'http://localhost:3000', // local dev - 'https://pubsq.pfrazee.com', // test server (universal links only) - 'pubsqapp://', // custom protocol (ios) - 'pubsq://app', // custom protocol (android) - ], - config: { - screens: { - Home: '', - Profile: 'profile/:name', - Search: 'search', - Notifications: 'notifications', - Menu: 'menu', - Login: 'login', - Signup: 'signup', - NotFound: '*', - }, - }, -} - -export const RootTabs = createBottomTabNavigator() -export const PrimaryStack = createNativeStackNavigator() - -const tabBarScreenOptions = ({ - route, -}: { - route: RouteProp -}) => ({ - headerShown: false, - tabBarIcon: (_state: {focused: boolean; color: string; size: number}) => { - // TODO: icons - return {route.name?.[0] || ''} - }, -}) - -const HIDE_TAB = {tabBarButton: () => null} - -export const Root = observer(() => { - const store = useStores() - - useEffect(() => { - console.log('Initial link setup') - Linking.getInitialURL().then((url: string | null) => { - console.log('Initial url', url) - }) - Linking.addEventListener('url', ({url}) => { - console.log('Deep link opened with', url) - }) - }, []) - - // hide the tabbar on desktop web - const tabBar = platform.isDesktopWeb ? () => null : undefined - - return ( - Loading...}> - - {store.session.isAuthed ? ( - <> - - - - - - - ) : ( - <> - - - - )} - - - - ) -}) diff --git a/src/routes/types.ts b/src/routes/types.ts deleted file mode 100644 index d92594bbe..000000000 --- a/src/routes/types.ts +++ /dev/null @@ -1,36 +0,0 @@ -import type {StackScreenProps} from '@react-navigation/stack' - -export type RootTabsParamList = { - Home: undefined - Search: undefined - Notifications: undefined - Menu: undefined - Profile: {name: string} - Login: undefined - Signup: undefined - NotFound: undefined -} -export type RootTabsScreenProps = - StackScreenProps - -/* -NOTE -this is leftover from a nested nav implementation -keeping it around for future reference --prf - -import type {NavigatorScreenParams} from '@react-navigation/native' -import type {CompositeScreenProps} from '@react-navigation/native' -import type {BottomTabScreenProps} from '@react-navigation/bottom-tabs' - -Container: NavigatorScreenParams -export type PrimaryStacksParamList = { - Home: undefined - Profile: {name: string} -} -export type PrimaryStacksScreenProps = - CompositeScreenProps< - BottomTabScreenProps, - RootTabsScreenProps - > -*/ diff --git a/src/screens/Home.tsx b/src/screens/Home.tsx deleted file mode 100644 index ed95121ea..000000000 --- a/src/screens/Home.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import React from 'react' -import {Text, Button, View} from 'react-native' -import {Shell} from '../platform/shell' -import type {RootTabsScreenProps} from '../routes/types' -import {useStores} from '../state' - -export function Home({navigation}: RootTabsScreenProps<'Home'>) { - const store = useStores() - return ( - - - Home -