Skip to content

Commit

Permalink
Merge pull request #704 from sparcs-kaist/#702-app-core-package-init
Browse files Browse the repository at this point in the history
#705 `@taxi/app` init
  • Loading branch information
SnowSuno authored Jan 30, 2024
2 parents 12fac24 + 036ac16 commit fcf0786
Show file tree
Hide file tree
Showing 35 changed files with 4,282 additions and 614 deletions.
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node-linker=hoisted
6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@
"private": true,
"scripts": {
"preinstall": "npx only-allow pnpm",
"web": "pnpm -F @taxi/web",
"app": "pnpm --filter @taxi/app",
"web": "pnpm --filter @taxi/web",
"start:app": "pnpm -r --stream start",
"start:app:prod": "NODE_ENV=production pnpm --filter @taxi/app start",
"start:web": "pnpm --filter @taxi/web... start",
"build:all": "pnpm -r build",
"build:web": "pnpm --filter @taxi/web... build",
"test": "pnpm -r test",
Expand Down
35 changes: 35 additions & 0 deletions packages/app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files

# dependencies
node_modules/

# Expo
.expo/
dist/
web-build/

# Native
*.orig.*
*.jks
*.p8
*.p12
*.key
*.mobileprovision

# Metro
.metro-health-check*

# debug
npm-debug.*
yarn-debug.*
yarn-error.*

# macOS
.DS_Store
*.pem

# local env files
.env*.local

# typescript
*.tsbuildinfo
40 changes: 40 additions & 0 deletions packages/app/app.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import type { ConfigContext, ExpoConfig } from "@expo/config";
import ip from "internal-ip";

const isDev = process.env.NODE_ENV === "development";

export default ({ config }: ConfigContext): Partial<ExpoConfig> => ({
...config,
name: "Taxi for KAIST",
slug: "Taxi-for-KAIST",
version: "1.0.0",
orientation: "portrait",
icon: "./assets/icon.png",
userInterfaceStyle: "light",
splash: {
image: "./assets/splash.png",
resizeMode: "contain",
backgroundColor: "#ffffff",
},
assetBundlePatterns: ["**/*"],
ios: {
supportsTablet: true,
},
android: {
adaptiveIcon: {
foregroundImage: "./assets/adaptive-icon.png",
backgroundColor: "#ffffff",
},
},
web: {
favicon: "./assets/favicon.png",
},
experiments: {
tsconfigPaths: true,
},
extra: {
SERVER_URL: isDev
? `http://${ip.v4.sync()}:3000`
: "https://taxi.sparcs.org",
},
});
Binary file added packages/app/assets/adaptive-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added packages/app/assets/favicon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added packages/app/assets/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added packages/app/assets/splash.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions packages/app/babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = function(api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
};
};
26 changes: 26 additions & 0 deletions packages/app/metro.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Learn more https://docs.expo.dev/guides/monorepos
const { getDefaultConfig } = require('expo/metro-config');
const { FileStore } = require('metro-cache');
const path = require('path');

const projectRoot = __dirname;
const workspaceRoot = path.resolve(projectRoot, '../..');

const config = getDefaultConfig(projectRoot);

// #1 - Watch all files in the monorepo
config.watchFolders = [workspaceRoot];
// #3 - Force resolving nested modules to the folders below
config.resolver.disableHierarchicalLookup = true;
// #2 - Try resolving with project modules first, then workspace modules
config.resolver.nodeModulesPaths = [
path.resolve(projectRoot, 'node_modules'),
path.resolve(workspaceRoot, 'node_modules'),
];

// Use turborepo to restore the cache when possible
config.cacheStores = [
new FileStore({ root: path.join(projectRoot, 'node_modules', '.cache', 'metro') }),
];

module.exports = config;
1 change: 1 addition & 0 deletions packages/app/node.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/// <reference types="@types/node" />
32 changes: 32 additions & 0 deletions packages/app/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"name": "@taxi/app",
"version": "1.0.0",
"main": "src/main.js",
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web"
},
"dependencies": {
"@react-navigation/bottom-tabs": "^6.5.11",
"@react-navigation/native": "^6.1.9",
"@react-navigation/stack": "^6.3.20",
"expo": "~49.0.15",
"expo-status-bar": "~1.6.0",
"react": "18.2.0",
"react-native": "0.72.6",
"react-native-webview": "^13.6.4",
"shallow-equal": "^3.1.0",
"url-pattern": "^1.0.3",
"uuid": "3.4.0"
},
"devDependencies": {
"@babel/core": "^7.20.0",
"@types/node": "^20.11.5",
"@types/react": "~18.2.14",
"internal-ip": "^6.2.0",
"typescript": "^5.1.3"
},
"private": true
}
15 changes: 15 additions & 0 deletions packages/app/src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { RootStack } from "@/screens";
import { NavigationContainer } from "@react-navigation/native";
import { StatusBar } from "expo-status-bar";
import { View } from "react-native";

