Skip to content

Commit

Permalink
🥰 publish
Browse files Browse the repository at this point in the history
  • Loading branch information
EvanBacon committed Apr 21, 2020
1 parent 806b779 commit 84ccdd3
Show file tree
Hide file tree
Showing 8 changed files with 151 additions and 94 deletions.
3 changes: 3 additions & 0 deletions .netlify/state.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"siteId": "3098adee-952d-48f9-9d8a-c722c6cd000e"
}
161 changes: 100 additions & 61 deletions App.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,86 @@
import React from "react";
import { StyleSheet, Button, Image, Text, View } from "react-native";
import "emoji-mart/css/emoji-mart.css";

import { Picker } from "emoji-mart";
import { SketchPicker } from "react-color";
import * as ImagePicker from "expo-image-picker";

import JSZip from "jszip";
import FileSaver from "file-saver";
import JSZip from "jszip";
import React from "react";
import { SketchPicker } from "react-color";
import { Button, Image, StyleSheet, View } from "react-native";

import { createAppIcon, twitterEmoji } from "./ImageOps";

const App = () => {
const [color, setColor] = React.useState("#ff00ff");
const [chosenEmoji, setChosenEmoji] = React.useState("1f914");
const defaultEmoji = {
id: "bacon",
name: "Bacon",
short_names: ["bacon"],
colons: ":bacon:",
emoticons: [],
unified: "1f953",
skin: null,
native: "🥓",
};

export default function App() {
const [color, setColor] = React.useState("#4A90E2");
const [chosenEmoji, setChosenEmoji] = React.useState(defaultEmoji);
const [image, setImage] = React.useState(null);

const onSelect = (data) => {
console.log(data);
console.log(JSON.stringify(data));

setChosenEmoji(data.unified);
setChosenEmoji(data);
setImage(null);
};

const emojiId = (chosenEmoji || {}).unified;

async function downloadImageAsync() {
const splash = await createAppIcon({
color,
emojiId: emojiId,
imageUrl: image,
size: 2048,
emojiPadding: 832,
});

const icon = await createAppIcon({
color,
emojiId: emojiId,
imageUrl: image,
size: 1024,
emojiPadding: 128,
});
const faviconPng = await createAppIcon({
color: "transparent",
emojiId: emojiId,
imageUrl: image,
size: 32,
emojiPadding: 0,
});

const iconB64 = icon.substring(icon.indexOf("base64,") + "base64,".length);
const splashB64 = splash.substring(
splash.indexOf("base64,") + "base64,".length
);
const faviconB64 = faviconPng.substring(
faviconPng.indexOf("base64,") + "base64,".length
);

let zip = new JSZip();
// icon 1024x1024 - emoji padding - 128
// splash 2048x2048 - emoji padding - 1000 (524 icon)
zip.file("icon.png", iconB64, { base64: true });
zip.file("splash.png", splashB64, { base64: true });
zip.file("favicon.png", faviconB64, { base64: true });
const content = await zip.generateAsync({ type: "blob" });

const folderName = image
? `app-icons-${image.slice(0, 10)}.zip`
: `app-icons-${chosenEmoji.id}-${color}.zip`;
FileSaver.saveAs(content, folderName);
}

return (
<View style={styles.container}>
<Row style={{ flex: 1 }}>
Expand All @@ -33,58 +92,34 @@ const App = () => {
/>
</Row>
<Row style={{ flex: 1 }}>
<AppIconImage color={color} emojiId={chosenEmoji} image={image} />
{chosenEmoji ? (
<Text>You chose: {chosenEmoji}</Text>
) : (
<Text>No emoji Chosen</Text>
)}
<Button
title="Download"
onPress={async () => {
const icon = await createAppIcon({
color,
emojiId: chosenEmoji,
imageUrl: image,
size: 1024,
emojiPadding: 128,
});
setImage(icon);
return;
FileSaver.saveAs(
icon,
`icon-${new Date().toLocaleTimeString()}.png`
);
return;

let zip = new JSZip();
// icon 1024x1024 - emoji padding - 128
// splash 2048x2048 - emoji padding - 1000 (524 icon)
zip.file("icon.png", icon);
// zip.file("splash.png", `hello`);
// zip.file("favicon.ico", `hello`);
const content = await zip.generateAsync({ type: "blob" });
FileSaver.saveAs(content, `app-icons.zip`);
}}
<AppIconImage
size={128}
color={color}
emojiId={emojiId}
image={image}
/>
<View style={{ padding: 24, flexDirection: "row" }}>
<Button title="Download" onPress={downloadImageAsync} />

<Button
title="Upload Image"
onPress={async () => {
const file = await ImagePicker.launchImageLibraryAsync();
console.log(file);
if (!file.cancelled) {
setImage(file.uri);
setChosenEmoji(null);
}
}}
/>
</View>
</Row>
<Row>
<Picker set="twitter" onSelect={onSelect} />
<Button
title="Upload Image"
onPress={async () => {
const file = await ImagePicker.launchImageLibraryAsync();
console.log(file);
if (!file.cancelled) {
setImage(file.uri);
setChosenEmoji(undefined);
}
}}
/>
</Row>
</View>
);
};
}

function Row({ style, ...props }) {
return (
Expand All @@ -98,8 +133,7 @@ function Row({ style, ...props }) {
);
}

function AppIconImage({ color, image, emojiId = "1f914" }) {
const size = 96;
function AppIconImage({ color, size, image, emojiId = "1f914" }) {
const imgSize = size * 0.75;

let imageContents;
Expand All @@ -123,6 +157,15 @@ function AppIconImage({ color, image, emojiId = "1f914" }) {
return (
<View
style={{
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 1,
},
shadowOpacity: 0.22,
shadowRadius: 2.22,

elevation: 3,
width: size,
height: size,
borderRadius: size * 0.3,
Expand All @@ -137,14 +180,10 @@ function AppIconImage({ color, image, emojiId = "1f914" }) {
);
}

export default App;

const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: "row",
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
},
});
28 changes: 23 additions & 5 deletions ImageOps.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,27 @@ function loadImageAsync(uri) {
});
}

function drawImageScaled(img, ctx) {
var canvas = ctx.canvas;
var hRatio = canvas.width / img.width;
var vRatio = canvas.height / img.height;
var ratio = Math.max(hRatio, vRatio);
var centerShift_x = (canvas.width - img.width * ratio) / 2;
var centerShift_y = (canvas.height - img.height * ratio) / 2;
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(
img,
0,
0,
img.width,
img.height,
centerShift_x,
centerShift_y,
img.width * ratio,
img.height * ratio
);
}

export async function createAppIcon({
color,
imageUrl,
Expand All @@ -29,11 +50,8 @@ export async function createAppIcon({
ctx.fillRect(0, 0, canvas.width, canvas.height);

if (imageUrl) {
const imageSource = await loadImageAsync(uri);
// ctx.drawImage(imageSource, 0, 0, imageSource.naturalWidth, imageSource.naturalHeight);

// draw image
ctx.drawImage(imageSource, 0, 0, size, size);
const imageSource = await loadImageAsync(imageUrl);
drawImageScaled(imageSource, ctx);
} else if (emojiId) {
const emojiUrl = twitterEmoji(emojiId);
// const emojiPadding = size * 0.125;
Expand Down
25 changes: 25 additions & 0 deletions app.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
export default {
name: "Expo Icon Builder",
slug: "icon-builder",
platforms: ["ios", "android", "web"],
version: "1.0.0",
primaryColor: "#50E3C2",
orientation: "portrait",
icon: "./assets/icon.png",
splash: {
image: "./assets/splash.png",
resizeMode: "cover",
backgroundColor: "#50E3C2",
},
updates: {
fallbackToCacheTimeout: 0,
},
assetBundlePatterns: ["**/*"],
web: {
shortName: "Icon Builder",
favicon: "./assets/favicon.png",
},
ios: {
supportsTablet: true,
},
};
28 changes: 0 additions & 28 deletions app.json

This file was deleted.

Binary file added 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 modified assets/icon.png
100644 → 100755
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/splash.png
100644 → 100755
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 84ccdd3

Please sign in to comment.