Skip to content

Commit

Permalink
Added support for query params
Browse files Browse the repository at this point in the history
  • Loading branch information
EvanBacon committed Aug 18, 2020
1 parent cf1f43e commit 4e573da
Show file tree
Hide file tree
Showing 4 changed files with 172 additions and 120 deletions.
4 changes: 3 additions & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,9 @@ export default function App({}) {
),
}}
>
{() => <CreateScreen ref={ref} />}
{({ route, navigation }) => (
<CreateScreen ref={ref} route={route} navigation={navigation} />
)}
</Stack.Screen>
</Stack.Navigator>
</NavigationContainer>
Expand Down
7 changes: 1 addition & 6 deletions src/components/ColorPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,6 @@ export const getContrastingColor = (data) => {
return yiq >= 128 ? "#000" : "#fff";
};

export const isvalidColorString = (string, type) => {
const stringWithoutDegree = string.replace("°", "");
return tinycolor(`${type} (${stringWithoutDegree})`)._ok;
};

export const isValidHex = (hex) => {
if (hex === "transparent") {
return true;
Expand Down Expand Up @@ -222,7 +217,7 @@ const defaultColors = [
"#999",
"#ABB8C3",
"black",
"#fff",
"white",
];

export const randomColor = () =>
Expand Down
19 changes: 10 additions & 9 deletions src/components/EmojiPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,18 @@ const defaultEmojis = [
id: "fire",
unified: "1f525",
},
{
id: "compass",
unified: "1f9ed",
},
{
id: "rolled_up_newspaper",
unified: "1f5de-fe0f",
},
];

export const randomEmoji = () =>
defaultEmojis[Math.floor(Math.random() * defaultEmojis.length)];
export const randomEmoji = (): EmojiData =>
defaultEmojis[Math.floor(Math.random() * defaultEmojis.length)] as any;

const mapping: Record<string, string> = {
copyright: "a9",
Expand Down Expand Up @@ -125,10 +133,3 @@ export function EmojiPicker({
/>
);
}

const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
},
});
262 changes: 158 additions & 104 deletions src/screens/CreateScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { P } from "@expo/html-elements";
import { FontAwesome } from "@expo/vector-icons";
import { useTheme } from "@react-navigation/native";
import { StackNavigationProp } from "@react-navigation/stack";
import { EmojiData, emojiIndex } from "emoji-mart";
import * as ImagePicker from "expo-image-picker";
import React from "react";
import { StyleSheet, View } from "react-native";
import { Button } from "react-native-paper";
import tinycolor from "tinycolor2";

import { AppIconImage } from "../components/AppIconImage";
import { ColorPicker, randomColor } from "../components/ColorPicker";
Expand All @@ -19,121 +22,172 @@ import { generateImagesAsync } from "../utils/ImageOps";
const defaultEmoji = randomEmoji();
const defaultColor = "#fff";

