Building a Fully Functional Youtube Clone Using Firebase, FFmpeg, And React [Part-3]

Written by decodebuzzing | Published 2022/06/27
Tech Story Tags: react | firebase | software-development | youtube-clone-react-js | ffmpeg | redux | context-api | front-end-development

TLDRAn exact clone of youtube with all functionalities from View count to Subscribe to everything (Without Youtube Api) Using Firebase, FFmpeg, And React, and React. So in this part First let’s add firebase to our app then we can create the firebase Context API. We’ll implement the Entire Authentication system of firebase and complete our context file. Let’s add firebase to our app and create the Firestore database for our app. The Github code has been uploaded to GitHub and you can check it out!via the TL;DR App

An exact clone of youtube with all functionalities from View count to Subscribe to everything (Without Youtube Api) Using Firebase, FFmpeg, And React


Note:

Following are the different parts of this project in order:

  • Part 1 — Intro to the Project and Features Explanation
  • Part 2 — Create the skeleton of the app from adding redux to adding all screens with dummy data and at last adding routes
  • Part 3 — Adding Firebase to our App, Creating Context Api, Completing Authentication Login from the web (This Article)

I’ll update the order as we Move on :))


Github Code

Again for new viewers, The Github code has been uploaded here! You can check it out!

https://github.com/harsh317/Youtube-CLone-ReactJs


What We Gonna go in this Part

So in this part First let’s add firebase to our app then we can create the firebase Context API. We’ll implement the Entire Authentication system of firebase and complete our context file. With that being said, Let’s get started !!


Creating And Initialising Firebase project AND Configuring For Basic Authentication functions

First, quickly go to Firebase Console and click on Add Project / Create A project. Give a Project name → Accept the Conditions → Disable/Enable Google Analytics → Create Project

You should see something like this

Enabling FireStore Database

Now let’s enable the firestore database for our app. Click on the Firestore database or directly go to this link


Next on the right- side click on “Create database” → Select a starting mode for your Cloud Firestore Security Rules (I will click Test mode for now) → Select a location for your database → Enable

Test Mode

*Good for getting started with the mobile and web client libraries, but allows anyone to read and overwrite your data. After testing, **make sure to review the Secure your datasection.
**
https://firebase.google.com/
*

With that our firebase should look like this with default Test rules which we will change later:

Enabling Authentication

Now, similarly, click on the Authentication tab in the sidebar or directly go to this link

Click on “Get Started” and you will be presented with the “Get started with Firebase Auth by adding your first sign-in method” Screen. Let’s Add the Providers we need

Adding Email/Password Provider

Just click on the Email/Password Provider And further, click on the Email/Password check box and click on the Save button

Adding Google Provider

Then just add a new provider and in the Additional providers, column click on “Google” provider. And further, click on the Google check box and change the following settings. Finally, click on the “Save” button

When you got the following 2 statuses enabled, we are ready to go!

And with that ig we are finished setting up Firebase. Now, let’s makeUp the Context API. :)

Creating out Firebase Context API For Basic Authentication Functions

If you don’t know about context API, I recommend checking about them more. Here is more basic meaning from the docs

Context provides a way to share values like these between components without having to explicitly pass a prop through every level of the tree.Context is designed to share data that can be considered “global” for a tree of React components, such as the current authenticated user, theme, or preferred language

So, let’s move ahead further without wasting any more time. In the Src folder, create a “Context” folder and create the context file with maybe a better file name unlike me ; — ;

Basic UserAuthContext File with Basic Login Functions

import React, { useContext, useState, useEffect } from "react";
import {
  createUserWithEmailAndPassword,
  signInWithEmailAndPassword,
  onAuthStateChanged,
  signOut,
  GoogleAuthProvider,
  signInWithPopup,
} from "firebase/auth";
import { doc, setDoc } from "firebase/firestore";
import { db, auth } from "../Config/FirebaseConfig";

const AuthContext = React.createContext();

export const useAuth = () => {
  const auth = useContext(AuthContext);
  return { ...auth, isAuthenticated: auth.CurrentUser != null };
};

export function AuthProvider({ children }) {
  const [CurrentUser, setCurrentUser] = useState();
  const [loading, setloading] = useState(true);

  useEffect(() => {
    const unsuscribe = onAuthStateChanged(auth, (user) => {
      console.log(user);
      setCurrentUser(user);
      setloading(false);
    });

    return unsuscribe;
  }, []);

  const SignupUser = (email, password, name) => {
    return createUserWithEmailAndPassword(auth, email, password).then(
      (resp) => {
        if (resp.user) {
          CreateFireStoreUser(
            resp.user,
            name,
            "https://cdn-icons-png.flaticon.com/512/149/149071.png"
          );
        }
      }
    );
  };

  const CreateFireStoreUser = (user, name, profileImage) => {
    const UsersRef = doc(db, "Users", user.uid);
    setDoc(UsersRef, {
      name: name,
      profileImage: profileImage,
      initials: name[0] + name[name.length - 1],
      Suscribers: [],
    }).then(() => {
      console.log("added User");
    });
  };

  const LogInUser = (email, password) => {
    return signInWithEmailAndPassword(auth, email, password);
  };

  const SignInWithGoogle = () => {
    const provider = new GoogleAuthProvider();
    return signInWithPopup(auth, provider);
  };

  const logout = () => {
    return signOut(auth);
  };

  const value = {
    CurrentUser,
    SignupUser,
    LogInUser,
    logout,
    ResetPassword,
    CreateFireStoreUser,
  };

  return (
    <AuthContext.Provider value={value}>
      {!loading && children}
    </AuthContext.Provider>
  );
}

