Skip to content

Commit

Permalink
feat: native google login option & matching statusbar color in native…
Browse files Browse the repository at this point in the history
… devices
  • Loading branch information
homocodian committed Sep 29, 2023
1 parent 22ec3bc commit 0dfeaee
Show file tree
Hide file tree
Showing 27 changed files with 365 additions and 284 deletions.
Original file line number Diff line number Diff line change
@@ -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);
}
}
1 change: 1 addition & 0 deletions android/app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
<string name="title_activity_main">Notes</string>
<string name="package_name">com.notes.homocodians</string>
<string name="custom_url_scheme">com.notes.homocodians</string>
<string name="server_client_id">754355741739-t7sec02ku3v1k0dt3opc4e2mktphq8m1.apps.googleusercontent.com</string>
</resources>
3 changes: 2 additions & 1 deletion capacitor.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
},
},
Expand Down
6 changes: 6 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@
<link rel="apple-touch-icon" href="/icon/apple-icon-180.png">
<link rel="manifest" href="/manifest.json" />
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" />

<!-- Google Meta Tags -->
<meta name="google-signin-client_id"
content="754355741739-t7sec02ku3v1k0dt3opc4e2mktphq8m1.apps.googleusercontent.com" />
<meta name="google-signin-scope" content="profile email" />

<title>Notes</title>
</head>

Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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",
Expand All @@ -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",
Expand Down
14 changes: 9 additions & 5 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -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"));
Expand Down Expand Up @@ -85,14 +86,16 @@ function App() {
return createTheme(getDesignTokens(isDarkMode ? "dark" : "light"));
}, [isDarkMode]);

changeStatusbarColor(isDarkMode);
useEffect(() => {
changeStatusbarColor(isDarkMode);
}, [isDarkMode]);

return (
<ThemeProvider theme={theme}>
<DrawerProvider>
<AccountMenuProvider>
<AppBar />
<div style={{ paddingTop: "64px" }}>
<div style={{ paddingTop: "64px", overflow: "auto" }}>
<Routes>
{routes.map((route) => (
<Route
Expand All @@ -105,6 +108,7 @@ function App() {
</div>
<Connectivity />
<CheckForUpdates />
<ThemedToaster />
</AccountMenuProvider>
</DrawerProvider>
</ThemeProvider>
Expand Down
160 changes: 83 additions & 77 deletions src/components/FormDialog.tsx
Original file line number Diff line number Diff line change
@@ -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<HTMLInputElement>();

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 (
<div>
<Dialog open={isOpen} onClose={handleClose}>
<DialogTitle>{title}</DialogTitle>
<DialogContent>
<DialogContentText>{content}</DialogContentText>
<TextField
autoFocus
margin="dense"
id="name"
label={textFieldLabel}
type={textFieldType}
autoComplete={textFieldType === "email" ? "email" : "text"}
fullWidth
variant="standard"
color={TextFieldcolor}
/>
</DialogContent>
<DialogActions>
<Button onClick={handleClose}>Cancel</Button>
{isLoading ? (
<Box mx={2}>
<CircularProgress size={25} />
</Box>
) : (
<Button onClick={handlePositiveClick}>{positiveButtonLabel}</Button>
)}
</DialogActions>
</Dialog>
</div>
);
return (
<div>
<Dialog open={isOpen} onClose={handleClose}>
<DialogTitle>{title}</DialogTitle>
<DialogContent>
<DialogContentText>{content}</DialogContentText>
<TextField
autoFocus
margin="dense"
id="name"
label={textFieldLabel}
type={textFieldType}
autoComplete={textFieldType === "email" ? "email" : "text"}
fullWidth
variant="standard"
color={TextFieldcolor}
inputRef={inputRef}
/>
</DialogContent>
<DialogActions>
<Button onClick={handleClose}>Cancel</Button>
{isLoading ? (
<Box mx={2}>
<CircularProgress size={25} />
</Box>
) : (
<Button onClick={handlePositiveClick}>{positiveButtonLabel}</Button>
)}
</DialogActions>
</Dialog>
</div>
);
}

export default FormDialog;
20 changes: 20 additions & 0 deletions src/components/ThemedToaster.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Toaster } from "react-hot-toast";
import { useTernaryDarkMode } from "usehooks-ts";

function ThemedToaster() {
const { isDarkMode } = useTernaryDarkMode();
return (
<Toaster
toastOptions={{
position: "bottom-center",
style: {
backgroundColor: !isDarkMode ? "#121212" : undefined,
color: !isDarkMode ? "#ffffff" : undefined,
borderRadius: 999,
},
}}
/>
);
}

export default ThemedToaster;
71 changes: 19 additions & 52 deletions src/components/general/CheckForUpdates.tsx
Original file line number Diff line number Diff line change
@@ -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<typeof CustomSnackbar>["alertType"];
message: React.ComponentProps<typeof CustomSnackbar>["message"];
open: React.ComponentProps<typeof CustomSnackbar>["open"];
};

function CheckForUpdates() {
const [alert, setAlert] = React.useState<Alert>({
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 (
<CustomSnackbar
open={alert.open}
setOpen={(prop) =>
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" }}
/>
);
Expand Down
Loading

0 comments on commit 0dfeaee

Please sign in to comment.