Compare commits
1 commit
Author | SHA1 | Date | |
---|---|---|---|
|
a656b409ac |
19 changed files with 103 additions and 4452 deletions
|
@ -1,15 +1,11 @@
|
||||||
/* eslint-env node */
|
/* eslint-env node */
|
||||||
module.exports = {
|
module.exports = {
|
||||||
extends: [
|
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended'],
|
||||||
"eslint:recommended",
|
parser: '@typescript-eslint/parser',
|
||||||
"plugin:@typescript-eslint/recommended",
|
plugins: ['@typescript-eslint'],
|
||||||
"prettier",
|
|
||||||
],
|
|
||||||
parser: "@typescript-eslint/parser",
|
|
||||||
plugins: ["@typescript-eslint"],
|
|
||||||
root: true,
|
root: true,
|
||||||
ignorePatterns: ["babel.config.js", "jest.config.js", "node_modules/"],
|
ignorePatterns: ["babel.config.js", "jest.config.js", "node_modules/"],
|
||||||
rules: {
|
rules: {
|
||||||
"@typescript-eslint/explicit-function-return-type": "error",
|
"@typescript-eslint/explicit-function-return-type": "error"
|
||||||
},
|
}
|
||||||
};
|
};
|
71
App.tsx
71
App.tsx
|
@ -1,74 +1,15 @@
|
||||||
import { StatusBar } from "expo-status-bar";
|
import { StatusBar } from "expo-status-bar";
|
||||||
|
import { Text, View } from "react-native";
|
||||||
import { style } from "./src/util/style";
|
import { style } from "./src/util/style";
|
||||||
|
|
||||||
import { PostsContainer } from "./src/components/PostsContainer";
|
import { PostsContainer } from "./src/components/PostsContainer";
|
||||||
import { NavigationContainer } from "@react-navigation/native";
|
|
||||||
import { createNativeStackNavigator } from "@react-navigation/native-stack";
|
|
||||||
import { NewPostContainer } from "./src/components/NewPostContainer";
|
|
||||||
import { NativeStackNavigationProp } from "@react-navigation/native-stack";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* RootStackParamList defines the possible screens in the app.
|
|
||||||
* @typedef {object} RootStackParamList
|
|
||||||
* @property {undefined} Home - Home screen.
|
|
||||||
* @property {undefined} New - New post screen.
|
|
||||||
*/
|
|
||||||
|
|
||||||
type RootStackParamList = {
|
|
||||||
Home: undefined;
|
|
||||||
New: undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* HomeScreenNavigationProp represents the navigation prop for the Home screen.
|
|
||||||
* @typedef {object} HomeScreenNavigationProp
|
|
||||||
* @property {Function} navigate - Function to navigate to a different screen.
|
|
||||||
*/
|
|
||||||
|
|
||||||
export type HomeScreenNavigationProp = NativeStackNavigationProp<
|
|
||||||
RootStackParamList,
|
|
||||||
"Home"
|
|
||||||
>;
|
|
||||||
|
|
||||||
const Stack = createNativeStackNavigator();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* App function represents the main application component.
|
|
||||||
* @returns {JSX.Element} - The rendered App component.
|
|
||||||
*/
|
|
||||||
export default function App(): JSX.Element {
|
export default function App(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<>
|
<View style={style.app}>
|
||||||
{/* Sets the status bar style */}
|
<Text>Open up App.tsx to start working on your app!</Text>
|
||||||
<StatusBar style="light" />
|
<StatusBar style="auto" />
|
||||||
|
<PostsContainer />
|
||||||
{/* Navigation container for the app */}
|
</View>
|
||||||
<NavigationContainer>
|
|
||||||
{/* Stack navigator for different screens */}
|
|
||||||
<Stack.Navigator>
|
|
||||||
{/* Home screen */}
|
|
||||||
<Stack.Screen
|
|
||||||
name="Home"
|
|
||||||
component={PostsContainer}
|
|
||||||
options={options}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* New post screen */}
|
|
||||||
<Stack.Screen
|
|
||||||
name="New"
|
|
||||||
options={options}
|
|
||||||
component={NewPostContainer}
|
|
||||||
/>
|
|
||||||
</Stack.Navigator>
|
|
||||||
</NavigationContainer>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Header options for the screens
|
|
||||||
const options = {
|
|
||||||
headerStyle: style.header,
|
|
||||||
headerTitleStyle: style.headerTitle,
|
|
||||||
headerTintColor: "#fff",
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
3
Justfile
3
Justfile
|
@ -7,8 +7,5 @@ npm-install:
|
||||||
clean:
|
clean:
|
||||||
rm -rf node_modules .expo
|
rm -rf node_modules .expo
|
||||||
|
|
||||||
fmt: npm-install
|
|
||||||
npm run format
|
|
||||||
|
|
||||||
lint: npm-install
|
lint: npm-install
|
||||||
npm run lint
|
npm run lint
|
20
README.md
20
README.md
|
@ -1,20 +0,0 @@
|
||||||
# FrostByte Native Client
|
|
||||||
|
|
||||||
This is a native client for the FrostByte forum. It is written in TypeScript and uses the Expo build system to build for Android and iOS.
|
|
||||||
A Justfile is included for convenience.
|
|
||||||
|
|
||||||
## Details
|
|
||||||
|
|
||||||
### The server architecture, also known as a monolith, all according to the YAGNI principle
|
|
||||||
|
|
||||||
![Boi Architecture](misc/boi_architecture.svg)
|
|
||||||
|
|
||||||
### This is a state diagram of the client application
|
|
||||||
|
|
||||||
![Homosapien stuff](misc/homosapien.svg)
|
|
||||||
|
|
||||||
## Results
|
|
||||||
|
|
||||||
Draft A | Draft B | Final Product
|
|
||||||
:----------------------------:|:----------------------------:|:---------------------------:
|
|
||||||
![Draft One](misc/draft2.png) | ![Draft Two](misc/draft.png) | ![Final Product](misc/product.png)
|
|
4
app.json
4
app.json
|
@ -11,7 +11,9 @@
|
||||||
"resizeMode": "contain",
|
"resizeMode": "contain",
|
||||||
"backgroundColor": "#ffffff"
|
"backgroundColor": "#ffffff"
|
||||||
},
|
},
|
||||||
"assetBundlePatterns": ["**/*"],
|
"assetBundlePatterns": [
|
||||||
|
"**/*"
|
||||||
|
],
|
||||||
"ios": {
|
"ios": {
|
||||||
"supportsTablet": true
|
"supportsTablet": true
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
module.exports = function (api) {
|
module.exports = function(api) {
|
||||||
api.cache(true);
|
api.cache(true);
|
||||||
return {
|
return {
|
||||||
presets: ["babel-preset-expo"],
|
presets: ['babel-preset-expo'],
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 30 KiB |
BIN
misc/draft.png
BIN
misc/draft.png
Binary file not shown.
Before Width: | Height: | Size: 171 KiB |
BIN
misc/draft2.png
BIN
misc/draft2.png
Binary file not shown.
Before Width: | Height: | Size: 21 KiB |
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 7 KiB |
BIN
misc/product.png
BIN
misc/product.png
Binary file not shown.
Before Width: | Height: | Size: 415 KiB |
4058
package-lock.json
generated
4058
package-lock.json
generated
File diff suppressed because it is too large
Load diff
14
package.json
14
package.json
|
@ -7,21 +7,13 @@
|
||||||
"android": "expo start --android",
|
"android": "expo start --android",
|
||||||
"ios": "expo start --ios",
|
"ios": "expo start --ios",
|
||||||
"web": "expo start --web",
|
"web": "expo start --web",
|
||||||
"lint": "tsc --noEmit && eslint --ext .js,.jsx,.ts,.tsx ./",
|
"lint": "tsc --noEmit && eslint --ext .js,.jsx,.ts,.tsx ./"
|
||||||
"format": "prettier --write ."
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@react-navigation/native": "^6.1.9",
|
|
||||||
"@react-navigation/native-stack": "^6.9.17",
|
|
||||||
"expo": "~49.0.15",
|
"expo": "~49.0.15",
|
||||||
"expo-status-bar": "~1.6.0",
|
"expo-status-bar": "~1.6.0",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
"react-native": "0.72.6",
|
"react-native": "0.72.6"
|
||||||
"react-native-safe-area-context": "4.6.3",
|
|
||||||
"react-native-screens": "~3.22.0",
|
|
||||||
"react-native-web": "~0.19.6",
|
|
||||||
"react-dom": "18.2.0",
|
|
||||||
"@expo/webpack-config": "^19.0.0"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.20.0",
|
"@babel/core": "^7.20.0",
|
||||||
|
@ -29,8 +21,6 @@
|
||||||
"@typescript-eslint/eslint-plugin": "^6.14.0",
|
"@typescript-eslint/eslint-plugin": "^6.14.0",
|
||||||
"@typescript-eslint/parser": "^6.14.0",
|
"@typescript-eslint/parser": "^6.14.0",
|
||||||
"eslint": "^8.55.0",
|
"eslint": "^8.55.0",
|
||||||
"eslint-config-prettier": "^9.1.0",
|
|
||||||
"prettier": "3.1.1",
|
|
||||||
"typescript": "^5.3.3"
|
"typescript": "^5.3.3"
|
||||||
},
|
},
|
||||||
"private": true
|
"private": true
|
||||||
|
|
|
@ -1,86 +0,0 @@
|
||||||
import React from "react";
|
|
||||||
import { View, Text, TextInput, Button } from "react-native";
|
|
||||||
import { style } from "../util/style";
|
|
||||||
import { createPost, NewPost, submitLogin } from "../util/api";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* NewPostContainer component for handling new post creation.
|
|
||||||
*
|
|
||||||
* @component
|
|
||||||
* @param {object} props - React component props.
|
|
||||||
* @param {object} props.navigation - Navigation object for navigating between screens.
|
|
||||||
* @returns {JSX.Element} - Rendered NewPostContainer component.
|
|
||||||
*/
|
|
||||||
export function NewPostContainer({ navigation }): JSX.Element {
|
|
||||||
/**
|
|
||||||
* State hook for managing the current input text.
|
|
||||||
* @type {[string, React.Dispatch<React.SetStateAction<string>>]}
|
|
||||||
*/
|
|
||||||
const [currentInput, setCurrentInput] = React.useState<string>("");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* State hook for managing the current input error message.
|
|
||||||
* @type {[string, React.Dispatch<React.SetStateAction<string>>]}
|
|
||||||
*/
|
|
||||||
const [currentInputError, setCurrentInputError] = React.useState<string>("");
|
|
||||||
|
|
||||||
return (
|
|
||||||
<View style={style.newPostContainer}>
|
|
||||||
{/* Input field for the new post */}
|
|
||||||
<TextInput
|
|
||||||
style={style.newPostInput}
|
|
||||||
placeholder="New Post"
|
|
||||||
onChangeText={(text) => {
|
|
||||||
setCurrentInput(text);
|
|
||||||
setCurrentInputError("");
|
|
||||||
}}
|
|
||||||
value={currentInput}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* Button to submit the new post */}
|
|
||||||
<Button
|
|
||||||
title="Post"
|
|
||||||
onPress={() => {
|
|
||||||
/**
|
|
||||||
* Asynchronously submits the new post.
|
|
||||||
*
|
|
||||||
* @async
|
|
||||||
* @function
|
|
||||||
* @returns {Promise<void>} - A Promise that resolves when the post is successfully submitted.
|
|
||||||
*/
|
|
||||||
async function submit(): Promise<void> {
|
|
||||||
// Submit login to obtain user token
|
|
||||||
const user = (await submitLogin("demouser", "demopw")) ?? {
|
|
||||||
token: "",
|
|
||||||
};
|
|
||||||
|
|
||||||
// Create new post object
|
|
||||||
const newPost: NewPost = {
|
|
||||||
content: currentInput,
|
|
||||||
token: user.token,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Call API to create the post
|
|
||||||
await createPost(newPost);
|
|
||||||
|
|
||||||
// Reset the input field
|
|
||||||
setCurrentInput("");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the input is not empty before submitting
|
|
||||||
if (currentInput.length > 0) {
|
|
||||||
submit();
|
|
||||||
// Navigate to the Home screen after successful post submission
|
|
||||||
navigation.navigate("Home");
|
|
||||||
} else {
|
|
||||||
// Set an error message if the input is empty
|
|
||||||
setCurrentInputError("Post must not be empty!");
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* Display error message if there's any */}
|
|
||||||
<Text style={style.errorText}>{currentInputError}</Text>
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -10,9 +10,13 @@ import { style } from "../util/style";
|
||||||
* @returns {JSX.Element} The JSX for the Post
|
* @returns {JSX.Element} The JSX for the Post
|
||||||
*/
|
*/
|
||||||
export function PostView({ post }: { post: Post }): JSX.Element {
|
export function PostView({ post }: { post: Post }): JSX.Element {
|
||||||
|
// WARNING THIS IS NOT ACCEPTABLE WARNING REMOVE WARNING
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
const [thisPost, setThisPost] = React.useState<Post>(post);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={style.postView}>
|
<View style={style.postView}>
|
||||||
<Text style={style.postFont}>{post.id + " " + post.content}</Text>
|
<Text style={style.postFont}>{thisPost.content}</Text>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,124 +1,66 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Button, RefreshControl } from "react-native";
|
import { View, Text } from "react-native";
|
||||||
import { getPostsInterval, Post } from "../util/api";
|
import { getPost, getPosts, Post } from "../util/api";
|
||||||
import { PostView } from "./PostView";
|
import { PostView } from "./PostView";
|
||||||
import { style } from "../util/style";
|
import { style } from "../util/style";
|
||||||
import { SafeAreaView } from "react-native";
|
import { SafeAreaView } from "react-native";
|
||||||
import { VirtualizedList } from "react-native";
|
import { VirtualizedList } from "react-native";
|
||||||
|
|
||||||
const WINDOW_SIZE = 20;
|
type ItemData = {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
type ItemProps = {
|
||||||
* PostsContainer component for displaying a list of posts.
|
title: string;
|
||||||
*
|
};
|
||||||
* @component
|
|
||||||
* @param {object} props - React component props.
|
|
||||||
* @param {object} props.navigation - Navigation object for navigating between screens.
|
|
||||||
* @returns {JSX.Element} - Rendered PostsContainer component.
|
|
||||||
*/
|
|
||||||
export function PostsContainer({ navigation }): JSX.Element {
|
|
||||||
const [postData, setPostData] = React.useState<Post[]>([]);
|
|
||||||
const [offset, setOffset] = React.useState<number>(0);
|
|
||||||
const [refreshing, setRefreshing] = React.useState<boolean>(false);
|
|
||||||
|
|
||||||
const handleEndReached = (): void => {
|
const Item = ({title}: ItemProps): JSX.Element => (
|
||||||
setOffset(offset + WINDOW_SIZE);
|
<View style={style.postView}>
|
||||||
fetchMorePosts();
|
<Text style={style.postFont}>{title}</Text>
|
||||||
};
|
</View>
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
export function PostsContainer(): JSX.Element {
|
||||||
* Handles the pull-to-refresh action.
|
// const [posts, setPosts] = React.useState<Post[]>([]);
|
||||||
* @function
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
function onRefresh(): void {
|
|
||||||
refreshPosts();
|
|
||||||
}
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
// React.useEffect(() => {
|
||||||
refreshPosts();
|
// refreshPosts();
|
||||||
}, []);
|
// }, []);
|
||||||
|
|
||||||
/**
|
const getItemCount = (_data: unknown): number => 50;
|
||||||
* Full refresh of posts.
|
|
||||||
* @function
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
function refreshPosts(): void {
|
|
||||||
setRefreshing(true);
|
|
||||||
setPostData([]);
|
|
||||||
setOffset(WINDOW_SIZE);
|
|
||||||
|
|
||||||
// Fetches posts from the API and updates the state.
|
// function refreshPosts(): void {
|
||||||
async function fetchPosts(): Promise<void> {
|
// async function fetchPosts(): Promise<void> {
|
||||||
setPostData(await getPostsInterval(0, WINDOW_SIZE));
|
// const posts = await getPosts();
|
||||||
}
|
// setPosts(posts);
|
||||||
|
// }
|
||||||
|
// fetchPosts();
|
||||||
|
// }
|
||||||
|
|
||||||
fetchPosts();
|
// function getItemCount(): number {
|
||||||
setRefreshing(false);
|
// return posts.length;
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
const getItem = (_data: unknown, index: number): ItemData => ({
|
||||||
* Fetches more posts from the API and updates the state.
|
id: Math.random().toString(12).substring(0),
|
||||||
* @function
|
title: `Item ${index + 1}`,
|
||||||
* @returns {void}
|
});
|
||||||
*/
|
|
||||||
function fetchMorePosts(): void {
|
|
||||||
async function fetchPosts(): Promise<void> {
|
|
||||||
setPostData([...postData, ...(await getPostsInterval(offset, WINDOW_SIZE))]);
|
|
||||||
}
|
|
||||||
|
|
||||||
fetchPosts();
|
// const getItem = async (data: any, index: number): Promise<Post> => {
|
||||||
}
|
// const p = await getPost(index);
|
||||||
|
// return p;
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// };
|
||||||
const getItemCount = (_data: unknown): number => postData.length;
|
|
||||||
|
|
||||||
const getItem = (_data: unknown, index: number): Post => postData[index];
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
|
||||||
{/* Navigation button to create a new post */}
|
|
||||||
<NavButton onPress={() => navigation.navigate("New")} text="New Post" />
|
|
||||||
<SafeAreaView style={style.postsContainer}>
|
<SafeAreaView style={style.postsContainer}>
|
||||||
{/* VirtualizedList to render the list of posts */}
|
|
||||||
<VirtualizedList
|
<VirtualizedList
|
||||||
data={postData}
|
|
||||||
initialNumToRender={4}
|
initialNumToRender={4}
|
||||||
renderItem={({ item }) => <PostView key={item.id} post={item} />}
|
renderItem={({ item }) => <Item title={item.title} />}
|
||||||
keyExtractor={(item: Post) => item.id}
|
keyExtractor={(item: ItemData) => item.id}
|
||||||
getItemCount={getItemCount}
|
getItemCount={getItemCount}
|
||||||
getItem={getItem}
|
getItem={getItem}
|
||||||
onEndReached={handleEndReached}
|
|
||||||
onEndReachedThreshold={0.4}
|
|
||||||
refreshControl={
|
|
||||||
<RefreshControl
|
|
||||||
refreshing={refreshing}
|
|
||||||
onRefresh={onRefresh}
|
|
||||||
colors={["#007AFF"]}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* NavButton component for rendering a navigation button.
|
|
||||||
*
|
|
||||||
* @component
|
|
||||||
* @param {object} props - React component props.
|
|
||||||
* @param {Function} props.onPress - Function to be called on button press.
|
|
||||||
* @param {string} props.text - Text to be displayed on the button.
|
|
||||||
* @returns {JSX.Element} - Rendered NavButton component.
|
|
||||||
*/
|
|
||||||
function NavButton({
|
|
||||||
onPress,
|
|
||||||
text,
|
|
||||||
}: {
|
|
||||||
onPress: () => void;
|
|
||||||
text: string;
|
|
||||||
}): JSX.Element {
|
|
||||||
return <Button title={text} onPress={onPress} />;
|
|
||||||
}
|
|
|
@ -56,15 +56,6 @@ export async function getPosts(): Promise<Post[]> {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getPostsInterval(
|
|
||||||
offset: number,
|
|
||||||
limit: number,
|
|
||||||
): Promise<Post[]> {
|
|
||||||
const res = await fetch(URL + `/api/posts?offset=${offset}&limit=${limit}`);
|
|
||||||
const data = await res.json();
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches a specific post by its ID from the API.
|
* Fetches a specific post by its ID from the API.
|
||||||
* @async
|
* @async
|
||||||
|
@ -107,7 +98,7 @@ export async function createPost(post: NewPost): Promise<void> {
|
||||||
export async function submitRegistration(
|
export async function submitRegistration(
|
||||||
username: string,
|
username: string,
|
||||||
password: string,
|
password: string,
|
||||||
captcha: string,
|
captcha: string
|
||||||
): Promise<AuthResponse | undefined> {
|
): Promise<AuthResponse | undefined> {
|
||||||
const response = await fetch(URL + "/api/register", {
|
const response = await fetch(URL + "/api/register", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
|
@ -128,7 +119,7 @@ export async function submitRegistration(
|
||||||
*/
|
*/
|
||||||
export async function submitLogin(
|
export async function submitLogin(
|
||||||
username: string,
|
username: string,
|
||||||
password: string,
|
password: string
|
||||||
): Promise<AuthResponse | undefined> {
|
): Promise<AuthResponse | undefined> {
|
||||||
if (username == "" || password == "") return;
|
if (username == "" || password == "") return;
|
||||||
|
|
||||||
|
|
|
@ -1,28 +1,28 @@
|
||||||
import { StyleSheet } from "react-native";
|
import { StyleSheet } from 'react-native';
|
||||||
|
|
||||||
const colorScheme = {
|
const colorScheme = {
|
||||||
background: "#273043",
|
background: "#273043",
|
||||||
postBox: "#9197AE",
|
postBox: "#9197AE",
|
||||||
postFont: "#EFF6EE",
|
postFont: "#EFF6EE",
|
||||||
accept: "#4D8B31",
|
accept: "#4D8B31",
|
||||||
error: "#F02D3A",
|
error: "#F02D3A"
|
||||||
};
|
}
|
||||||
|
|
||||||
export const style = StyleSheet.create({
|
export const style = StyleSheet.create({
|
||||||
app: {
|
app: { // Outermost container
|
||||||
flex: 1,
|
flex: 1,
|
||||||
backgroundColor: colorScheme.background, // For the "entire" app
|
backgroundColor: colorScheme.background, // For the "entire" app
|
||||||
alignItems: "center",
|
alignItems: 'center',
|
||||||
justifyContent: "center",
|
justifyContent: 'center',
|
||||||
margin: 0,
|
margin: 0,
|
||||||
},
|
},
|
||||||
postsContainer: {
|
postsContainer: {
|
||||||
margin: 0,
|
margin: 0,
|
||||||
height: "100%",
|
height: '100%',
|
||||||
width: "100%",
|
width: '100%',
|
||||||
padding: 5,
|
padding: 5,
|
||||||
paddingBottom: 10,
|
paddingVertical: 30,
|
||||||
justifyContent: "flex-start",
|
justifyContent: 'flex-start',
|
||||||
backgroundColor: colorScheme.background, // For the container holding the posts
|
backgroundColor: colorScheme.background, // For the container holding the posts
|
||||||
},
|
},
|
||||||
postView: {
|
postView: {
|
||||||
|
@ -35,38 +35,4 @@ export const style = StyleSheet.create({
|
||||||
postFont: {
|
postFont: {
|
||||||
color: colorScheme.postFont,
|
color: colorScheme.postFont,
|
||||||
},
|
},
|
||||||
header: {
|
|
||||||
backgroundColor: colorScheme.background,
|
|
||||||
},
|
|
||||||
headerTitle: {
|
|
||||||
fontSize: 20,
|
|
||||||
fontWeight: "bold",
|
|
||||||
color: colorScheme.postFont,
|
|
||||||
},
|
|
||||||
newPostContainer: {
|
|
||||||
backgroundColor: colorScheme.background,
|
|
||||||
margin: 0,
|
|
||||||
padding: 0,
|
|
||||||
width: "100%",
|
|
||||||
height: "100%",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "flex-start",
|
|
||||||
},
|
|
||||||
newPostInput: {
|
|
||||||
backgroundColor: colorScheme.postBox,
|
|
||||||
borderRadius: 6,
|
|
||||||
margin : 10,
|
|
||||||
width: "90%",
|
|
||||||
minHeight: "50%",
|
|
||||||
textAlignVertical: "top",
|
|
||||||
padding: 15,
|
|
||||||
color: colorScheme.postFont,
|
|
||||||
},
|
|
||||||
errorText: {
|
|
||||||
color: colorScheme.error,
|
|
||||||
},
|
|
||||||
navButton: {
|
|
||||||
// backgroundColor: colorScheme.background,
|
|
||||||
color: colorScheme.accept
|
|
||||||
},
|
|
||||||
});
|
});
|
Loading…
Reference in a new issue