Add Ionic Capacitor Support (Cross Platform Native) (#62)
@@ -1,3 +1,6 @@
|
||||
# Android Build
|
||||
/frontend-next/android
|
||||
|
||||
# Firebase Stuff
|
||||
firebase-admin-key.json
|
||||
firebase*.json
|
||||
|
||||
@@ -19,7 +19,7 @@ npm install
|
||||
|
||||
npm run build
|
||||
|
||||
npm run dev
|
||||
npm run start
|
||||
|
||||
then navigating to:
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import { CapacitorConfig } from '@capacitor/cli';
|
||||
|
||||
const config: CapacitorConfig = {
|
||||
appId: 'com.jacsn.chatmaps',
|
||||
appName: 'ChatMaps',
|
||||
webDir: 'out',
|
||||
server: {
|
||||
androidScheme: 'https'
|
||||
}
|
||||
};
|
||||
|
||||
export default config;
|
||||
|
After Width: | Height: | Size: 4.6 KiB |
|
After Width: | Height: | Size: 6.8 KiB |
|
After Width: | Height: | Size: 9.5 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
@@ -1,4 +1,4 @@
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {};
|
||||
const nextConfig = {output: 'export'};
|
||||
|
||||
export default nextConfig;
|
||||
|
||||
@@ -5,10 +5,13 @@
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"start": "npx serve@latest out",
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@capacitor/android": "^5.7.4",
|
||||
"@capacitor/core": "^5.7.4",
|
||||
"@capacitor/geolocation": "^5.0.7",
|
||||
"@emotion/react": "^11.11.4",
|
||||
"@emotion/styled": "^11.11.5",
|
||||
"@headlessui/react": "^1.7.18",
|
||||
@@ -21,10 +24,11 @@
|
||||
"react-beforeunload": "^2.6.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-firebase-hooks": "^5.1.1",
|
||||
"react-geolocated": "^4.1.2",
|
||||
"react-hook-form": "^7.50.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@capacitor/assets": "^3.0.5",
|
||||
"@capacitor/cli": "^5.7.4",
|
||||
"autoprefixer": "^10.0.1",
|
||||
"eslint": "^8",
|
||||
"eslint-config-next": "14.1.0",
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"icons": [
|
||||
{
|
||||
"src": "../icons/icon-48.webp",
|
||||
"type": "image/png",
|
||||
"sizes": "48x48",
|
||||
"purpose": "any maskable"
|
||||
},
|
||||
{
|
||||
"src": "../icons/icon-72.webp",
|
||||
"type": "image/png",
|
||||
"sizes": "72x72",
|
||||
"purpose": "any maskable"
|
||||
},
|
||||
{
|
||||
"src": "../icons/icon-96.webp",
|
||||
"type": "image/png",
|
||||
"sizes": "96x96",
|
||||
"purpose": "any maskable"
|
||||
},
|
||||
{
|
||||
"src": "../icons/icon-128.webp",
|
||||
"type": "image/png",
|
||||
"sizes": "128x128",
|
||||
"purpose": "any maskable"
|
||||
},
|
||||
{
|
||||
"src": "../icons/icon-192.webp",
|
||||
"type": "image/png",
|
||||
"sizes": "192x192",
|
||||
"purpose": "any maskable"
|
||||
},
|
||||
{
|
||||
"src": "../icons/icon-256.webp",
|
||||
"type": "image/png",
|
||||
"sizes": "256x256",
|
||||
"purpose": "any maskable"
|
||||
},
|
||||
{
|
||||
"src": "../icons/icon-512.webp",
|
||||
"type": "image/png",
|
||||
"sizes": "512x512",
|
||||
"purpose": "any maskable"
|
||||
}
|
||||
],
|
||||
"background_color": "#ffffff"
|
||||
}
|
||||
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 173 KiB |
|
After Width: | Height: | Size: 173 KiB |
@@ -3,7 +3,6 @@
|
||||
import { useState, useEffect } from "react";
|
||||
|
||||
// Dependencies
|
||||
import { useGeolocated } from "react-geolocated";
|
||||
import Drawer from '@mui/material/Drawer';
|
||||
|
||||
// Firebase Imports
|
||||
@@ -17,6 +16,9 @@ import { HomePage } from "../../components/app/page/home";
|
||||
import { Sidebar } from "../../components/app/sidebar/home";
|
||||
import {useWindowSize} from "../../components/app/datatypes";
|
||||
|
||||
// Capacitor Import
|
||||
import { Geolocation } from '@capacitor/geolocation';
|
||||
|
||||
/**
|
||||
* Contains most everything for the app homepage
|
||||
* @returns {Object} Home Page
|
||||
@@ -27,6 +29,7 @@ function Home() {
|
||||
const [loadingLoc, setLoadingLoc] = useState(true); // location variable loading, true = loading, false = finished loading
|
||||
const [authUser] = useAuthState(auth) // auth user object (used to obtain other user object)
|
||||
const [drawerOpen, setDrawerOpen] = useState(true); // drawer open state
|
||||
const [coords, setCoords] = useState(null)
|
||||
|
||||
var windowSize = useWindowSize()
|
||||
useEffect(() => {
|
||||
@@ -48,23 +51,17 @@ function Home() {
|
||||
window.location.href = "/onboarding";
|
||||
}
|
||||
});
|
||||
} else {
|
||||
window.location.href = "/login"
|
||||
}
|
||||
}, [authUser])
|
||||
|
||||
// Gets current location
|
||||
const { coords } = useGeolocated({
|
||||
positionOptions: {
|
||||
enableHighAccuracy: false,
|
||||
},
|
||||
userDecisionTimeout: 5000,
|
||||
});
|
||||
|
||||
// If theres a location, go ahead and show location based stuff
|
||||
useEffect(() => {
|
||||
if (coords) {
|
||||
setLoadingLoc(false);
|
||||
}
|
||||
}, [coords])
|
||||
Geolocation.getCurrentPosition().then((position) => {
|
||||
setCoords(position.coords);
|
||||
setLoadingLoc(false);
|
||||
});
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="overflow-hidden h-dvh">
|
||||
|
||||
@@ -47,6 +47,8 @@ function Chat() {
|
||||
window.location.href = "/onboarding";
|
||||
}
|
||||
});
|
||||
} else {
|
||||
window.location.href = "/login"
|
||||
}
|
||||
}, [authUser])
|
||||
|
||||
|
||||
@@ -3,9 +3,11 @@ import { useState, useEffect } from "react";
|
||||
import Link from "next/link"
|
||||
import { auth, database } from "../../firebase-config";
|
||||
import { ref, get } from "firebase/database";
|
||||
import { useGeolocated } from "react-geolocated";
|
||||
import { onAuthStateChanged } from "firebase/auth";
|
||||
|
||||
// Capacitor Import
|
||||
import { Geolocation } from '@capacitor/geolocation';
|
||||
|
||||
/**
|
||||
* Home Page
|
||||
* @returns {Object} - Home Page
|
||||
@@ -14,10 +16,11 @@ function Home() {
|
||||
const [isLoadingLoc, setLoadingLoc] = useState(true); // is location loading?
|
||||
const [roomCount, setRoomCount] = useState(null); // local room count
|
||||
const [isAuthenticated, setAuth] = useState(false); // is user authenticated?
|
||||
const [coords, setCoords] = useState(null)
|
||||
|
||||
// Authentication
|
||||
useEffect(() => {
|
||||
onAuthStateChanged(auth, (user) => {
|
||||
onAuthStateChanged(auth, async (user) => {
|
||||
if (user) {
|
||||
setAuth(true);
|
||||
} else {
|
||||
@@ -26,13 +29,12 @@ function Home() {
|
||||
});
|
||||
}, []);
|
||||
|
||||
// Grab Location
|
||||
const { coords } = useGeolocated({
|
||||
positionOptions: {
|
||||
enableHighAccuracy: false,
|
||||
},
|
||||
userDecisionTimeout: 5000,
|
||||
});
|
||||
useEffect(() => {
|
||||
Geolocation.getCurrentPosition().then((position) => {
|
||||
setCoords(position.coords);
|
||||
setLoadingLoc(false);
|
||||
});
|
||||
}, [])
|
||||
|
||||
// Update room count on location fix
|
||||
useEffect(() => {
|
||||
|
||||
@@ -35,7 +35,6 @@ function UserProfile() {
|
||||
|
||||
// Authentication
|
||||
useEffect(() => {
|
||||
|
||||
onAuthStateChanged(auth, (user) => {
|
||||
const searchParams = new URLSearchParams(document.location.search);
|
||||
var userUID = searchParams.get("uid")
|
||||
|
||||
@@ -102,8 +102,7 @@ export function Chat({ chatObj }) {
|
||||
<div>
|
||||
<span style={{ color: userColors[generateColor(chatObj.user)] }}>
|
||||
<Link href={`/user?uid=${chatObj.uid}`}
|
||||
className="hover:font-bold cursor-pointer"
|
||||
target="_blank">
|
||||
className="hover:font-bold cursor-pointer">
|
||||
{chatObj.user}
|
||||
</Link>
|
||||
</span>
|
||||
@@ -128,8 +127,7 @@ export function SystemMessage({ chatObj }) {
|
||||
<div className="text-[#d1d1d1]">
|
||||
<span style={{ color: userColors[generateColor(chatObj.user)] }}>
|
||||
<Link href={`/user?uid=${chatObj.uid}`}
|
||||
className="hover:font-bold cursor-pointer"
|
||||
target="_blank">
|
||||
className="hover:font-bold cursor-pointer">
|
||||
{chatObj.user}
|
||||
</Link>
|
||||
</span>{" "}
|
||||
@@ -149,7 +147,7 @@ export function SystemMessage({ chatObj }) {
|
||||
*/
|
||||
export function Member({ memberObj }) {
|
||||
return (
|
||||
<Link href={"/user?uid=" + memberObj.uid} target="_blank">
|
||||
<Link href={"/user?uid=" + memberObj.uid}>
|
||||
<div className="cursor-pointer g-[aliceblue] rounded-lg m-3 shadow-xl p-2">
|
||||
{memberObj.username}
|
||||
</div>
|
||||
|
||||
@@ -8,6 +8,9 @@ import { database } from "../../../../firebase-config";
|
||||
// Component Imports
|
||||
import { Chat, SystemMessage } from "../datatypes";
|
||||
|
||||
// Icons
|
||||
import SendIcon from '@mui/icons-material/Send';
|
||||
|
||||
/**
|
||||
* Chat Room Component
|
||||
* @prop {JSON} roomObj - Room Object
|
||||
@@ -75,9 +78,9 @@ export function ChatRoom({ roomObj, user }) {
|
||||
onSubmit={handleSubmit(sendMessage)}
|
||||
control={control}
|
||||
>
|
||||
<div className="width-[100%] grid grid-cols-6">
|
||||
<input type="text" {...register("message")} placeholder="Enter message" className="col-span-5 border-[0px] mt-[8px] mb-[8px]" />
|
||||
<button className="p-2 cursor-pointer bg-cyan-500 text-white font-bold rounded-full mr-5 w-[60px]">Send</button>
|
||||
<div className="width-[100%] grid grid-cols-6 pr-5 pt-1">
|
||||
<input type="text" {...register("message")} placeholder="Enter message..." className="col-span-5 border-[0px]" />
|
||||
<button className="p-2 cursor-pointer bg-cyan-500 text-white font-bold rounded-full mr-5 w-[100%]"><SendIcon/></button>
|
||||
</div>
|
||||
</Form>
|
||||
</div>
|
||||
|
||||