diff --git a/android/app/src/main/java/com/notes/homocodians/MainActivity.java b/android/app/src/main/java/com/notes/homocodians/MainActivity.java
index 5835f00..6c59ce1 100644
--- a/android/app/src/main/java/com/notes/homocodians/MainActivity.java
+++ b/android/app/src/main/java/com/notes/homocodians/MainActivity.java
@@ -1,5 +1,14 @@
package com.notes.homocodians;
+import android.os.Bundle;
+import com.codetrixstudio.capacitor.GoogleAuth.GoogleAuth;
import com.getcapacitor.BridgeActivity;
-public class MainActivity extends BridgeActivity {}
+public class MainActivity extends BridgeActivity {
+
+ public void onCreate(Bundle savedInstanceState){
+ super.onCreate(savedInstanceState);
+
+ registerPlugin(GoogleAuth.class);
+ }
+}
diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml
index bcb139d..fbf4b7d 100644
--- a/android/app/src/main/res/values/strings.xml
+++ b/android/app/src/main/res/values/strings.xml
@@ -4,4 +4,5 @@
Notes
com.notes.homocodians
com.notes.homocodians
+ 754355741739-t7sec02ku3v1k0dt3opc4e2mktphq8m1.apps.googleusercontent.com
diff --git a/capacitor.config.ts b/capacitor.config.ts
index 441d3fa..be94a35 100644
--- a/capacitor.config.ts
+++ b/capacitor.config.ts
@@ -12,7 +12,8 @@ const config: CapacitorConfig = {
},
GoogleAuth: {
scopes: ["profile", "email"],
- serverClientId: "xxxxxx-xxxxxxxxxxxxxxxxxx.apps.googleusercontent.com",
+ serverClientId:
+ "754355741739-t7sec02ku3v1k0dt3opc4e2mktphq8m1.apps.googleusercontent.com",
forceCodeForRefreshToken: true,
},
},
diff --git a/index.html b/index.html
index 9c31c6a..cd0a1cf 100644
--- a/index.html
+++ b/index.html
@@ -31,6 +31,12 @@
+
+
+
+
+
Notes
diff --git a/package.json b/package.json
index 83ba558..df42075 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "notes",
"private": true,
- "version": "2.1.1",
+ "version": "2.1.2",
"scripts": {
"dev": "vite --port 3000",
"build": "tsc && vite build",
@@ -27,6 +27,7 @@
"octokit": "^3.1.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
+ "react-hot-toast": "^2.4.1",
"react-hotkeys-hook": "^4.4.1",
"react-router": "^6.15.0",
"react-router-dom": "^6.15.0",
diff --git a/src/App.tsx b/src/App.tsx
index 7104d37..0e9d2b2 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,4 +1,4 @@
-import { ReactNode, useMemo } from "react";
+import { useEffect, useMemo } from "react";
import loadable from "@loadable/component";
import { Routes, Route } from "react-router-dom";
@@ -10,11 +10,12 @@ import Loading from "@/components/Loading";
import NotFound from "@/components/NotFound";
import PrivateRoute from "@/components/PrivateRoute";
import DrawerProvider from "@/context/DrawerContext";
-import { getDesignTokens } from "@/utils/getDesignToken";
+import { getDesignTokens } from "@/utils/get-design-token";
import Connectivity from "@/components/general/Connectivity";
import AccountMenuProvider from "@/context/AccountMenuContext";
import { changeStatusbarColor } from "@/utils/change-statusbar-color";
-import CheckForUpdates from "./components/general/CheckForUpdates";
+import CheckForUpdates from "@/components/general/CheckForUpdates";
+import ThemedToaster from "@/components/ThemedToaster";
const HomePage = loadable(() => import("@/pages/Home"));
const ImportantPage = loadable(() => import("@/pages/Important"));
@@ -85,14 +86,16 @@ function App() {
return createTheme(getDesignTokens(isDarkMode ? "dark" : "light"));
}, [isDarkMode]);
- changeStatusbarColor(isDarkMode);
+ useEffect(() => {
+ changeStatusbarColor(isDarkMode);
+ }, [isDarkMode]);
return (
-
+
{routes.map((route) => (
+
diff --git a/src/components/FormDialog.tsx b/src/components/FormDialog.tsx
index f8ad180..3e0fe07 100644
--- a/src/components/FormDialog.tsx
+++ b/src/components/FormDialog.tsx
@@ -1,93 +1,99 @@
-import { HTMLInputTypeAttribute, useState } from "react";
+import { HTMLInputTypeAttribute, useRef, useState } from "react";
import {
- Dialog,
- Button,
- TextField,
- DialogTitle,
- DialogContent,
- DialogActions,
- CircularProgress,
- DialogContentText,
+ Dialog,
+ Button,
+ TextField,
+ DialogTitle,
+ DialogContent,
+ DialogActions,
+ CircularProgress,
+ DialogContentText,
} from "@mui/material";
import Box from "@mui/system/Box";
+import toast from "react-hot-toast";
type FormDialogProps = {
- isOpen: boolean;
- setOpen: (isOpen: boolean) => void;
- title: string;
- content: string;
- textFieldLabel: string;
- textFieldType: HTMLInputTypeAttribute;
- positiveButtonLabel: string;
- TextFieldcolor?:
- | "error"
- | "primary"
- | "secondary"
- | "info"
- | "success"
- | "warning";
- positiveButtonAction: (value: string, cb: () => void) => void;
+ isOpen: boolean;
+ setOpen: (isOpen: boolean) => void;
+ title: string;
+ content: string;
+ textFieldLabel: string;
+ textFieldType: HTMLInputTypeAttribute;
+ positiveButtonLabel: string;
+ TextFieldcolor?:
+ | "error"
+ | "primary"
+ | "secondary"
+ | "info"
+ | "success"
+ | "warning";
+ positiveButtonAction: (value: string, cb: () => void) => void;
};
function FormDialog({
- title,
- isOpen,
- setOpen,
- content,
- textFieldLabel,
- textFieldType,
- positiveButtonLabel,
- positiveButtonAction,
- TextFieldcolor,
+ title,
+ isOpen,
+ setOpen,
+ content,
+ textFieldLabel,
+ textFieldType,
+ positiveButtonLabel,
+ positiveButtonAction,
+ TextFieldcolor,
}: FormDialogProps) {
- const [isLoading, setIsLoading] = useState(false);
+ const [isLoading, setIsLoading] = useState(false);
+ const inputRef = useRef();
- const handleClose = () => {
- setOpen(false);
- };
+ const handleClose = () => {
+ setOpen(false);
+ };
- const handlePositiveClick = () => {
- setIsLoading(true);
- const input = document.getElementById("name") as HTMLInputElement;
- if (input.value) {
- positiveButtonAction(input.value, () => {
- setIsLoading(false);
- });
- }
- };
+ const handlePositiveClick = () => {
+ setIsLoading(true);
+ const input = inputRef.current;
+ if (input && input.value) {
+ positiveButtonAction(input.value, () => {
+ setIsLoading(false);
+ });
+ } else {
+ setIsLoading(false);
+ toast.error("Invalid email");
+ }
+ };
- return (
-
-
-
- );
+ return (
+
+
+
+ );
}
export default FormDialog;
diff --git a/src/components/ThemedToaster.tsx b/src/components/ThemedToaster.tsx
new file mode 100644
index 0000000..0f60eaa
--- /dev/null
+++ b/src/components/ThemedToaster.tsx
@@ -0,0 +1,20 @@
+import { Toaster } from "react-hot-toast";
+import { useTernaryDarkMode } from "usehooks-ts";
+
+function ThemedToaster() {
+ const { isDarkMode } = useTernaryDarkMode();
+ return (
+
+ );
+}
+
+export default ThemedToaster;
diff --git a/src/components/general/CheckForUpdates.tsx b/src/components/general/CheckForUpdates.tsx
index 55f009b..fa33200 100644
--- a/src/components/general/CheckForUpdates.tsx
+++ b/src/components/general/CheckForUpdates.tsx
@@ -1,67 +1,34 @@
-import React from "react";
+import { useCallback, useEffect, useState } from "react";
-import { getLatestRelease } from "@/utils/get-latest-release";
-import CustomSnackbar from "../CustomSnackbar";
+import { checkForUpdates } from "@/utils/get-latest-release";
+import CustomSnackbar from "@/components/CustomSnackbar";
import { Capacitor } from "@capacitor/core";
-type Alert = {
- type: React.ComponentProps["alertType"];
- message: React.ComponentProps["message"];
- open: React.ComponentProps["open"];
-};
-
function CheckForUpdates() {
- const [alert, setAlert] = React.useState({
- type: "error",
- message: "",
- open: false,
- });
+ const [open, setOpen] = useState(false);
+ const [message, setMessage] = useState("");
- const checkForUpdate = React.useCallback(async () => {
+ const checkForUpdate = useCallback(async () => {
try {
- const data = await getLatestRelease();
- if (
- data.status === 200 &&
- data.data.target_commitish === "main" &&
- data.data.draft === false &&
- Number(data.data?.name?.substring(1)?.split(".")?.join("")) >
- Number(import.meta.env.VITE_RELEASE_NUMBER)
- ) {
- setAlert({
- open: true,
- message: `New update available ${data.data.html_url}`,
- type: "info",
- });
- }
- // else {
- // setAlert({
- // open: true,
- // message: `There are currently no new updates available.`,
- // type: "info",
- // });
- // }
- } catch (error) {
- // setAlert({
- // open: true,
- // message: "Failed to check for update.",
- // type: "error",
- // });
- }
+ const data = await checkForUpdates();
+ if (!data) return;
+ setMessage(`New update available ${data.data.html_url}`);
+ setOpen(true);
+ } catch (error) {}
}, []);
- React.useEffect(() => {
- if (Capacitor.getPlatform() === "web") return;
- checkForUpdate();
+ useEffect(() => {
+ if (Capacitor.isNativePlatform()) {
+ checkForUpdate();
+ }
}, [checkForUpdate]);
return (
- setAlert((prev) => ({ ...prev, open: prop, message: "" }))
- }
- alertType={alert.type}
- message={alert.message}
+ open={open}
+ setOpen={setOpen}
+ alertType="info"
+ message={message}
anchorPosition={{ vertical: "bottom", horizontal: "center" }}
/>
);
diff --git a/src/components/general/SettingsMenu.tsx b/src/components/general/SettingsMenu.tsx
index e7d4658..1372a94 100644
--- a/src/components/general/SettingsMenu.tsx
+++ b/src/components/general/SettingsMenu.tsx
@@ -10,16 +10,13 @@ import IconButton from "@mui/material/IconButton";
import Typography from "@mui/material/Typography";
import LogoutIcon from "@mui/icons-material/Logout";
import ListItemIcon from "@mui/material/ListItemIcon";
-import ContentCopyIcon from "@mui/icons-material/ContentCopy";
import { useHotkeys } from "react-hotkeys-hook";
import { useAuth } from "@/context/AuthContext";
import ThemeMenuItem from "@/components/general/ThemeMenuItem";
import ProfileAvatar from "@/components/general/ProfileAvatar";
-import { writeToClipboard } from "@/utils/clipboard";
import CustomSnackbar from "../CustomSnackbar";
import { Settings } from "@mui/icons-material";
-import { grey } from "@mui/material/colors";
export default function SettingsMenu() {
const { logout, user } = useAuth();
diff --git a/src/components/main/AddButton.tsx b/src/components/main/AddButton.tsx
index 092e4a7..1941e58 100644
--- a/src/components/main/AddButton.tsx
+++ b/src/components/main/AddButton.tsx
@@ -2,7 +2,7 @@ import { Fab, useMediaQuery } from "@mui/material";
import AddIcon from "@mui/icons-material/Add";
interface IProps {
- openAddTodoModal: React.Dispatch>;
+ openAddTodoModal: (prop: boolean) => void;
}
function AddButton({ openAddTodoModal }: IProps) {
diff --git a/src/components/main/NoteCard.tsx b/src/components/main/NoteCard.tsx
index 80ebee1..cc862a2 100644
--- a/src/components/main/NoteCard.tsx
+++ b/src/components/main/NoteCard.tsx
@@ -9,7 +9,7 @@ import Typography from "@mui/material/Typography";
import IconButton from "@mui/material/IconButton";
import CardActions from "@mui/material/CardActions";
-import formatDate from "@/utils/formatDate";
+import formatDate from "@/utils/format-date";
import NoteMenu from "@/components/main/NoteMenu";
import useTheme from "@mui/material/styles/useTheme";
import { useAuth } from "@/context/AuthContext";
diff --git a/src/components/main/Notes.tsx b/src/components/main/Notes.tsx
index 62c7b65..8e48f59 100644
--- a/src/components/main/Notes.tsx
+++ b/src/components/main/Notes.tsx
@@ -24,7 +24,7 @@ function Notes() {
) : (
-
+
{notes.map((note) => {
const {
text,
diff --git a/src/components/main/SideDrawer.tsx b/src/components/main/SideDrawer.tsx
index d147a40..3f4cf58 100644
--- a/src/components/main/SideDrawer.tsx
+++ b/src/components/main/SideDrawer.tsx
@@ -21,24 +21,18 @@ import { useDrawer } from "@/context/DrawerContext";
import ConfirmDialog from "@/components/ConfirmDialog";
import CustomSnackbar from "@/components/CustomSnackbar";
import useDeleteAllNotes from "@/hooks/useDeleteAllNotes";
-import { getLatestRelease } from "@/utils/get-latest-release";
+import { checkForUpdates } from "@/utils/get-latest-release";
-type Alert = {
- type: ComponentProps["alertType"];
- message: ComponentProps["message"];
- open: ComponentProps["open"];
-};
+type Type = ComponentProps["alertType"];
function SideDrawer() {
const navigate = useNavigate();
const [open, setOpen] = useState(false);
+ const [message, setMessage] = useState("");
const [loading, setLoading] = useState(false);
+ const [type, setType] = useState("info");
const { isDrawerOpen, setDrawerIsOpen } = useDrawer();
- const [alert, setAlert] = useState({
- type: "error",
- message: "",
- open: false,
- });
+ const [isSnackbarOpen, setIsSnackbarOpen] = useState(false);
useHotkeys("shift+d", () => {
setDrawerIsOpen((prev) => !prev);
@@ -61,37 +55,25 @@ function SideDrawer() {
const checkForUpdate = useCallback(async () => {
setLoading(true);
try {
- const data = await getLatestRelease();
- if (
- data.status === 200 &&
- data.data.target_commitish === "main" &&
- data.data.draft === false &&
- Number(data.data?.name?.substring(1)?.split(".")?.join("")) >
- Number(import.meta.env.VITE_RELEASE_NUMBER)
- ) {
- setLoading(false);
- handleClose();
- setAlert({
- open: true,
- message: `New update available ${data.data.html_url}`,
- type: "info",
- });
- } else {
+ const data = await checkForUpdates();
+ if (!data) {
setLoading(false);
handleClose();
- setAlert({
- open: true,
- message: `There are currently no new updates available.`,
- type: "info",
- });
+ setType("info");
+ setIsSnackbarOpen(true);
+ setMessage("There are currently no new updates available.");
+ return;
}
+ setLoading(false);
+ handleClose();
+ setType("info");
+ setIsSnackbarOpen(true);
+ setMessage(`New update available ${data.data.html_url}`);
} catch (error) {
handleClose();
- setAlert({
- open: true,
- message: "Failed to check for update.",
- type: "error",
- });
+ setType("error");
+ setIsSnackbarOpen(true);
+ setMessage("Failed to check for update.");
}
}, []);
@@ -147,7 +129,7 @@ function SideDrawer() {
gap="0.5rem"
padding="1rem 0.5rem"
>
- {Capacitor.getPlatform() === "web" ? null : (
+ {Capacitor.isNativePlatform() ? (
Check update
- )}
+ ) : null}
- setAlert((prev) => ({ ...prev, open: prop, message: "" }))
- }
- alertType={alert.type}
- message={alert.message}
+ alertType={type}
+ message={message}
+ open={isSnackbarOpen}
+ setOpen={setIsSnackbarOpen}
/>
);
diff --git a/src/context/AuthContext.tsx b/src/context/AuthContext.tsx
index 6270266..6a6877f 100644
--- a/src/context/AuthContext.tsx
+++ b/src/context/AuthContext.tsx
@@ -1,3 +1,5 @@
+import toast from "react-hot-toast";
+
import {
createContext,
ReactNode,
@@ -20,6 +22,8 @@ import {
import Loading from "../components/Loading";
import { auth } from "../firebase";
+import { GoogleAuth } from "@codetrix-studio/capacitor-google-auth";
+import { Capacitor } from "@capacitor/core";
type AuthContextProps = {
children: ReactNode;
@@ -47,7 +51,22 @@ const signInWithGooglePopup = () => {
return signInWithPopup(auth, provider);
};
-const logout = () => {
+const logout = async () => {
+ if (Capacitor.isNativePlatform()) {
+ await toast.promise(
+ GoogleAuth.signOut(),
+ {
+ loading: "Logout...",
+ success: "Success",
+ error: "Failed to Logout",
+ },
+ {
+ style: {
+ minWidth: "180px",
+ },
+ }
+ );
+ }
return signOut(auth);
};
diff --git a/src/firebase.ts b/src/firebase.ts
index 4e74bd4..3b6cf63 100644
--- a/src/firebase.ts
+++ b/src/firebase.ts
@@ -1,13 +1,30 @@
-import { getAuth } from "firebase/auth";
+import {
+ getAuth,
+ indexedDBLocalPersistence,
+ initializeAuth,
+} from "firebase/auth";
import { initializeApp } from "firebase/app";
import { doc, getFirestore } from "firebase/firestore";
import { firebaseConfig } from "./config/firebase.config";
+import { Capacitor } from "@capacitor/core";
const app = initializeApp(firebaseConfig);
+function whichAuth() {
+ let auth;
+ if (Capacitor.isNativePlatform()) {
+ auth = initializeAuth(app, {
+ persistence: indexedDBLocalPersistence,
+ });
+ } else {
+ auth = getAuth(app);
+ }
+ return auth;
+}
+
export default app;
-export const auth = getAuth(app);
+export const auth = whichAuth();
export const db = getFirestore(app);
export const noteDocReference = (id: string) => doc(db, "notes", id);
export const noteReference = () => doc(db, "notes");
diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx
index 866e812..d1480a4 100644
--- a/src/pages/Home.tsx
+++ b/src/pages/Home.tsx
@@ -1,4 +1,4 @@
-import { useState, Fragment } from "react";
+import { useState, Fragment, useCallback } from "react";
import Box from "@mui/system/Box";
import { useHotkeys } from "react-hotkeys-hook";
@@ -10,11 +10,35 @@ import AlertMessage from "@/components/AlertMessage";
import SideDrawer from "@/components/main/SideDrawer";
import AddNoteModal from "@/components/main/AddNoteModal";
import { useAccountMenu } from "@/context/AccountMenuContext";
+import {
+ changeStatusbarColor,
+ setStatusbarColor,
+} from "@/utils/change-statusbar-color";
+import { useTernaryDarkMode } from "usehooks-ts";
+import { Style } from "@capacitor/status-bar";
+import { Capacitor } from "@capacitor/core";
+
+const PaddingTop = Capacitor.isNativePlatform() ? 1 : 2;
function Home() {
+ const { isDarkMode } = useTernaryDarkMode();
const accountMenuOptions = useAccountMenu();
const [isNoteModalOpen, setIsNoteModalOpen] = useState(false);
+ const handleAddNoteModalState = useCallback(
+ (prop: boolean) => {
+ setIsNoteModalOpen(prop);
+ if (prop === true) {
+ const color = isDarkMode ? "#383838" : "#ffffff";
+ const style = isDarkMode ? Style.Dark : Style.Light;
+ setStatusbarColor(color, style);
+ } else {
+ changeStatusbarColor(isDarkMode);
+ }
+ },
+ [isDarkMode, Style]
+ );
+
useHotkeys(
"shift+n",
() => {
@@ -32,26 +56,28 @@ function Home() {
sx={{
display: "flex",
width: "100%",
- overflow: "auto",
paddingBottom: "15px",
}}
>
-
+
-
+
-
+
);
}
diff --git a/src/pages/SignIn.tsx b/src/pages/SignIn.tsx
index 821e727..70c7530 100644
--- a/src/pages/SignIn.tsx
+++ b/src/pages/SignIn.tsx
@@ -20,12 +20,12 @@ import GoogleIcon from "@mui/icons-material/Google";
import LockIcon from "@mui/icons-material/LockOutlined";
import InputAdornment from "@mui/material/InputAdornment";
import CircularProgress from "@mui/material/CircularProgress";
+import toast from "react-hot-toast";
import { useAuth } from "@/context/AuthContext";
import FormDialog from "@/components/FormDialog";
-import CustomDialog from "@/components/CustomDialog";
-import CustomSnackbar from "@/components/CustomSnackbar";
-import VerifyFirebaseErrorCode from "@/utils/authError";
+import VerifyFirebaseErrorCode from "@/utils/firebase-auth-error";
+import { signInWithGoogleNative } from "@/utils/native-google-login";
interface State {
email: string;
@@ -41,10 +41,7 @@ export default function SignIn() {
});
const navigate = useNavigate();
const [isLoading, setIsLoading] = useState(false);
- const [errorMessage, setErrorMessage] = useState("");
- const [isAlertOpen, setIsAlertOpen] = useState(false);
const [isResetFormOpen, setIsResetFormOpen] = useState(false);
- const [isCustomDialogOpen, setIsCustomDialogOpen] = useState(false);
const { signIn, signInWithGooglePopup, sendPasswordResetLink, user } =
useAuth();
@@ -83,27 +80,28 @@ export default function SignIn() {
try {
await signIn(email, password);
} catch (error: any) {
- setErrorMessage(VerifyFirebaseErrorCode(error.code));
- setIsCustomDialogOpen(true);
+ const message = VerifyFirebaseErrorCode(error.code);
setIsLoading(false);
+ toast.error(message);
}
} else {
- setErrorMessage("Please fill all required fields");
- setIsCustomDialogOpen(true);
setIsLoading(false);
+ toast.error("Please fill all required fields");
}
};
const signInWithPopup = async () => {
setIsLoading(true);
try {
- await signInWithGooglePopup();
- // setIsLoading(false);
- // navigate("/", { replace: true });
+ if (Capacitor.isNativePlatform()) {
+ await signInWithGoogleNative();
+ } else {
+ await signInWithGooglePopup();
+ }
} catch (error: any) {
- setErrorMessage(VerifyFirebaseErrorCode(error.code));
- setIsCustomDialogOpen(true);
+ const errorMessage = VerifyFirebaseErrorCode(error.code);
setIsLoading(false);
+ toast.error(errorMessage);
}
};
@@ -112,12 +110,14 @@ export default function SignIn() {
await sendPasswordResetLink(email);
cb();
setIsResetFormOpen(false);
- setIsAlertOpen(true);
+ toast.success(
+ "Email has been sent, please check your spam folder if not found."
+ );
} catch (error: any) {
cb();
- setErrorMessage(VerifyFirebaseErrorCode(error.code));
- setIsCustomDialogOpen(true);
+ const errorMessage = VerifyFirebaseErrorCode(error?.code);
setIsResetFormOpen(false);
+ toast.error(errorMessage);
}
};
@@ -200,18 +200,17 @@ export default function SignIn() {
>
Sign In
- {Capacitor.getPlatform() === "web" && (
- : null}
- onClick={signInWithPopup}
- >
- Continue With Google
-
- )}
+
+ : null}
+ onClick={signInWithPopup}
+ >
+ Continue With Google
+
-
theme.zIndex.drawer + 1 }}
+ sx={{
+ color: "#fff",
+ zIndex: (theme) => theme.zIndex.drawer + 1,
+ }}
open={isLoading}
>
-
>
);
}
diff --git a/src/pages/SignUp.tsx b/src/pages/SignUp.tsx
index 89673f3..4a0ddf8 100644
--- a/src/pages/SignUp.tsx
+++ b/src/pages/SignUp.tsx
@@ -20,10 +20,11 @@ import LockIcon from "@mui/icons-material/LockOutlined";
import { useNavigate } from "react-router-dom";
import Container from "@mui/material/Container";
import { Capacitor } from "@capacitor/core";
+import toast from "react-hot-toast";
import { useAuth } from "@/context/AuthContext";
-import VerifyFirebaseErrorCode from "@/utils/authError";
-import CustomSnackbar from "@/components/CustomSnackbar";
+import VerifyFirebaseErrorCode from "@/utils/firebase-auth-error";
+import { signInWithGoogleNative } from "@/utils/native-google-login";
interface InputFields {
email: string;
@@ -104,11 +105,8 @@ export default function SignUp() {
password: password === "" ? true : false,
confirmPassword: confirm_password === "" ? true : false,
});
- setAlert({
- message: "Password does not match!",
- isOpen: true,
- });
setIsLoading(false);
+ toast.error("Password does not match.");
return;
}
if (password !== confirm_password) {
@@ -117,36 +115,33 @@ export default function SignUp() {
password: true,
confirmPassword: true,
});
- setAlert({
- message: "Password does not match.",
- isOpen: true,
- });
setIsLoading(false);
+ toast.error("Password does not match.");
return;
}
try {
await signUp(email, password);
} catch (error: any) {
- setAlert({
- message: VerifyFirebaseErrorCode(error.code),
- isOpen: true,
- });
+ const errorMessage = VerifyFirebaseErrorCode(error?.code);
setIsLoading(false);
+ toast.error(errorMessage);
}
};
const signInWithPopup = async () => {
setIsLoading(true);
try {
- await signInWithGooglePopup();
+ if (Capacitor.isNativePlatform()) {
+ await signInWithGoogleNative();
+ } else {
+ await signInWithGooglePopup();
+ }
setIsLoading(false);
navigate("/", { replace: true });
} catch (error: any) {
- setAlert({
- message: VerifyFirebaseErrorCode(error.code),
- isOpen: true,
- });
+ const errorMessage = VerifyFirebaseErrorCode(error?.code);
setIsLoading(false);
+ toast.error(errorMessage);
}
};
@@ -262,18 +257,17 @@ export default function SignUp() {
>
Sign Up
- {Capacitor.getPlatform() === "web" && (
- }
- onClick={signInWithPopup}
- >
- Continue With Google
-
- )}
+
+ }
+ onClick={signInWithPopup}
+ >
+ Continue With Google
+
@@ -284,18 +278,6 @@ export default function SignUp() {
-
theme.zIndex.drawer + 1 }}
open={isLoading}
diff --git a/src/utils/change-statusbar-color.ts b/src/utils/change-statusbar-color.ts
index 9062ee3..ffe29cf 100644
--- a/src/utils/change-statusbar-color.ts
+++ b/src/utils/change-statusbar-color.ts
@@ -4,10 +4,18 @@ import { StatusBar, Style } from "@capacitor/status-bar";
export async function changeStatusbarColor(isDarkMode: boolean) {
if (Capacitor.getPlatform() === "android") {
if (isDarkMode) {
- await StatusBar.setBackgroundColor({ color: "#121212" });
+ await StatusBar.setBackgroundColor({ color: "#272727" });
} else {
await StatusBar.setBackgroundColor({ color: "#ff5722" });
}
await StatusBar.setStyle({ style: Style.Dark });
}
}
+
+export async function setStatusbarColor(color: string, style?: Style) {
+ await StatusBar.setBackgroundColor({ color });
+
+ if (style) {
+ await StatusBar.setStyle({ style });
+ }
+}
diff --git a/src/utils/authError.ts b/src/utils/firebase-auth-error.ts
similarity index 98%
rename from src/utils/authError.ts
rename to src/utils/firebase-auth-error.ts
index 92bc7cc..454d121 100644
--- a/src/utils/authError.ts
+++ b/src/utils/firebase-auth-error.ts
@@ -172,7 +172,9 @@ export default function VerifyFirebaseErrorCode(errorCode: any): string {
return "The credential used to initialize the Admin SDK has insufficient permission to access the requested Authentication resource.";
case "auth/internal-error":
return "The Authentication server encountered an unexpected error while trying to process the request.";
+ case "12501":
+ return "Sign-in flow cancelled";
default:
- return errorCode;
+ return "Something went wrong.";
}
}
diff --git a/src/utils/formatDate.ts b/src/utils/format-date.ts
similarity index 100%
rename from src/utils/formatDate.ts
rename to src/utils/format-date.ts
diff --git a/src/utils/getDesignToken.ts b/src/utils/get-design-token.ts
similarity index 100%
rename from src/utils/getDesignToken.ts
rename to src/utils/get-design-token.ts
diff --git a/src/utils/get-latest-release.ts b/src/utils/get-latest-release.ts
index 0960780..62f3919 100644
--- a/src/utils/get-latest-release.ts
+++ b/src/utils/get-latest-release.ts
@@ -10,3 +10,22 @@ export async function getLatestRelease() {
repo: import.meta.env.VITE_GITHUB_REPO,
});
}
+
+export async function checkForUpdates() {
+ const data = await getLatestRelease();
+
+ if (!data) {
+ return null;
+ }
+
+ if (
+ data.status === 200 &&
+ data.data.target_commitish === "main" &&
+ data.data.draft === false &&
+ Number(data.data?.tag_name?.substring(1)?.split(".")?.join("")) >
+ Number(import.meta.env.VITE_RELEASE_NUMBER)
+ ) {
+ return data;
+ }
+ return null;
+}
diff --git a/src/utils/native-google-login.ts b/src/utils/native-google-login.ts
new file mode 100644
index 0000000..f0b1168
--- /dev/null
+++ b/src/utils/native-google-login.ts
@@ -0,0 +1,11 @@
+import { auth } from "@/firebase";
+import { GoogleAuth } from "@codetrix-studio/capacitor-google-auth";
+import { GoogleAuthProvider, signInWithCredential } from "firebase/auth";
+
+export async function signInWithGoogleNative() {
+ const response = await GoogleAuth.signIn();
+ const credentials = GoogleAuthProvider.credential(
+ response?.authentication?.idToken
+ );
+ return signInWithCredential(auth, credentials);
+}
diff --git a/src/utils/sleep.ts b/src/utils/sleep.ts
new file mode 100644
index 0000000..507d915
--- /dev/null
+++ b/src/utils/sleep.ts
@@ -0,0 +1,3 @@
+export async function sleep(ms = 5000) {
+ return new Promise((resolve) => setTimeout(resolve, ms));
+}
diff --git a/yarn.lock b/yarn.lock
index 77126c5..9f8774a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2704,6 +2704,11 @@ globals@^11.1.0:
resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
+goober@^2.1.10:
+ version "2.1.13"
+ resolved "https://registry.yarnpkg.com/goober/-/goober-2.1.13.tgz#e3c06d5578486212a76c9eba860cbc3232ff6d7c"
+ integrity sha512-jFj3BQeleOoy7t93E9rZ2de+ScC4lQICLwiAQmKMg9F6roKGaLSHoCDYKkWlSafg138jejvq/mTdvmnwDQgqoQ==
+
gopd@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c"
@@ -3651,6 +3656,13 @@ react-dom@^18.2.0:
loose-envify "^1.1.0"
scheduler "^0.23.0"
+react-hot-toast@^2.4.1:
+ version "2.4.1"
+ resolved "https://registry.yarnpkg.com/react-hot-toast/-/react-hot-toast-2.4.1.tgz#df04295eda8a7b12c4f968e54a61c8d36f4c0994"
+ integrity sha512-j8z+cQbWIM5LY37pR6uZR6D4LfseplqnuAO4co4u8917hBUvXlEqyP1ZzqVLcqoyUesZZv/ImreoCeHVDpE5pQ==
+ dependencies:
+ goober "^2.1.10"
+
react-hotkeys-hook@^4.4.1:
version "4.4.1"
resolved "https://registry.yarnpkg.com/react-hotkeys-hook/-/react-hotkeys-hook-4.4.1.tgz#1f7a7a1c9c21d4fa3280bf340fcca8fd77d81994"