export default React.forwardRef((props, ref) => {
const theme = useTheme();
const [color, setColor] = React.useState(defaultColor);
const [chosenEmoji = {}, setEmoji] = React.useState(defaultEmoji);
const [image, setImage] = React.useState(null);
const chosenUnified = chosenEmoji?.unified ?? null;
const chosenId = chosenEmoji?.id ?? null;
let emojiId = transformId(chosenUnified, chosenId);
function searchForEmoji(emojiId?: string): EmojiData | null {
if (!emojiId) return null;
const results = emojiIndex.search(emojiId);
if (!results) return null;

const { width } = useWindowDimensions();
return results[0];
}

function normalizeColorForURL(color: string): string {
if (color.startsWith("#")) {
return tinycolor(color).toHex();
}
// allow for CSS named colors
return color;
}

const isMobile = width < 640;
export default React.forwardRef(
(
{
navigation,
route,
}: StackNavigationProp<
{ Home: { emoji?: string; image?: string; color?: string } },
"Home"
>,
ref
) => {
const theme = useTheme();
const [color, setColor] = React.useState(
route.params?.color
? "#" + tinycolor(route.params.color).toHex()
: defaultColor
);
const [chosenEmoji = {}, setEmoji] = React.useState<EmojiData | null>(
searchForEmoji(route.params?.emoji) ?? defaultEmoji
);
const [image, setImage] = React.useState<string | null>(
route.params?.image ? decodeURIComponent(route.params?.image) : null
);
const chosenUnified = chosenEmoji?.unified ?? null;
const chosenId = chosenEmoji?.id ?? null;
let emojiId = transformId(chosenUnified, chosenId);

async function uploadImageAsync() {
const file = await ImagePicker.launchImageLibraryAsync();
if (!file.cancelled) {
setImage(file.uri);
setEmoji(null);
const { width } = useWindowDimensions();

const isMobile = width < 640;

async function uploadImageAsync() {
const file = await ImagePicker.launchImageLibraryAsync();
if (!file.cancelled) {
setImage(file.uri);
setEmoji(null);
navigation.setParams({
// images are often too big
// image: encodeURIComponent(file.uri),
emoji: undefined,
});
}
}
}

React.useImperativeHandle(
ref,
() => ({
async saveAsync() {
await generateImagesAsync({ emojiId, image, color });
},
async uploadAsync() {
await uploadImageAsync();
},
}),
[emojiId, image, color]
);
React.useImperativeHandle(
ref,
() => ({
async saveAsync() {
await generateImagesAsync({ emojiId, image, color });
},
async uploadAsync() {
await uploadImageAsync();
},
}),
[emojiId, image, color]
);

const onSelect = (data) => {
console.log("Emoji: ", data);
// navigation.setParams({ emoji: data.unified });

setEmoji(data);
setImage(null);
};

const renderAppIcon = () => (
<>
<AppIconImage
size={128}
onPress={uploadImageAsync}
color={color}
emojiId={emojiId}
image={image}
/>
<View style={{ marginTop: 8, opacity: 0.8 }}>
<FontAwesome.Button
name="refresh"
backgroundColor="transparent"
underlayColor={theme.colors.header}
color={theme.colors.text}
onPress={() => {
setColor(randomColor());
setEmoji(randomEmoji());
}}
>
Random
</FontAwesome.Button>
</View>
{false && (
<P
style={{
opacity: 0.6,
color: theme.colors.text,
textAlign: "center",
}}
>
Touch the icon to use a custom image.
</P>
)}
</>
);
function setColorAndUpdateURL(color: string) {
console.log("Selected Color", color);

const renderDownloadButton = () => (
<DownloadButton
color={theme.colors.text}
style={{ marginTop: 12 }}
onPress={() => {
generateImagesAsync({ emojiId, image, color });
}}
/>
);
setColor(color);
navigation.setParams({ color: normalizeColorForURL(color) });
}
function setEmojiAndUpdateURL(emoji: EmojiData) {
console.log("Selected Emoji", emoji);

return (
<View
style={{
flex: 1,
backgroundColor: theme.colors.background,
paddingVertical: isMobile ? 18 : 0,
flexDirection: isMobile ? "column" : "row",
}}
>
navigation.setParams({ emoji: emoji.id });
setEmoji(emoji);
// reset custom image
setImage(null);
}

const renderAppIcon = () => (
<>
<AppIconImage
size={128}
onPress={uploadImageAsync}
color={color}
emojiId={emojiId}
image={image}
/>
<View style={{ marginTop: 8, opacity: 0.8 }}>
<FontAwesome.Button
name="refresh"
backgroundColor="transparent"
underlayColor={theme.colors.header}
color={theme.colors.text}
onPress={() => {
setColorAndUpdateURL(randomColor());
setEmojiAndUpdateURL(randomEmoji());
}}
>
Random
</FontAwesome.Button>
</View>
{false && (
<P
style={{
opacity: 0.6,
color: theme.colors.text,
textAlign: "center",
}}
>
Touch the icon to use a custom image.
</P>
)}
</>
);

const renderDownloadButton = () => (
<DownloadButton
color={theme.colors.text}
style={{ marginTop: 12 }}
onPress={() => {
generateImagesAsync({ emojiId, image, color });
}}
/>
);

return (
<View
style={[
styles.rowItem,
{
paddingVertical: isMobile ? 18 : 0,
},
]}
style={{
flex: 1,
backgroundColor: theme.colors.background,
paddingVertical: isMobile ? 18 : 0,
flexDirection: isMobile ? "column" : "row",
}}
>
{renderAppIcon()}
<ColorPicker onValueChanged={(hex) => setColor(hex)} />
</View>
<View style={styles.rowItem}>
<EmojiPicker isMobile={isMobile} onSelect={onSelect} />
<View
style={[
styles.rowItem,
{
paddingVertical: isMobile ? 18 : 0,
},
]}
>
{renderAppIcon()}
<ColorPicker
onValueChanged={(hex) => {
setColorAndUpdateURL(hex);
}}
/>
</View>
<View style={styles.rowItem}>
<EmojiPicker isMobile={isMobile} onSelect={setEmojiAndUpdateURL} />
</View>
</View>
</View>
);
});
);
}
);

function DownloadButton(props: React.ComponentProps<typeof Button>) {
return (
Expand Down

0 comments on commit 4e573da

Please sign in to comment.