Yup, we have Our Basic Context File ready for simple and basic functions like Signup/login(With Email Password), creating a Firestore user when the user is signing up, etc. The above code is quite self-explanatory ig

Adding More Functionalities to our Authentication System apart from basic things

So let’s move on my adding functions like Email verification, password reset, etc. For that, In the Authentication section, click on the templates tab Or directly go to this link

Email address verification

Now, let’s work on all the 3 things on the sidebar. First, we have the Email address verification thing. Like below ⬇️⬇️⬇️

Now, Click on the edit button in and change the things you want. Like ‘sender name’ and ‘from’ settings. In the message section, you see this weird line right?

http://localhost:3000/UserActions?mode=action&oobCode=code

For all the user management actions such as updating a user’s email address and resetting a user’s password, we send an email to the user’s email duh. So, By default, user management emails link to the default action handler, which is a web page hosted at a URL in your project’s Firebase Hosting domain. Firebase adds several query parameters to your action handler URL when it generates user management emails. For example:

https://example.com/usermgmt?mode=resetPassword&oobCode=ABC123&apiKey=AIzaSy...&lang=fr

For more info, you can read about it here ⬇️ :)

https://firebase.google.com/docs/auth/custom-email-handler

So, let’s change the default action handler. It’s not that difficult ;). In the bottom section, you would be able to see a text with “Customize action URL” and there put the following value.

http://localhost:3000/UserActions

Don’t worry if you are confused right now, when we will start implementing these features, you will get more clear ;))

Password reset AND Email address change Settings

There is nothing more to do in these settings. Just change the text you want etc but idk we have nothing more left to do here.

OOF OOF, that whole section was a mouthful, It might look boring a bit but nvm we are finished and now we can close this site ❤️❤️😳

Complete UserAuthContext File with All Login Functions

Now let’s complete our UserAuthContext file. This will be the complete file. It’s not that complicated ig, Just 1–2 lines of code with some settings to pass and we have the functionality running

import React, { useContext, useState, useEffect } from "react";
import {
  createUserWithEmailAndPassword,
  signInWithEmailAndPassword,
  onAuthStateChanged,
  signOut,
  GoogleAuthProvider,
  signInWithPopup,
  sendPasswordResetEmail,
  confirmPasswordReset,
  sendSignInLinkToEmail,
  isSignInWithEmailLink,
  signInWithEmailLink,
} from "firebase/auth";
import { doc, setDoc } from "firebase/firestore";
import { db, auth } from "../Config/FirebaseConfig";

const AuthContext = React.createContext();

export const useAuth = () => {
  const auth = useContext(AuthContext);
  return { ...auth, isAuthenticated: auth.CurrentUser != null };
};

export function AuthProvider({ children }) {
  const [CurrentUser, setCurrentUser] = useState();
  const [loading, setloading] = useState(true);

  useEffect(() => {
    const unsuscribe = onAuthStateChanged(auth, (user) => {
      console.log(user);
      setCurrentUser(user);
      setloading(false);
    });

    return unsuscribe;
  }, []);

  const SignupUser = (email, password, name) => {
    return createUserWithEmailAndPassword(auth, email, password).then(
      (resp) => {
        if (resp.user) {
          CreateFireStoreUser(
            resp.user,
            name,
            "https://cdn-icons-png.flaticon.com/512/149/149071.png"
          );
        }
      }
    );
  };

  const CreateFireStoreUser = (user, name, profileImage) => {
    const UsersRef = doc(db, "Users", user.uid);
    setDoc(UsersRef, {
      name: name,
      profileImage: profileImage,
      initials: name[0] + name[name.length - 1],
      Suscribers: [],
    }).then(() => {
      console.log("added User");
    });
  };

  const LogInUser = (email, password) => {
    return signInWithEmailAndPassword(auth, email, password);
  };

  const SendEmailVerification = () => {
    const actionCodeSettings = {
      url: "http://localhost:3000", // Redirect to this url when we are succesfull 
      handleCodeInApp: true,
    };
    return sendSignInLinkToEmail(auth, CurrentUser.email, actionCodeSettings);
  };

  const VerifyEmailLink = () => {
    if (isSignInWithEmailLink(auth, window.location.href)) {
      return signInWithEmailLink(auth, CurrentUser.email);
    }
  };

  const SignInWithGoogle = () => {
    const provider = new GoogleAuthProvider();
    return signInWithPopup(auth, provider);
  };

  const forgotPassword = (email) => {
    return sendPasswordResetEmail(auth, email, {
      url: "http://localhost:3000/login",
    });
  };

  const ResetPassword = (oobcode, newPasword) => {
    return confirmPasswordReset(auth, oobcode, newPasword);
  };

  const logout = () => {
    return signOut(auth);
  };

  const value = {
    CurrentUser,
    SignupUser,
    LogInUser,
    logout,
    SignInWithGoogle,
    forgotPassword,
    ResetPassword,
    CreateFireStoreUser,
    SendEmailVerification,
    VerifyEmailLink,
  };

  return (
    <AuthContext.Provider value={value}>
      {!loading && children}
    </AuthContext.Provider>
  );
}

Annd with that, we have completed our Context API file too! Nice :000000. Well, the article went a bit long today but don’t worry we have some output :))

Now in the next part, we will complete the Authentication system with all the screens. We are moving slowly but we will soon be able to see some results. I bet.

I hope you like this part and I will be back with another part soon! Till then

Till then stay safe, stay healthy

Thank you


Also Published Here


Written by decodebuzzing | Hi folks! I am Harsh Vardhan Jain, 14 years old and I aim to learn together and share my thoughts in the coding world.
Published by HackerNoon on 2022/06/27