export function App() {
return (
<View style={{ flex: 1 }}>
<NavigationContainer>
<RootStack />
</NavigationContainer>
<StatusBar style="auto" />
</View>
);
}
44 changes: 44 additions & 0 deletions packages/app/src/components/TaxiWebView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { env } from "@/env";
import { mapWebRoutes } from "@/navigation/web";
import { isSameScreen } from "@/utils/navigation";
import { useIsFocused, useNavigation } from "@react-navigation/native";
import React, { useCallback, useMemo, useRef } from "react";
import { Platform } from "react-native";
import { WebView, type WebViewNavigation } from "react-native-webview";

type TaxiWebViewProps = {
path: string;
};

export const TaxiWebView: React.FC<TaxiWebViewProps> = ({ path }) => {
const uri = useMemo(
() => (path.startsWith("/") ? env.SERVER_URL + path : path),
[path]
);
const ref = useRef<WebView>(null);
const currentScreen = useMemo(() => mapWebRoutes(uri), [uri]);
const isFocused = useIsFocused();
const navigation = useNavigation();

const onNavigationStateChange = useCallback(
(event: WebViewNavigation) => {
const screen = mapWebRoutes(event.url);
if (!isFocused || isSameScreen(currentScreen, screen)) return;

navigation.navigate(...screen);
ref.current?.stopLoading();
ref.current?.goBack();
},
[isFocused, currentScreen, navigation]
);

return (
<WebView
cacheEnabled
ref={ref}
userAgent={`taxi-app-webview/${Platform.OS}`}
source={{ uri }}
onNavigationStateChange={onNavigationStateChange}
/>
);
};
6 changes: 6 additions & 0 deletions packages/app/src/env.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import Constants from "expo-constants";

export const env = {
SERVER_URL: "https://taxi.sparcs.org",
...Constants.expoConfig?.extra,
};
4 changes: 4 additions & 0 deletions packages/app/src/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { registerRootComponent } from "expo";
import { App }from "./App";

registerRootComponent(App);
41 changes: 41 additions & 0 deletions packages/app/src/navigation/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/**
* Native tab navigation is disabled temporarily. (handled inside webview)
* Uncomment the commented code to enable native tab navigation.
*/
// import type { BottomTabScreenProps } from "@react-navigation/bottom-tabs";
// import type {
// CompositeScreenProps,
// NavigatorScreenParams,
// } from "@react-navigation/native";
import type { StackScreenProps } from "@react-navigation/stack";

// export type HomeTabParamList = {
// Home: undefined;
// Search: undefined;
// AddRoom: undefined;
// MyRoom: undefined;
// MyPage: undefined;
// };

export type RootStackParamList = {
// HomeTab: NavigatorScreenParams<HomeTabParamList>;
Home: undefined;
Event: { eventName: string };
Chatting: { roomId: string };
Web: { uri: string };
};

export type RootStackScreenProps<T extends keyof RootStackParamList> =
StackScreenProps<RootStackParamList, T>;

// export type HomeTabScreenProps<T extends keyof HomeTabParamList> =
// CompositeScreenProps<
// BottomTabScreenProps<HomeTabParamList, T>,
// RootStackScreenProps<keyof RootStackParamList>
// >;

declare global {
namespace ReactNavigation {
interface RootParamList extends RootStackParamList {}
}
}
13 changes: 13 additions & 0 deletions packages/app/src/navigation/web.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { route, routes, screen } from "@/utils/navigation";

export const mapWebRoutes = routes([
route("/", () => screen("Home")),
route("/home(/:roomId)", () => screen("Home")),
route("/event/:eventName", ({ eventName }) => screen("Event", { eventName })),
route("/search", () => screen("Home")),
route("/addroom", () => screen("Home")),
route("/myroom", () => screen("Home")),
route("/myroom/:roomId", ({ roomId }) => screen("Chatting", { roomId })),
route("/mypage", () => screen("Home")),
route("/chatting/:roomId", ({ roomId }) => screen("Chatting", { roomId })),
]);
17 changes: 17 additions & 0 deletions packages/app/src/screens/Chatting.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { RootStackScreenProps } from "@/navigation/types";
import React from "react";
import { KeyboardAvoidingView, Platform } from "react-native";

