eyeSVG & center login
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
# Repository Guidelines
|
# Repository Guidelines
|
||||||
|
|
||||||
## Project Structure & Module Organization
|
## Project Structure & Module Organization
|
||||||
|
|
||||||
- Entry points: `App.js`, `index.js`, `index.web.js`.
|
- Entry points: `App.js`, `index.js`, `index.web.js`.
|
||||||
- Source code: `src/` (key folders: `actions/`, `components/`, `hooks/`, `screens/`, `providers/`, `navigation/`, `utils/`, `styles/`, `assets/`).
|
- Source code: `src/` (key folders: `actions/`, `components/`, `hooks/`, `screens/`, `providers/`, `navigation/`, `utils/`, `styles/`, `assets/`).
|
||||||
- Native projects: `android/`, `ios/`.
|
- Native projects: `android/`, `ios/`.
|
||||||
@@ -9,6 +10,7 @@
|
|||||||
- Backend: `functions/` (Firebase Cloud Functions, Node 20).
|
- Backend: `functions/` (Firebase Cloud Functions, Node 20).
|
||||||
|
|
||||||
## Build, Test, and Development Commands
|
## Build, Test, and Development Commands
|
||||||
|
|
||||||
- Install deps: `yarn` (preferred; lockfile is `yarn.lock`).
|
- Install deps: `yarn` (preferred; lockfile is `yarn.lock`).
|
||||||
- Run app: `yarn start` (Expo dev client), `yarn android`, `yarn ios`, `yarn web`.
|
- Run app: `yarn start` (Expo dev client), `yarn android`, `yarn ios`, `yarn web`.
|
||||||
- Clean native builds: `yarn clean` (runs `expo prebuild --clean`).
|
- Clean native builds: `yarn clean` (runs `expo prebuild --clean`).
|
||||||
@@ -17,26 +19,28 @@
|
|||||||
- Firebase functions: `cd functions && npm run serve` (emulators), `npm run deploy`.
|
- Firebase functions: `cd functions && npm run serve` (emulators), `npm run deploy`.
|
||||||
|
|
||||||
## Coding Style & Naming Conventions
|
## Coding Style & Naming Conventions
|
||||||
|
|
||||||
- Languages: React Native (JS/TS). Indentation: 2 spaces.
|
- Languages: React Native (JS/TS). Indentation: 2 spaces.
|
||||||
- Lint/format: ESLint (`expo`, `prettier`) + Prettier. Keep code formatted; fix all lint errors.
|
- dont do eslint checks
|
||||||
- Example: `npx eslint src`.
|
|
||||||
- Components and screens: PascalCase filenames, e.g., `MusicDetails.js`, `CreateLyricsWithAi.js`.
|
- Components and screens: PascalCase filenames, e.g., `MusicDetails.js`, `CreateLyricsWithAi.js`.
|
||||||
- Hooks: prefix with `use` (e.g., `src/hooks/useFirestorePagination.js`).
|
- Hooks: prefix with `use` (e.g., `src/hooks/useFirestorePagination.js`).
|
||||||
- Utilities: lowerCamelCase modules in `src/utils/` or `helpers/`; prefer named exports.
|
- Utilities: lowerCamelCase modules in `src/utils/` or `helpers/`; prefer named exports.
|
||||||
- Avoid duplicating inline styles; share via `src/styles/`.
|
- Avoid duplicating inline styles; share via `src/styles/`.
|
||||||
|
|
||||||
## Testing Guidelines
|
## Testing Guidelines
|
||||||
|
|
||||||
- No unit tests configured yet. If adding tests, prefer Jest + `@testing-library/react-native`.
|
- No unit tests configured yet. If adding tests, prefer Jest + `@testing-library/react-native`.
|
||||||
- Place tests under `src/**/__tests__/` or as `*.test.[jt]sx` near sources.
|
- Place tests under `src/**/__tests__/` or as `*.test.[jt]sx` near sources.
|
||||||
- Until tests exist, include manual test steps in PRs (platform, device, steps, expected results).
|
- Until tests exist, include manual test steps in PRs (platform, device, steps, expected results).
|
||||||
|
|
||||||
## Commit & Pull Request Guidelines
|
## Commit & Pull Request Guidelines
|
||||||
|
|
||||||
- Commits: concise, imperative subject (≤72 chars). Optional scope, e.g., `feat(login): add Google button`.
|
- Commits: concise, imperative subject (≤72 chars). Optional scope, e.g., `feat(login): add Google button`.
|
||||||
- PRs must include: clear description, screenshots/video for UI changes, reproduction and verification steps, linked issues, and notes on breaking changes.
|
- PRs must include: clear description, screenshots/video for UI changes, reproduction and verification steps, linked issues, and notes on breaking changes.
|
||||||
- Verify the app launches on Android, iOS, and Web locally; fix lint and type warnings before requesting review.
|
- Verify the app launches on Android, iOS, and Web locally; fix lint and type warnings before requesting review.
|
||||||
|
|
||||||
## Security & Configuration Tips
|
## Security & Configuration Tips
|
||||||
|
|
||||||
- Never commit secrets (e.g., `functions/serviceAccountKey.json`, API keys). Use Firebase/Expo secrets and environment config.
|
- Never commit secrets (e.g., `functions/serviceAccountKey.json`, API keys). Use Firebase/Expo secrets and environment config.
|
||||||
- Manage runtime config via `app.json`/`eas.json` or remote config; avoid hardcoding credentials.
|
- Manage runtime config via `app.json`/`eas.json` or remote config; avoid hardcoding credentials.
|
||||||
- Before EAS builds, run `yarn clean` to resync native projects.
|
- Before EAS builds, run `yarn clean` to resync native projects.
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import * as React from "react";
|
||||||
|
import Svg, { Circle, Path } from "react-native-svg";
|
||||||
|
|
||||||
|
function EyeSVG(props) {
|
||||||
|
return (
|
||||||
|
<Svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width={props?.size ?? 24}
|
||||||
|
height={props?.size ?? 24}
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="white"
|
||||||
|
strokeWidth={2}
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
aria-hidden="true"
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<Path d="M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7-10-7-10-7z" />
|
||||||
|
<Circle cx={12} cy={12} r={3} />
|
||||||
|
</Svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default EyeSVG;
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import * as React from "react";
|
||||||
|
import Svg, { Path } from "react-native-svg";
|
||||||
|
|
||||||
|
function EyeSlashSVG(props) {
|
||||||
|
return (
|
||||||
|
<Svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width={props?.size ?? 24}
|
||||||
|
height={props?.size ?? 24}
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="white"
|
||||||
|
strokeWidth={2}
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
aria-hidden="true"
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<Path d="M3 3l18 18" />
|
||||||
|
<Path d="M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7-10-7-10-7z" />
|
||||||
|
<Path d="M12 9a3 3 0 013 3" />
|
||||||
|
<Path d="M9.88 9.88A3 3 0 0012 15a3 3 0 002.12-.88" />
|
||||||
|
</Svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default EyeSlashSVG;
|
||||||
+15
-18
@@ -1,24 +1,25 @@
|
|||||||
import {
|
|
||||||
Pressable,
|
|
||||||
TextInput,
|
|
||||||
InputAccessoryView,
|
|
||||||
Text,
|
|
||||||
View,
|
|
||||||
Image,
|
|
||||||
Keyboard,
|
|
||||||
Platform,
|
|
||||||
} from "react-native";
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
import {
|
||||||
|
Image,
|
||||||
|
InputAccessoryView,
|
||||||
|
Keyboard,
|
||||||
|
Pressable,
|
||||||
|
Text,
|
||||||
|
TextInput,
|
||||||
|
View,
|
||||||
|
} from "react-native";
|
||||||
// import CountryPicker, { DARK_THEME } from "react-native-country-picker-modal";
|
// import CountryPicker, { DARK_THEME } from "react-native-country-picker-modal";
|
||||||
import usePlaceApi from "react-native-minuit/src/hooks/usePlacesApi";
|
import usePlaceApi from "react-native-minuit/src/hooks/usePlacesApi";
|
||||||
|
|
||||||
import { art, icons } from "../assets";
|
import { art, icons } from "../assets";
|
||||||
import { Fonts, Palette, Style, gutters } from "../styles";
|
import { Fonts, Palette, Style, gutters } from "../styles";
|
||||||
import { FONT_FAMILY, fontTypeList } from "../styles/Fonts";
|
import { FONT_FAMILY } from "../styles/Fonts";
|
||||||
|
|
||||||
import { isWeb } from "../hooks/useLayoutType";
|
|
||||||
import { GOOGLE_API_KEY } from "../data/keys";
|
|
||||||
import { BlurView } from "expo-blur";
|
import { BlurView } from "expo-blur";
|
||||||
|
import EyeSlashSVG from "../assets/UI/EyeSlashSVG";
|
||||||
|
import EyeSVG from "../assets/UI/EyeSVG";
|
||||||
|
import { GOOGLE_API_KEY } from "../data/keys";
|
||||||
|
import { isWeb } from "../hooks/useLayoutType";
|
||||||
|
|
||||||
const Input = ({
|
const Input = ({
|
||||||
inputRef = null,
|
inputRef = null,
|
||||||
@@ -189,11 +190,7 @@ const Input = ({
|
|||||||
)}
|
)}
|
||||||
{type === "password" ? (
|
{type === "password" ? (
|
||||||
<Pressable onPress={() => setShowPassword(!showPassword)}>
|
<Pressable onPress={() => setShowPassword(!showPassword)}>
|
||||||
<Image
|
{showPassword ? <EyeSVG /> : <EyeSlashSVG />}
|
||||||
source={icons.eye}
|
|
||||||
style={[Style.iconDefault]}
|
|
||||||
resizeMode="contain"
|
|
||||||
/>
|
|
||||||
</Pressable>
|
</Pressable>
|
||||||
) : type === "coinAmount" ? (
|
) : type === "coinAmount" ? (
|
||||||
<Image
|
<Image
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import React from "react";
|
|
||||||
import { ActionSheetProvider } from "@expo/react-native-action-sheet";
|
import { ActionSheetProvider } from "@expo/react-native-action-sheet";
|
||||||
import { SafeAreaProvider } from "react-native-safe-area-context";
|
|
||||||
import { BottomSheetModalProvider } from "@gorhom/bottom-sheet";
|
import { BottomSheetModalProvider } from "@gorhom/bottom-sheet";
|
||||||
|
import React from "react";
|
||||||
|
import { SafeAreaProvider } from "react-native-safe-area-context";
|
||||||
|
|
||||||
|
import { SheetProvider } from "react-native-actions-sheet";
|
||||||
|
import SplashAnimationProvider from "./SplashAnimationProvider";
|
||||||
|
import StripeEmbeddedProvider from "./StripeEmbeddedProvider";
|
||||||
|
import UniversalLinkProvider from "./UniversalLinkProvider";
|
||||||
import UserDataProvider from "./UserDataProvider";
|
import UserDataProvider from "./UserDataProvider";
|
||||||
import WebViewProvider from "./WebViewProvider";
|
import WebViewProvider from "./WebViewProvider";
|
||||||
import SplashAnimationProvider from "./SplashAnimationProvider";
|
|
||||||
import UniversalLinkProvider from "./UniversalLinkProvider";
|
|
||||||
import StripeEmbeddedProvider from "./StripeEmbeddedProvider";
|
|
||||||
import { SheetProvider } from "react-native-actions-sheet";
|
|
||||||
|
|
||||||
const SharedProviders = ({ children }) => {
|
const SharedProviders = ({ children }) => {
|
||||||
const providers = [
|
const providers = [
|
||||||
|
|||||||
+11
-5
@@ -1,4 +1,4 @@
|
|||||||
import { GoogleSigninButton } from "@react-native-google-signin/google-signin";
|
/* eslint-disable react/display-name */
|
||||||
import * as AuthSession from "expo-auth-session";
|
import * as AuthSession from "expo-auth-session";
|
||||||
import * as GoogleAuth from "expo-auth-session/providers/google";
|
import * as GoogleAuth from "expo-auth-session/providers/google";
|
||||||
import * as WebBrowser from "expo-web-browser";
|
import * as WebBrowser from "expo-web-browser";
|
||||||
@@ -8,6 +8,7 @@ import { useGlobal } from "reactn";
|
|||||||
import { background } from "../assets";
|
import { background } from "../assets";
|
||||||
import GradientButton from "../components/GradientButton.js";
|
import GradientButton from "../components/GradientButton.js";
|
||||||
import { Input } from "../components/Input.js";
|
import { Input } from "../components/Input.js";
|
||||||
|
import ItemContainer from "../components/ItemContainer/ItemContainer";
|
||||||
import firebase, { usersRef } from "../config/firebase";
|
import firebase, { usersRef } from "../config/firebase";
|
||||||
import {
|
import {
|
||||||
GOOGLE_ANDROID_CLIENT_ID,
|
GOOGLE_ANDROID_CLIENT_ID,
|
||||||
@@ -20,7 +21,6 @@ import { Routes } from "../navigation";
|
|||||||
import { navigate } from "../navigation/NavigationService.js";
|
import { navigate } from "../navigation/NavigationService.js";
|
||||||
import { FONT_FAMILY } from "../styles/Fonts.js";
|
import { FONT_FAMILY } from "../styles/Fonts.js";
|
||||||
import Palette from "../styles/Palette.js";
|
import Palette from "../styles/Palette.js";
|
||||||
import ItemContainer from "../components/ItemContainer/ItemContainer";
|
|
||||||
|
|
||||||
export default ({ navigation }) => {
|
export default ({ navigation }) => {
|
||||||
WebBrowser.maybeCompleteAuthSession();
|
WebBrowser.maybeCompleteAuthSession();
|
||||||
@@ -133,7 +133,7 @@ export default ({ navigation }) => {
|
|||||||
redirectUri: request?.redirectUri,
|
redirectUri: request?.redirectUri,
|
||||||
extraParams: { code_verifier: request?.codeVerifier },
|
extraParams: { code_verifier: request?.codeVerifier },
|
||||||
},
|
},
|
||||||
discovery,
|
discovery
|
||||||
);
|
);
|
||||||
idToken = tokenResponse?.id_token;
|
idToken = tokenResponse?.id_token;
|
||||||
}
|
}
|
||||||
@@ -168,10 +168,16 @@ export default ({ navigation }) => {
|
|||||||
width={isWeb ? 600 : null}
|
width={isWeb ? 600 : null}
|
||||||
backgroundImg={isWeb ? background.loginBgWeb : background.homeBG}
|
backgroundImg={isWeb ? background.loginBgWeb : background.homeBG}
|
||||||
headerType="NAVIGATION"
|
headerType="NAVIGATION"
|
||||||
title="Connexion"
|
title={isWeb ? "" : "Connexion"}
|
||||||
hideBackButton
|
hideBackButton
|
||||||
>
|
>
|
||||||
<View style={{ flex: 1, paddingTop: 20 }}>
|
<View
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
<ItemContainer height={600} width={800} disableKeyboardHeight>
|
<ItemContainer height={600} width={800} disableKeyboardHeight>
|
||||||
<View style={{ gap: 30, paddingTop: 5, paddingHorizontal: 5 }}>
|
<View style={{ gap: 30, paddingTop: 5, paddingHorizontal: 5 }}>
|
||||||
<View style={{ gap: 2 }}>
|
<View style={{ gap: 2 }}>
|
||||||
|
|||||||
@@ -193,9 +193,7 @@ const RecordPlayback = ({ route }) => {
|
|||||||
"mediaRecorder:error",
|
"mediaRecorder:error",
|
||||||
String(err?.message || err || "")
|
String(err?.message || err || "")
|
||||||
);
|
);
|
||||||
setMediaError(
|
setMediaError(err instanceof Error ? err : new Error(String(err || "")));
|
||||||
err instanceof Error ? err : new Error(String(err || ""))
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
recorder.onstop = () => {
|
recorder.onstop = () => {
|
||||||
@@ -475,14 +473,10 @@ const RecordPlayback = ({ route }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setIsRecording(false);
|
setIsRecording(false);
|
||||||
console.log(
|
console.log(LOG_PREFIX, "stopAndNavigate:navigate", {
|
||||||
LOG_PREFIX,
|
route: Routes.RecordedPlayback,
|
||||||
"stopAndNavigate:navigate",
|
hasVideo: !!videoUrl,
|
||||||
{
|
});
|
||||||
route: Routes.RecordedPlayback,
|
|
||||||
hasVideo: !!videoUrl,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
navigate(Routes.RecordedPlayback, { project, videoUri: videoUrl || null });
|
navigate(Routes.RecordedPlayback, { project, videoUri: videoUrl || null });
|
||||||
}, [dur, player, pos, project, stopRecorderAndGetUrl]);
|
}, [dur, player, pos, project, stopRecorderAndGetUrl]);
|
||||||
|
|
||||||
|
|||||||
+14
-8
@@ -1,15 +1,15 @@
|
|||||||
import { View, Text, Pressable } from "react-native";
|
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import Page from "../layouts/Page";
|
import { Pressable, Text, View } from "react-native";
|
||||||
import { background } from "../assets";
|
import { background } from "../assets";
|
||||||
import { Palette } from "../styles";
|
|
||||||
import { FONT_FAMILY } from "../styles/Fonts";
|
|
||||||
import { Input } from "../components/Input";
|
|
||||||
import BorderGradientButton from "../components/BorderGradientButton";
|
import BorderGradientButton from "../components/BorderGradientButton";
|
||||||
import { navigate } from "../navigation/NavigationService";
|
import { Input } from "../components/Input";
|
||||||
import { Routes } from "../navigation";
|
|
||||||
import ItemContainer from "../components/ItemContainer/ItemContainer";
|
import ItemContainer from "../components/ItemContainer/ItemContainer";
|
||||||
import { isWeb } from "../hooks/useLayoutType";
|
import { isWeb } from "../hooks/useLayoutType";
|
||||||
|
import Page from "../layouts/Page";
|
||||||
|
import { Routes } from "../navigation";
|
||||||
|
import { navigate } from "../navigation/NavigationService";
|
||||||
|
import { Palette } from "../styles";
|
||||||
|
import { FONT_FAMILY } from "../styles/Fonts";
|
||||||
|
|
||||||
const Register = () => {
|
const Register = () => {
|
||||||
const [email, setEmail] = useState("");
|
const [email, setEmail] = useState("");
|
||||||
@@ -21,7 +21,13 @@ const Register = () => {
|
|||||||
headerType="NAVIGATION"
|
headerType="NAVIGATION"
|
||||||
title="Inscription"
|
title="Inscription"
|
||||||
>
|
>
|
||||||
<View style={{ flex: 1, paddingTop: 20 }}>
|
<View
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
<ItemContainer height={360} disableKeyboardHeight>
|
<ItemContainer height={360} disableKeyboardHeight>
|
||||||
<View style={{ gap: 32, paddingTop: 5, paddingHorizontal: 5 }}>
|
<View style={{ gap: 32, paddingTop: 5, paddingHorizontal: 5 }}>
|
||||||
<Text
|
<Text
|
||||||
|
|||||||
Reference in New Issue
Block a user