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.
This commit is contained in:
Nat 2023-01-01 16:52:07 -08:00
parent db54b13fd2
commit c15d42f081
Signed by: nat
GPG Key ID: B53AB05285D710D6
19 changed files with 2899 additions and 2746 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

1
assets/icons/camera.svg Normal file
View File

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

1
assets/icons/feed.svg Normal file
View File

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

1
assets/icons/mail.svg Normal file
View File

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

1
assets/icons/person.svg Normal file
View File

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

1
assets/icons/search.svg Normal file
View File

@ -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

5571
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -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",

View File

@ -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"),
}, },
}; };

49
src/components/icons.js Normal file
View File

@ -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;