import { TaxiWebView } from "@/components/TaxiWebView";

export const Chatting: React.FC<RootStackScreenProps<"Chatting">> = ({
route: { params },
}) => (
<KeyboardAvoidingView
behavior={Platform.select({ ios: "padding", android: "height" })}
style={{ flex: 1 }}
// @TODO: Remove keyboard avoiding in web
>
<TaxiWebView path={`/chatting/${params.roomId}`} />
</KeyboardAvoidingView>
);
8 changes: 8 additions & 0 deletions packages/app/src/screens/Event.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { RootStackScreenProps } from "@/navigation/types";
import React from "react";

import { TaxiWebView } from "@/components/TaxiWebView";

export const Event: React.FC<RootStackScreenProps<"Event">> = ({
route: { params },
}) => <TaxiWebView path={`/event/${params.eventName}`} />;
8 changes: 8 additions & 0 deletions packages/app/src/screens/Home.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { RootStackScreenProps } from "@/navigation/types";
import React from "react";

import { TaxiWebView } from "@/components/TaxiWebView";

export const Home: React.FC<RootStackScreenProps<"Home">> = () => (
<TaxiWebView path="/home" />
);
8 changes: 8 additions & 0 deletions packages/app/src/screens/HomeTab/AddRoom.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { HomeTabScreenProps } from "@/navigation/types";
import React from "react";

import { TaxiWebView } from "@/components/TaxiWebView";

export const AddRoom: React.FC<HomeTabScreenProps<"AddRoom">> = () => (
<TaxiWebView path="/addroom" />
);
8 changes: 8 additions & 0 deletions packages/app/src/screens/HomeTab/Home.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { HomeTabScreenProps } from "@/navigation/types";
import React from "react";

import { TaxiWebView } from "@/components/TaxiWebView";

export const Home: React.FC<HomeTabScreenProps<"Home">> = () => (
<TaxiWebView path="/home" />
);
8 changes: 8 additions & 0 deletions packages/app/src/screens/HomeTab/MyPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { HomeTabScreenProps } from "@/navigation/types";
import React from "react";

import { TaxiWebView } from "@/components/TaxiWebView";

export const MyPage: React.FC<HomeTabScreenProps<"MyPage">> = () => (
<TaxiWebView path="/mypage" />
);
8 changes: 8 additions & 0 deletions packages/app/src/screens/HomeTab/MyRoom.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { HomeTabScreenProps } from "@/navigation/types";
import React from "react";

import { TaxiWebView } from "@/components/TaxiWebView";

export const MyRoom: React.FC<HomeTabScreenProps<"MyRoom">> = () => (
<TaxiWebView path="/myroom" />
);
8 changes: 8 additions & 0 deletions packages/app/src/screens/HomeTab/Search.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { HomeTabScreenProps } from "@/navigation/types";
import React from "react";

import { TaxiWebView } from "@/components/TaxiWebView";

export const Search: React.FC<HomeTabScreenProps<"Search">> = () => (
<TaxiWebView path="/search" />
);
25 changes: 25 additions & 0 deletions packages/app/src/screens/HomeTab/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import type { HomeTabParamList } from "@/navigation/types";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
import React from "react";

import { AddRoom } from "./AddRoom";
import { Home } from "./Home";
import { MyPage } from "./MyPage";
import { MyRoom } from "./MyRoom";
import { Search } from "./Search";

const Tab = createBottomTabNavigator<HomeTabParamList>();

export const HomeTab: React.FC = () => (
<Tab.Navigator screenOptions={{ headerShown: false }}>
<Tab.Screen name="Home" options={{ title: "홈" }} component={Home} />
<Tab.Screen name="Search" options={{ title: "검색" }} component={Search} />
<Tab.Screen
name="AddRoom"
options={{ title: "개설" }}
component={AddRoom}
/>
<Tab.Screen name="MyRoom" options={{ title: "내 방" }} component={MyRoom} />
<Tab.Screen name="MyPage" options={{ title: "마이" }} component={MyPage} />
</Tab.Navigator>
);
Loading

0 comments on commit fcf0786

Please sign in to comment.