Introduce icons.js
The default export here replaces Expo's <Iconicons/>, <Fontawesome/>, etc. components with <Icon/> in a first step away from the Expo ecosystem. Using PNG images greatly limits our access to unique colours, but since there only should realistically be using two colours, #000 and #666, in the interface, hopefully this won't be a problem. At least not until there's a dark theme. Rendering more PNGs from the SVGs is tedious.
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.8 KiB |
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="ionicon" viewBox="0 0 512 512"><title>Camera</title><path d="M350.54 148.68l-26.62-42.06C318.31 100.08 310.62 96 302 96h-92c-8.62 0-16.31 4.08-21.92 10.62l-26.62 42.06C155.85 155.23 148.62 160 140 160H80a32 32 0 00-32 32v192a32 32 0 0032 32h352a32 32 0 0032-32V192a32 32 0 00-32-32h-59c-8.65 0-16.85-4.77-22.46-11.32z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/><circle cx="256" cy="272" r="80" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32" d="M124 158v-22h-24v22"/></svg>
|
After Width: | Height: | Size: 711 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.6 KiB |
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="ionicon" viewBox="0 0 512 512"><title>Home</title><path d="M80 212v236a16 16 0 0016 16h96V328a24 24 0 0124-24h80a24 24 0 0124 24v136h96a16 16 0 0016-16V212" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/><path d="M480 256L266.89 52c-5-5.28-16.69-5.34-21.78 0L32 256M400 179V64h-48v69" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/></svg>
|
After Width: | Height: | Size: 491 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.4 KiB |
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="ionicon" viewBox="0 0 512 512"><title>Mail</title><rect x="48" y="96" width="416" height="320" rx="40" ry="40" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32" d="M112 160l144 112 144-112"/></svg>
|
After Width: | Height: | Size: 399 B |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 2.1 KiB |
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="ionicon" viewBox="0 0 512 512"><title>Person</title><path d="M344 144c-3.92 52.87-44 96-88 96s-84.15-43.12-88-96c-4-55 35-96 88-96s92 42 88 96z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/><path d="M256 304c-87 0-175.3 48-191.64 138.6C62.39 453.52 68.57 464 80 464h352c11.44 0 17.62-10.48 15.65-21.4C431.3 352 343 304 256 304z" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/></svg>
|
After Width: | Height: | Size: 513 B |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 16 KiB |
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="ionicon" viewBox="0 0 512 512"><title>Search</title><path d="M221.09 64a157.09 157.09 0 10157.09 157.09A157.1 157.1 0 00221.09 64z" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="32" d="M338.29 338.29L448 448"/></svg>
|
After Width: | Height: | Size: 393 B |
|
@ -21,9 +21,9 @@
|
||||||
"expo-status-bar": "~1.3.0",
|
"expo-status-bar": "~1.3.0",
|
||||||
"expo-web-browser": "~10.2.0",
|
"expo-web-browser": "~10.2.0",
|
||||||
"mime": "^2.5.2",
|
"mime": "^2.5.2",
|
||||||
"react": "17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-dom": "17.0.2",
|
"react-dom": "17.0.2",
|
||||||
"react-native": "https://github.com/expo/react-native/archive/sdk-45.0.0.tar.gz",
|
"react-native": "0.68.2",
|
||||||
"react-native-gesture-handler": "~2.2.1",
|
"react-native-gesture-handler": "~2.2.1",
|
||||||
"react-native-pager-view": "5.4.15",
|
"react-native-pager-view": "5.4.15",
|
||||||
"react-native-popup-menu": "^0.15.10",
|
"react-native-popup-menu": "^0.15.10",
|
||||||
|
|
16
src/App.js
|
@ -7,11 +7,11 @@ import { createStackNavigator } from "@react-navigation/stack";
|
||||||
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
|
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
|
||||||
import { NavigationContainer } from "@react-navigation/native";
|
import { NavigationContainer } from "@react-navigation/native";
|
||||||
import { MenuProvider } from "react-native-popup-menu";
|
import { MenuProvider } from "react-native-popup-menu";
|
||||||
import { Ionicons } from "@expo/vector-icons";
|
|
||||||
|
|
||||||
import { registerRootComponent } from 'expo';
|
import { registerRootComponent } from 'expo';
|
||||||
import * as Linking from "expo-linking";
|
import * as Linking from "expo-linking";
|
||||||
|
|
||||||
|
import Icon from "src/components/icons.js";
|
||||||
import ViewPost from "src/components/pages/view-post";
|
import ViewPost from "src/components/pages/view-post";
|
||||||
import ViewComments from "src/components/pages/view-comments.js";
|
import ViewComments from "src/components/pages/view-comments.js";
|
||||||
|
|
||||||
|
@ -40,10 +40,10 @@ const MainNavigator = () => {
|
||||||
|
|
||||||
const bottomTabIcon = name => {
|
const bottomTabIcon = name => {
|
||||||
return ({ size, focused }) =>
|
return ({ size, focused }) =>
|
||||||
<Ionicons
|
<Icon
|
||||||
name = { name }
|
name = { name }
|
||||||
size = { size }
|
size = { size }
|
||||||
color = { focused ? "black" : "#666" }/>
|
focused = { focused }/>
|
||||||
};
|
};
|
||||||
|
|
||||||
const screenOptions = {
|
const screenOptions = {
|
||||||
|
@ -57,23 +57,23 @@ const MainNavigator = () => {
|
||||||
},
|
},
|
||||||
Feed: {
|
Feed: {
|
||||||
tabBarAccessibilityLabel: "Feed",
|
tabBarAccessibilityLabel: "Feed",
|
||||||
tabBarIcon: bottomTabIcon("home-outline"),
|
tabBarIcon: bottomTabIcon("feed"),
|
||||||
},
|
},
|
||||||
Discover: {
|
Discover: {
|
||||||
tabBarAccessibilityLabel: "Discover",
|
tabBarAccessibilityLabel: "Discover",
|
||||||
tabBarIcon: bottomTabIcon("search-outline"),
|
tabBarIcon: bottomTabIcon("search"),
|
||||||
},
|
},
|
||||||
Publish: {
|
Publish: {
|
||||||
tabBarAccessibilityLabel: "Publish",
|
tabBarAccessibilityLabel: "Publish",
|
||||||
tabBarIcon: bottomTabIcon("camera-outline"),
|
tabBarIcon: bottomTabIcon("camera"),
|
||||||
},
|
},
|
||||||
Direct: {
|
Direct: {
|
||||||
tabBarAccessibilityLabel: "Direct messages",
|
tabBarAccessibilityLabel: "Direct messages",
|
||||||
tabBarIcon: bottomTabIcon("mail-outline"),
|
tabBarIcon: bottomTabIcon("mail"),
|
||||||
},
|
},
|
||||||
Profile: {
|
Profile: {
|
||||||
tabBarAccessibilityLabel: "Profile",
|
tabBarAccessibilityLabel: "Profile",
|
||||||
tabBarIcon: bottomTabIcon("person-outline"),
|
tabBarIcon: bottomTabIcon("person"),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
import React from "react";
|
||||||
|
import { Image, StyleSheet } from "react-native";
|
||||||
|
|
||||||
|
/* React doesn't allow you to `require` images dynamically because they need
|
||||||
|
* to be known ahead of time. As such, we require all the icons we'll need in
|
||||||
|
* this map. If a new icon is added, then it must be added to this array
|
||||||
|
*/
|
||||||
|
const images = {
|
||||||
|
feed: {
|
||||||
|
black: require("assets/icons/feed-black-64px.png"),
|
||||||
|
grey: require("assets/icons/feed-grey-64px.png"),
|
||||||
|
},
|
||||||
|
search: {
|
||||||
|
black: require("assets/icons/search-black-64px.png"),
|
||||||
|
grey: require("assets/icons/search-grey-64px.png"),
|
||||||
|
},
|
||||||
|
camera: {
|
||||||
|
black: require("assets/icons/camera-black-64px.png"),
|
||||||
|
grey: require("assets/icons/camera-grey-64px.png"),
|
||||||
|
},
|
||||||
|
mail: {
|
||||||
|
black: require("assets/icons/mail-black-64px.png"),
|
||||||
|
grey: require("assets/icons/mail-grey-64px.png"),
|
||||||
|
},
|
||||||
|
person: {
|
||||||
|
black: require("assets/icons/person-black-64px.png"),
|
||||||
|
grey: require("assets/icons/person-grey-64px.png"),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const Icon = ({name, size, focused = true}) => {
|
||||||
|
if (images[name] === undefined) {
|
||||||
|
console.error(`Icon "${name}" is not recognized`);
|
||||||
|
return <></>
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
image: {
|
||||||
|
width: size,
|
||||||
|
height: size,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return <Image
|
||||||
|
style = { styles.image }
|
||||||
|
source = {images[name][focused ? "black" : "grey"]}/>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Icon;
|