diff --git a/assets/icons/alien_stroke2_corner0_rounded.svg b/assets/icons/alien_stroke2_corner0_rounded.svg
new file mode 100644
index 0000000000..595308c97b
--- /dev/null
+++ b/assets/icons/alien_stroke2_corner0_rounded.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/icons/bubbles_stroke2_corner0_rounded.svg b/assets/icons/bubbles_stroke2_corner0_rounded.svg
new file mode 100644
index 0000000000..8706007afc
--- /dev/null
+++ b/assets/icons/bubbles_stroke2_corner0_rounded.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/icons/celebrate_stroke2_corner0_rounded.svg b/assets/icons/celebrate_stroke2_corner0_rounded.svg
new file mode 100644
index 0000000000..3ea7bc8d2a
--- /dev/null
+++ b/assets/icons/celebrate_stroke2_corner0_rounded.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/icons/emojiArc_stroke2_corner0_rounded.svg b/assets/icons/emojiArc_stroke2_corner0_rounded.svg
new file mode 100644
index 0000000000..3d09228e71
--- /dev/null
+++ b/assets/icons/emojiArc_stroke2_corner0_rounded.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/icons/emojiHeartEyes_stroke2_corner0_rounded.svg b/assets/icons/emojiHeartEyes_stroke2_corner0_rounded.svg
new file mode 100644
index 0000000000..4aecb86c54
--- /dev/null
+++ b/assets/icons/emojiHeartEyes_stroke2_corner0_rounded.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/icons/explosion_stroke2_corner0_rounded.svg b/assets/icons/explosion_stroke2_corner0_rounded.svg
new file mode 100644
index 0000000000..11544bf79c
--- /dev/null
+++ b/assets/icons/explosion_stroke2_corner0_rounded.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/icons/lab_stroke2_corner0_rounded.svg b/assets/icons/lab_stroke2_corner0_rounded.svg
new file mode 100644
index 0000000000..466809194e
--- /dev/null
+++ b/assets/icons/lab_stroke2_corner0_rounded.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/icons/piggyBank_stroke2_corner0_rounded.svg b/assets/icons/piggyBank_stroke2_corner0_rounded.svg
new file mode 100644
index 0000000000..36d3060102
--- /dev/null
+++ b/assets/icons/piggyBank_stroke2_corner0_rounded.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/icons/poop_stroke2_corner0_rounded.svg b/assets/icons/poop_stroke2_corner0_rounded.svg
new file mode 100644
index 0000000000..daa6c11126
--- /dev/null
+++ b/assets/icons/poop_stroke2_corner0_rounded.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/package.json b/package.json
index 837a8d0e45..d5b68abea2 100644
--- a/package.json
+++ b/package.json
@@ -8,14 +8,14 @@
"scripts": {
"prepare": "is-ci || husky install",
"postinstall": "patch-package && yarn intl:compile",
- "prebuild": "expo prebuild --clean",
- "android": "expo run:android",
- "ios": "expo run:ios",
- "web": "expo start --web",
- "build-web": "expo export:web && node ./scripts/post-web-build.js && cp -v ./web-build/static/js/*.* ./bskyweb/static/js/",
+ "prebuild": "npx expo prebuild --clean",
+ "android": "npx expo run:android",
+ "ios": "npx expo run:ios",
+ "web": "npx expo start --web",
+ "build-web": "npx expo export:web && node ./scripts/post-web-build.js && cp -v ./web-build/static/js/*.* ./bskyweb/static/js/",
"build-all": "yarn intl:build && eas build --platform all",
- "start": "expo start --dev-client",
- "start:prod": "expo start --dev-client --no-dev --minify",
+ "start": "npx expo start --dev-client",
+ "start:prod": "npx expo start --dev-client --no-dev --minify",
"clean-cache": "rm -rf node_modules/.cache/babel-loader/*",
"test": "NODE_ENV=test jest --forceExit --testTimeout=20000 --bail",
"test-watch": "NODE_ENV=test jest --watchAll",
@@ -24,7 +24,7 @@
"lint": "eslint ./src --ext .js,.jsx,.ts,.tsx",
"typecheck": "tsc --project ./tsconfig.check.json",
"e2e:mock-server": "./jest/dev-infra/with-test-redis-and-db.sh ts-node --project tsconfig.e2e.json __e2e__/mock-server.ts",
- "e2e:metro": "NODE_ENV=test RN_SRC_EXT=e2e.ts,e2e.tsx expo run:ios",
+ "e2e:metro": "NODE_ENV=test RN_SRC_EXT=e2e.ts,e2e.tsx npx expo run:ios",
"e2e:build": "NODE_ENV=test detox build -c ios.sim.debug",
"e2e:run": "NODE_ENV=test detox test --configuration ios.sim.debug --take-screenshots all",
"perf:test": "NODE_ENV=test maestro test",
@@ -164,9 +164,11 @@
"react-native-safe-area-context": "4.8.2",
"react-native-screens": "~3.29.0",
"react-native-svg": "14.1.0",
+ "react-native-ui-text-view": "link:./modules/react-native-ui-text-view",
"react-native-url-polyfill": "^1.3.0",
"react-native-uuid": "^2.0.1",
"react-native-version-number": "^0.3.6",
+ "react-native-view-shot": "^3.8.0",
"react-native-web": "~0.19.6",
"react-native-web-linear-gradient": "^1.1.2",
"react-native-web-webview": "^1.0.2",
@@ -178,8 +180,7 @@
"tlds": "^1.234.0",
"use-deep-compare": "^1.1.0",
"zeego": "^1.6.2",
- "zod": "^3.20.2",
- "react-native-ui-text-view": "link:./modules/react-native-ui-text-view"
+ "zod": "^3.20.2"
},
"devDependencies": {
"@atproto/dev-env": "^0.2.28",
diff --git a/src/components/icons/Alien.tsx b/src/components/icons/Alien.tsx
new file mode 100644
index 0000000000..ef1aa0f912
--- /dev/null
+++ b/src/components/icons/Alien.tsx
@@ -0,0 +1,5 @@
+import {createSinglePathSVG} from './TEMPLATE'
+
+export const PlusLarge_Stroke2_Corner0_Rounded = createSinglePathSVG({
+ path: 'M5 11a7 7 0 0 1 14 0c0 2.625-1.547 5.138-3.354 7.066a17.23 17.23 0 0 1-2.55 2.242 8.246 8.246 0 0 1-.924.577 2.904 2.904 0 0 1-.172.083 2.904 2.904 0 0 1-.172-.083 8.246 8.246 0 0 1-.923-.577 17.227 17.227 0 0 1-2.55-2.242C6.547 16.138 5 13.625 5 11Zm6.882 10.012Zm.232-.001h-.003a.047.047 0 0 0 .007.001l-.004-.001ZM12 2a9 9 0 0 0-9 9c0 3.375 1.953 6.362 3.895 8.434a19.216 19.216 0 0 0 2.856 2.508c.425.3.82.545 1.159.72.168.087.337.164.498.222.14.05.356.116.592.116s.451-.066.592-.116c.16-.058.33-.135.498-.222.339-.175.734-.42 1.159-.72.85-.6 1.87-1.457 2.856-2.508C19.047 17.362 21 14.375 21 11a9 9 0 0 0-9-9ZM7.38 9.927c2.774-.094 3.459 1.31 3.591 3.19a.89.89 0 0 1-.855.956c-2.774.094-3.458-1.31-3.59-3.19a.89.89 0 0 1 .854-.956Zm9.236 0c-2.774-.094-3.458 1.31-3.59 3.19a.89.89 0 0 0 .854.956c2.774.094 3.459-1.31 3.591-3.19a.89.89 0 0 0-.855-.956Z',
+})
diff --git a/src/components/icons/Bubbles.tsx b/src/components/icons/Bubbles.tsx
new file mode 100644
index 0000000000..671f0af8bf
--- /dev/null
+++ b/src/components/icons/Bubbles.tsx
@@ -0,0 +1,5 @@
+import {createSinglePathSVG} from './TEMPLATE'
+
+export const PlusLarge_Stroke2_Corner0_Rounded = createSinglePathSVG({
+ path: 'M8 4a4 4 0 1 0 0 8 4 4 0 0 0 0-8ZM2 8a6 6 0 1 1 12 0A6 6 0 0 1 2 8Zm16.5 0a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3ZM15 9.5a3.5 3.5 0 1 1 7 0 3.5 3.5 0 0 1-7 0Zm-.5 5.5a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5ZM10 17.5a4.5 4.5 0 1 1 9 0 4.5 4.5 0 0 1-9 0Z',
+})
diff --git a/src/components/icons/Celebrate.tsx b/src/components/icons/Celebrate.tsx
new file mode 100644
index 0000000000..357d2ce91d
--- /dev/null
+++ b/src/components/icons/Celebrate.tsx
@@ -0,0 +1,5 @@
+import {createSinglePathSVG} from './TEMPLATE'
+
+export const PlusLarge_Stroke2_Corner0_Rounded = createSinglePathSVG({
+ path: 'M13.832 1.014a1 1 0 0 1 1.154.818L14 2l.986-.168v.003l.001.005.002.014.007.045.021.156c.017.13.035.312.048.527.025.42.028 1.01-.082 1.6-.127.69-.447 1.31-.701 1.726a7.107 7.107 0 0 1-.498.712l-.01.014-.004.005-.002.001v.002L13 6l.767.642a1 1 0 0 1-1.535-1.282l.002-.003.017-.02a5.13 5.13 0 0 0 .324-.47c.198-.325.378-.705.442-1.049.068-.37.071-.78.051-1.12a6.268 6.268 0 0 0-.05-.504l-.004-.025m.818-1.155a1 1 0 0 0-.818 1.155Zm5.257 1.545a1 1 0 0 1 .602 1.28l-.45 1.25a1 1 0 0 1-1.882-.678l.45-1.25a1 1 0 0 1 1.28-.602ZM6.524 7.136a2 2 0 0 1 3.294-.732l7.778 7.778a2 2 0 0 1-.732 3.294L4.653 21.91c-1.596.579-3.142-.967-2.563-2.563L6.524 7.136Zm9.658 8.46L8.404 7.818 3.97 20.03l12.212-4.434Zm5.712-8.543a1 1 0 0 1-.447 1.341l-1 .5a1 1 0 1 1-.894-1.788l1-.5a1 1 0 0 1 1.341.447Zm-4.687-.26a1 1 0 0 1 0 1.414l-1 1a1 1 0 1 1-1.414-1.414l1-1a1 1 0 0 1 1.414 0Zm-.206 4.165A1 1 0 0 1 18.042 10L18 11l.042-1 .003.001h.014l.035.003.117.008a7.693 7.693 0 0 1 1.594.306c.423.135.861.352 1.168.516a11.873 11.873 0 0 1 .508.288l.032.02.01.006.004.002L21 12l.527-.85a1 1 0 0 1-1.054 1.7l-.005-.003-.023-.014a7.477 7.477 0 0 0-.415-.236 5.497 5.497 0 0 0-.835-.374A5.684 5.684 0 0 0 17.973 12l-.015-.002h-.002a1 1 0 0 1-.955-1.041Z',
+})
diff --git a/src/components/icons/EmojiAlt.tsx b/src/components/icons/EmojiAlt.tsx
new file mode 100644
index 0000000000..d0698f7f44
--- /dev/null
+++ b/src/components/icons/EmojiAlt.tsx
@@ -0,0 +1,5 @@
+import {createSinglePathSVG} from './TEMPLATE'
+
+export const PlusLarge_Stroke2_Corner0_Rounded = createSinglePathSVG({
+ path: 'M12 3a1 1 0 0 1 1 1v7h7a1 1 0 1 1 0 2h-7v7a1 1 0 1 1-2 0v-7H4a1 1 0 1 1 0-2h7V4a1 1 0 0 1 1-1Z',
+})
diff --git a/src/components/icons/EmojiArc.tsx b/src/components/icons/EmojiArc.tsx
new file mode 100644
index 0000000000..aaccc285a0
--- /dev/null
+++ b/src/components/icons/EmojiArc.tsx
@@ -0,0 +1,5 @@
+import {createSinglePathSVG} from './TEMPLATE'
+
+export const PlusLarge_Stroke2_Corner0_Rounded = createSinglePathSVG({
+ path: 'M12 4a8 8 0 1 0 0 16 8 8 0 0 0 0-16ZM2 12C2 6.477 6.477 2 12 2s10 4.477 10 10-4.477 10-10 10S2 17.523 2 12Zm8-5a1 1 0 0 1 1 1v3a1 1 0 1 1-2 0V8a1 1 0 0 1 1-1Zm4 0a1 1 0 0 1 1 1v3a1 1 0 1 1-2 0V8a1 1 0 0 1 1-1Zm-5.894 7.803a1 1 0 0 1 1.341-.447c1.719.859 3.387.859 5.106 0a1 1 0 1 1 .894 1.788c-2.281 1.141-4.613 1.141-6.894 0a1 1 0 0 1-.447-1.341Z',
+})
diff --git a/src/components/icons/EmojiHeartEyes.tsx b/src/components/icons/EmojiHeartEyes.tsx
new file mode 100644
index 0000000000..22cfdc1760
--- /dev/null
+++ b/src/components/icons/EmojiHeartEyes.tsx
@@ -0,0 +1,5 @@
+import {createSinglePathSVG} from './TEMPLATE'
+
+export const PlusLarge_Stroke2_Corner0_Rounded = createSinglePathSVG({
+ path: 'M4 12a8 8 0 1 1 16 0 8 8 0 0 1-16 0Zm8-10C6.477 2 2 6.477 2 12s4.477 10 10 10 10-4.477 10-10S17.523 2 12 2ZM9.351 12.13c1.898-1.507 2.176-2.95 1.613-3.83a1.524 1.524 0 0 0-1.225-.707 1.562 1.562 0 0 0-1.218.53 1.561 1.561 0 0 0-1.326-.082c-.456.186-.8.588-.91 1.083-.227 1.02.527 2.282 2.826 3.048a.256.256 0 0 0 .24-.043Zm5.538.042c2.299-.766 3.053-2.027 2.826-3.048a1.524 1.524 0 0 0-.91-1.082 1.561 1.561 0 0 0-1.326.081 1.562 1.562 0 0 0-1.217-.53 1.524 1.524 0 0 0-1.226.706c-.563.881-.285 2.325 1.613 3.83.068.054.158.07.24.043Zm1.072 2.38a4 4 0 0 1-7.924 0c-.04-.293.218-.525.514-.499 2.309.206 4.587.206 6.896 0 .296-.026.555.206.514.5Z',
+})
diff --git a/src/components/icons/EmojiSad.tsx b/src/components/icons/EmojiSad.tsx
new file mode 100644
index 0000000000..d0698f7f44
--- /dev/null
+++ b/src/components/icons/EmojiSad.tsx
@@ -0,0 +1,5 @@
+import {createSinglePathSVG} from './TEMPLATE'
+
+export const PlusLarge_Stroke2_Corner0_Rounded = createSinglePathSVG({
+ path: 'M12 3a1 1 0 0 1 1 1v7h7a1 1 0 1 1 0 2h-7v7a1 1 0 1 1-2 0v-7H4a1 1 0 1 1 0-2h7V4a1 1 0 0 1 1-1Z',
+})
diff --git a/src/components/icons/EmojiSmile.tsx b/src/components/icons/EmojiSmile.tsx
new file mode 100644
index 0000000000..d0698f7f44
--- /dev/null
+++ b/src/components/icons/EmojiSmile.tsx
@@ -0,0 +1,5 @@
+import {createSinglePathSVG} from './TEMPLATE'
+
+export const PlusLarge_Stroke2_Corner0_Rounded = createSinglePathSVG({
+ path: 'M12 3a1 1 0 0 1 1 1v7h7a1 1 0 1 1 0 2h-7v7a1 1 0 1 1-2 0v-7H4a1 1 0 1 1 0-2h7V4a1 1 0 0 1 1-1Z',
+})
diff --git a/src/components/icons/Explosion.tsx b/src/components/icons/Explosion.tsx
new file mode 100644
index 0000000000..4e51663336
--- /dev/null
+++ b/src/components/icons/Explosion.tsx
@@ -0,0 +1,5 @@
+import {createSinglePathSVG} from './TEMPLATE'
+
+export const PlusLarge_Stroke2_Corner0_Rounded = createSinglePathSVG({
+ path: 'M12 2a1 1 0 0 1 .889.542l1.679 3.259 3.491-1.117a1 1 0 0 1 1.257 1.257L18.2 9.432l3.259 1.679a1 1 0 0 1 0 1.778l-3.124 1.61 2.609 5.098a1 1 0 0 1-1.346 1.346l-5.098-2.61-1.61 3.125a1 1 0 0 1-1.778 0l-1.679-3.259-3.491 1.117a1 1 0 0 1-1.257-1.257L5.8 14.568l-3.259-1.679a1 1 0 0 1 0-1.778l3.124-1.61-2.609-5.098a1 1 0 0 1 1.346-1.346l5.098 2.61-.455.89.455-.89 1.61-3.125A1 1 0 0 1 12 2Zm0 3.183-.72 1.4a2 2 0 0 1-2.69.864L6.248 6.248 7.447 8.59a2 2 0 0 1-.865 2.69L5.183 12l1.534.79a2 2 0 0 1 .989 2.387L7.18 16.82l1.643-.526a2 2 0 0 1 2.387.99l.79 1.533.72-1.4a2 2 0 0 1 2.69-.864l2.342 1.199-1.199-2.342a2 2 0 0 1 .864-2.69l1.4-.72-1.534-.79a2 2 0 0 1-.989-2.387l.526-1.643-1.643.526a2 2 0 0 1-2.387-.99L12 5.184Z',
+})
diff --git a/src/components/icons/Lab.tsx b/src/components/icons/Lab.tsx
new file mode 100644
index 0000000000..638cc2fcd1
--- /dev/null
+++ b/src/components/icons/Lab.tsx
@@ -0,0 +1,5 @@
+import {createSinglePathSVG} from './TEMPLATE'
+
+export const PlusLarge_Stroke2_Corner0_Rounded = createSinglePathSVG({
+ path: 'M13.5 4a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3ZM10 5a1 1 0 1 0 0-2 1 1 0 0 0 0 2ZM8 6a1 1 0 0 0 0 2v2.64c-.212.25-.45.515-.711.8l-.129.142c-.312.342-.649.711-.974 1.092-.731.857-1.488 1.866-1.89 2.99A4.845 4.845 0 0 0 4 17.297 4.702 4.702 0 0 0 8.702 22h6.596A4.702 4.702 0 0 0 20 17.298c0-.575-.114-1.122-.297-1.634-.401-1.124-1.157-2.133-1.89-2.99-.324-.38-.66-.75-.973-1.092l-.129-.141c-.26-.286-.5-.55-.711-.8V8a1 1 0 1 0 0-2H8Zm2 5.35V8h4v3.35l.22.275c.306.383.661.777 1.013 1.163l.13.143c.315.345.628.688.93 1.042.372.435.704.861.974 1.28l-.159.025c-.845.13-1.838.242-2.581.222-.842-.022-1.475-.217-2.227-.454l-.027-.008c-.746-.235-1.61-.507-2.746-.538-.743-.02-1.617.064-2.38.165.173-.228.36-.459.56-.692.302-.354.615-.697.93-1.042l.13-.143c.352-.386.707-.78 1.014-1.163L10 11.35Zm7.41 5.905c.21-.032.407-.064.586-.095A2.702 2.702 0 0 1 15.298 20H8.702A2.702 2.702 0 0 1 6 17.298c0-.142.013-.286.039-.434.236-.043.53-.093.853-.142.845-.13 1.837-.242 2.581-.222.842.022 1.475.217 2.227.454l.027.008c.746.235 1.61.507 2.746.538.931.024 2.07-.113 2.937-.245Z',
+})
diff --git a/src/components/icons/PiggyBank.tsx b/src/components/icons/PiggyBank.tsx
new file mode 100644
index 0000000000..4a2ab24edf
--- /dev/null
+++ b/src/components/icons/PiggyBank.tsx
@@ -0,0 +1,5 @@
+import {createSinglePathSVG} from './TEMPLATE'
+
+export const PlusLarge_Stroke2_Corner0_Rounded = createSinglePathSVG({
+ path: 'M6.5 4.999Zm0 0a.054.054 0 0 1-.016.024.196.196 0 0 1-.152.043c.057.01.113.02.168.032V7.5a1 1 0 0 1-.33.742c-.543.49-.917 1.176-1.23 2.036a1 1 0 0 1-.94.657H3V14h1a1 1 0 0 1 .866.5c.436.754.879 1.195 1.637 1.636A1 1 0 0 1 7 17v2h2a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2h2v-2.537a1 1 0 0 1 .332-.744A4.978 4.978 0 0 0 19 11.999 5 5 0 0 0 14 7H9.474a1 1 0 0 1-.893-.55v-.001l-.001-.002-.005-.008L9.474 6l-.9.438h.001v.002l.002.001.001.003.002.003v.003a2.62 2.62 0 0 0-.443-.538c-.319-.298-.839-.648-1.637-.814V5Zm2.082 1.452ZM9.5 4.447c.211.196.379.387.508.553H14a7 7 0 0 1 6.72 8.96 1.003 1.003 0 0 0 1.146-1.46 1 1 0 1 1 1.731-1 3 3 0 0 1-3.714 4.286A7.074 7.074 0 0 1 19 16.888V19a2 2 0 0 1-2 2h-2a2 2 0 0 1-2-2h-2a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2v-1.45A5.783 5.783 0 0 1 3.448 16H3a2 2 0 0 1-2-2v-3.065a2 2 0 0 1 2-2h.324c.286-.649.657-1.291 1.176-1.852V5c0-1.047.89-2.12 2.161-1.907 1.33.223 2.248.805 2.839 1.354ZM8.25 12a1.25 1.25 0 1 0 0-2.5 1.25 1.25 0 0 0 0 2.5Z',
+})
diff --git a/src/components/icons/Poop.tsx b/src/components/icons/Poop.tsx
new file mode 100644
index 0000000000..5c37bd1d65
--- /dev/null
+++ b/src/components/icons/Poop.tsx
@@ -0,0 +1,5 @@
+import {createSinglePathSVG} from './TEMPLATE'
+
+export const PlusLarge_Stroke2_Corner0_Rounded = createSinglePathSVG({
+ path: 'M12 4c0-1.012.894-2.187 2.237-1.846a5.002 5.002 0 0 1 3.218 7.119 4.001 4.001 0 0 1 2.345 4.976A3.501 3.501 0 0 1 18.5 21h-13a3.5 3.5 0 0 1-1.3-6.75 4 4 0 0 1 2.052-4.848A4 4 0 0 1 10 4h2.001Zm-4.187 7.009A2 2 0 0 0 6 13c0 .366.098.706.271 1H12a1 1 0 1 1 0 2H5.5a1.5 1.5 0 0 0 0 3h13a1.5 1.5 0 1 0 0-3H17a1 1 0 1 1 0-2h.729c.173-.294.271-.634.271-1a2 2 0 0 0-2-2h-2a1 1 0 1 1 0-2h1.236a3.002 3.002 0 0 0-1.243-4.832A2 2 0 0 1 12 6h-2a2 2 0 0 0-1.728 3.009H9a1 1 0 0 1 0 2H7.813Z',
+})
diff --git a/src/lib/media/avatar-generator.tsx b/src/lib/media/avatar-generator.tsx
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/src/screens/Onboarding/StepProfile/SelectImageButton.tsx b/src/screens/Onboarding/StepProfile/SelectImageButton.tsx
new file mode 100644
index 0000000000..cb4d3d7ef3
--- /dev/null
+++ b/src/screens/Onboarding/StepProfile/SelectImageButton.tsx
@@ -0,0 +1,76 @@
+import React from 'react'
+import {Pressable, StyleSheet} from 'react-native'
+import {Camera_Stroke2_Corner0_Rounded as Camera} from '#/components/icons/Camera'
+import {useSetAvatar} from '#/screens/Onboarding/StepProfile/index'
+import {useTheme} from '#/alf'
+import {usePhotoLibraryPermission} from 'lib/hooks/usePermissions'
+import {openPicker} from 'lib/media/picker.shared'
+import {openCropper} from 'lib/media/picker'
+
+export function SelectImageButton() {
+ const t = useTheme()
+ const setAvatar = useSetAvatar()
+ const {requestPhotoAccessIfNeeded} = usePhotoLibraryPermission()
+
+ const onCameraPress = React.useCallback(async () => {
+ if (!(await requestPhotoAccessIfNeeded())) {
+ return
+ }
+
+ const items = await openPicker({
+ aspect: [1, 1],
+ })
+ const item = items[0]
+ if (!item) return
+
+ const croppedImage = await openCropper({
+ mediaType: 'photo',
+ cropperCircleOverlay: true,
+ height: item.height,
+ width: item.width,
+ path: item.path,
+ })
+
+ setAvatar(prev => ({
+ ...prev,
+ image: croppedImage,
+ }))
+ }, [requestPhotoAccessIfNeeded, setAvatar])
+
+ return (
+
+
+
+ )
+}
+
+const styles = StyleSheet.create({
+ imageContainer: {
+ borderRadius: 100,
+ borderWidth: 2,
+ height: 150,
+ width: 150,
+ overflow: 'hidden',
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ paletteContainer: {
+ height: 80,
+ width: 80,
+ marginHorizontal: 5,
+ },
+ flatListOuter: {
+ height: 100,
+ },
+ flatListContainer: {
+ paddingLeft: 40,
+ paddingRight: 40,
+ },
+})
diff --git a/src/screens/Onboarding/StepProfile/SelectImageButton.web.tsx b/src/screens/Onboarding/StepProfile/SelectImageButton.web.tsx
new file mode 100644
index 0000000000..a37990af2d
--- /dev/null
+++ b/src/screens/Onboarding/StepProfile/SelectImageButton.web.tsx
@@ -0,0 +1,98 @@
+import React from 'react'
+import {Pressable, StyleSheet, Text} from 'react-native'
+import {Camera_Stroke2_Corner0_Rounded as Camera} from '#/components/icons/Camera'
+import {useAvatar, useSetAvatar} from '#/screens/Onboarding/StepProfile/index'
+import {useTheme} from '#/alf'
+import {usePhotoLibraryPermission} from 'lib/hooks/usePermissions'
+import {openPicker} from 'lib/media/picker.shared'
+import {openCropper} from 'lib/media/picker'
+
+export function SelectImageButton() {
+ const t = useTheme()
+ const setAvatar = useSetAvatar()
+ const {requestPhotoAccessIfNeeded} = usePhotoLibraryPermission()
+
+ const onCameraPress = React.useCallback(async () => {
+ if (!(await requestPhotoAccessIfNeeded())) {
+ return
+ }
+
+ const items = await openPicker({
+ aspect: [1, 1],
+ })
+ const item = items[0]
+ if (!item) return
+
+ const croppedImage = await openCropper({
+ mediaType: 'photo',
+ cropperCircleOverlay: true,
+ height: item.height,
+ width: item.width,
+ path: item.path,
+ })
+
+ setAvatar(prev => ({
+ ...prev,
+ image: croppedImage,
+ }))
+ }, [requestPhotoAccessIfNeeded, setAvatar])
+
+ return (
+ <>
+
+
+
+
+ >
+ )
+}
+
+function Canvas() {
+ const avatar = useAvatar()
+ const canvasRef = React.useRef(null)
+ React.useEffect(() => {}, [])
+
+ return (
+
+ )
+}
+
+const styles = StyleSheet.create({
+ imageContainer: {
+ borderRadius: 100,
+ borderWidth: 2,
+ height: 150,
+ width: 150,
+ overflow: 'hidden',
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ paletteContainer: {
+ height: 80,
+ width: 80,
+ marginHorizontal: 5,
+ },
+ flatListOuter: {
+ height: 100,
+ },
+ flatListContainer: {
+ paddingLeft: 40,
+ paddingRight: 40,
+ },
+})
diff --git a/src/screens/Onboarding/StepProfile/index.tsx b/src/screens/Onboarding/StepProfile/index.tsx
index 4842c09dca..65e1b6ee3f 100644
--- a/src/screens/Onboarding/StepProfile/index.tsx
+++ b/src/screens/Onboarding/StepProfile/index.tsx
@@ -29,6 +29,7 @@ import {IconCircle} from '#/components/IconCircle'
import {Image} from 'expo-image'
import {usePhotoLibraryPermission} from 'lib/hooks/usePermissions'
import {openCropper, openPicker} from 'lib/media/picker'
+import {SelectImageButton} from '#/screens/Onboarding/StepProfile/SelectImageButton'
interface Avatar {
image?: {
@@ -46,8 +47,8 @@ const AvatarContext = React.createContext({} as Avatar)
const SetAvatarContext = React.createContext<
React.Dispatch>
>({} as React.Dispatch>)
-const useAvatar = () => React.useContext(AvatarContext)
-const useSetAvatar = () => React.useContext(SetAvatarContext)
+export const useAvatar = () => React.useContext(AvatarContext)
+export const useSetAvatar = () => React.useContext(SetAvatarContext)
export function StepProfile() {
const {_} = useLingui()
@@ -189,7 +190,6 @@ function EmojiItem({emoji}: {emoji: Emoji}) {
const t = useTheme()
const avatar = useAvatar()
const setAvatar = useSetAvatar()
- const {requestPhotoAccessIfNeeded} = usePhotoLibraryPermission()
const onPress = React.useCallback(() => {
setAvatar(prev => ({
@@ -198,47 +198,8 @@ function EmojiItem({emoji}: {emoji: Emoji}) {
}))
}, [emoji, setAvatar])
- const onCameraPress = React.useCallback(async () => {
- if (!(await requestPhotoAccessIfNeeded())) {
- return
- }
-
- const items = await openPicker({
- aspect: [1, 1],
- })
- const item = items[0]
- if (!item) return
-
- const croppedImage = await openCropper({
- mediaType: 'photo',
- cropperCircleOverlay: true,
- height: item.height,
- width: item.width,
- path: item.path,
- })
-
- setAvatar(prev => ({
- ...prev,
- image: croppedImage,
- }))
- }, [requestPhotoAccessIfNeeded, setAvatar])
-
if (emoji === 'camera') {
- return (
-
-
-
- )
+ return
}
return (
diff --git a/yarn.lock b/yarn.lock
index d26d098729..e5326d17b4 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -8883,6 +8883,11 @@ base-64@0.1.0, base-64@^0.1.0:
resolved "https://registry.yarnpkg.com/base-64/-/base-64-0.1.0.tgz#780a99c84e7d600260361511c4877613bf24f6bb"
integrity sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA==
+base64-arraybuffer@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz#1c37589a7c4b0746e34bd1feb951da2df01c1bdc"
+ integrity sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==
+
base64-js@^1.0.2, base64-js@^1.2.3, base64-js@^1.3.1, base64-js@^1.5.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
@@ -10018,6 +10023,13 @@ css-in-js-utils@^3.1.0:
dependencies:
hyphenate-style-name "^1.0.3"
+css-line-break@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/css-line-break/-/css-line-break-2.1.0.tgz#bfef660dfa6f5397ea54116bb3cb4873edbc4fa0"
+ integrity sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==
+ dependencies:
+ utrie "^1.0.2"
+
css-loader@^6.5.1:
version "6.8.1"
resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.8.1.tgz#0f8f52699f60f5e679eab4ec0fcd68b8e8a50a88"
@@ -12931,6 +12943,14 @@ html-webpack-plugin@^5.5.0:
pretty-error "^4.0.0"
tapable "^2.0.0"
+html2canvas@^1.4.1:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/html2canvas/-/html2canvas-1.4.1.tgz#7cef1888311b5011d507794a066041b14669a543"
+ integrity sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==
+ dependencies:
+ css-line-break "^2.1.0"
+ text-segmentation "^1.0.3"
+
htmlparser2@^6.1.0:
version "6.1.0"
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7"
@@ -18472,6 +18492,13 @@ react-native-version-number@^0.3.6:
resolved "https://registry.yarnpkg.com/react-native-version-number/-/react-native-version-number-0.3.6.tgz#dd8b1435fc217df0a166d7e4a61fdc993f3e7437"
integrity sha512-TdyXiK90NiwmSbmAUlUBOV6WI1QGoqtvZZzI5zQY4fKl67B3ZrZn/h+Wy/OYIKKFMfePSiyfeIs8LtHGOZ/NgA==
+react-native-view-shot@^3.8.0:
+ version "3.8.0"
+ resolved "https://registry.yarnpkg.com/react-native-view-shot/-/react-native-view-shot-3.8.0.tgz#1aa1905f0e79428ca32bf80c16fd4abc719c600b"
+ integrity sha512-4cU8SOhMn3YQIrskh+5Q8VvVRxQOu8/s1M9NAL4z5BY1Rm0HXMWkQJ4N0XsZ42+Yca+y86ISF3LC5qdLPvPuiA==
+ dependencies:
+ html2canvas "^1.4.1"
+
react-native-web-linear-gradient@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/react-native-web-linear-gradient/-/react-native-web-linear-gradient-1.1.2.tgz#33f85f7085a0bb5ffa5106faf02ed105b92a9ed7"
@@ -20430,6 +20457,13 @@ test-exclude@^6.0.0:
glob "^7.1.4"
minimatch "^3.0.4"
+text-segmentation@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/text-segmentation/-/text-segmentation-1.0.3.tgz#52a388159efffe746b24a63ba311b6ac9f2d7943"
+ integrity sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==
+ dependencies:
+ utrie "^1.0.2"
+
text-table@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
@@ -21065,6 +21099,13 @@ utils-merge@1.0.1:
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==
+utrie@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/utrie/-/utrie-1.0.2.tgz#d42fe44de9bc0119c25de7f564a6ed1b2c87a645"
+ integrity sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==
+ dependencies:
+ base64-arraybuffer "^1.0.2"
+
uuid@^3.0.1:
version "3.4.0"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"