@@ -158,7 +161,7 @@ export default function Post() {
disabled
>
{ handleSubmission() }}>
- submit
+ Post
*some photos taken on an iphone (.heic) may not work. if there is an error try taking a screenshot of the image and uploading that instead.
diff --git a/client/pages/post/post-with-camera/index.tsx b/client/pages/post/post-with-camera/index.tsx
new file mode 100644
index 0000000..783862d
--- /dev/null
+++ b/client/pages/post/post-with-camera/index.tsx
@@ -0,0 +1,202 @@
+import { useState, useRef, useEffect } from "react";
+import s from './postcamera.module.scss';
+import useCheck from "@/utils/check";
+import { useRouter } from "next/router";
+
+export default function Post() {
+ useCheck();
+ const router = useRouter();
+
+ const [loading, setLoading] = useState
(false);
+ const [failure, setFailure] = useState("");
+ const [success, setSuccess] = useState("");
+
+ const [caption, setCaption] = useState('');
+ const [primaryBase64, setPrimaryBase64] = useState('');
+ const [secondaryBase64, setSecondaryBase64] = useState('');
+ const [cameraActive, setCameraActive] = useState(false);
+ const [isPrimaryCaptured, setIsPrimaryCaptured] = useState(false);
+ const [isSecondaryCaptured, setIsSecondaryCaptured] = useState(false);
+ const [selectedCameraId, setSelectedCameraId] = useState(null);
+ const [currentCapture, setCurrentCapture] = useState<'primary' | 'secondary' | null>(null);
+
+ const videoRef = useRef(null);
+ const canvasRef = useRef(null);
+
+ useEffect(() => {
+ let stream: MediaStream | null = null;
+
+ const getMediaStream = async () => {
+ try {
+ const constraints: MediaStreamConstraints = {
+ video: { deviceId: selectedCameraId ? { exact: selectedCameraId } : undefined }
+ };
+ stream = await navigator.mediaDevices.getUserMedia(constraints);
+ if (videoRef.current) {
+ videoRef.current.srcObject = stream;
+ videoRef.current.play();
+ }
+ } catch (err) {
+ console.error("Error accessing the camera: ", err);
+ }
+ };
+
+ if (cameraActive) {
+ getMediaStream();
+ }
+
+ return () => {
+ if (stream) {
+ stream.getTracks().forEach(track => track.stop());
+ }
+ };
+ }, [cameraActive, selectedCameraId]);
+
+ useEffect(() => {
+ const getCameraList = async () => {
+ const devices = await navigator.mediaDevices.enumerateDevices();
+ const videoDevices = devices.filter(device => device.kind === 'videoinput');
+ if (videoDevices.length > 0) {
+ setSelectedCameraId(videoDevices[0].deviceId); // Default to the first camera
+ }
+ };
+
+ getCameraList();
+ }, []);
+
+ const captureImage = () => {
+ if (canvasRef.current && videoRef.current) {
+ const context = canvasRef.current.getContext('2d');
+ if (context) {
+ canvasRef.current.width = 1500;
+ canvasRef.current.height = 2000;
+ context.drawImage(videoRef.current, 0, 0, 1500, 2000);
+ const imageBase64 = canvasRef.current.toDataURL('image/png');
+
+ if (currentCapture === 'primary') {
+ setPrimaryBase64(imageBase64);
+ setIsPrimaryCaptured(true);
+ } else if (currentCapture === 'secondary') {
+ setSecondaryBase64(imageBase64);
+ setIsSecondaryCaptured(true);
+ }
+
+ stopCamera();
+ }
+ }
+ };
+
+ const stopCamera = () => {
+ const stream = videoRef.current?.srcObject as MediaStream;
+ if (stream) {
+ stream.getTracks().forEach(track => track.stop());
+ }
+ setCameraActive(false);
+ };
+
+ const handleCameraToggle = async () => {
+ const devices = await navigator.mediaDevices.enumerateDevices();
+ const videoDevices = devices.filter(device => device.kind === 'videoinput');
+ if (videoDevices.length > 0) {
+ const currentIndex = videoDevices.findIndex(device => device.deviceId === selectedCameraId);
+ const nextIndex = (currentIndex + 1) % videoDevices.length;
+ setSelectedCameraId(videoDevices[nextIndex].deviceId);
+ }
+ };
+
+ const handleCameraModalOpen = (type: 'primary' | 'secondary') => {
+ setCurrentCapture(type);
+ setIsPrimaryCaptured(type === 'primary' ? false : isPrimaryCaptured);
+ setIsSecondaryCaptured(type === 'secondary' ? false : isSecondaryCaptured);
+ setCameraActive(true);
+ };
+
+ const handleSubmission = () => {
+ setLoading(true);
+
+ const authorization_token = localStorage.getItem("token");
+
+ fetch("/api/add/post", {
+ method: "POST",
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify({
+ primaryb64: primaryBase64,
+ secondaryb64: secondaryBase64,
+ caption: caption,
+ token: authorization_token
+ })
+ })
+ .then(response => {
+ if (response.ok) {
+ setLoading(false);
+ setSuccess("Successfully posted!");
+ setTimeout(() => { setSuccess(""); router.push("/feed") }, 3000);
+ } else {
+ throw new Error("Error: " + response.statusText);
+ }
+ })
+ .catch(error => {
+ console.log(error);
+ setLoading(false);
+ setFailure(error.message);
+ setTimeout(() => { setFailure("") }, 5000);
+ });
+ };
+
+ return (
+
+
+
+
+
+ {isPrimaryCaptured && (
+
+

+
+ )}
+
+
+
+ {isSecondaryCaptured && (
+
+

+
+ )}
+
+
+
setCaption(txt.target.value)}
+ disabled
+ />
+
Post
+
+ *The photos taken here won't look perfect in the app for everyone else, but it's close.
+
+ {failure &&
{failure}
}
+ {loading &&
loading...
}
+ {success &&
{success}
}
+
+ {cameraActive && (
+
+
+
+
+
+
+
+
+
+ )}
+
+ );
+}
diff --git a/client/pages/post/post-with-camera/postcamera.module.scss b/client/pages/post/post-with-camera/postcamera.module.scss
new file mode 100644
index 0000000..d27dabb
--- /dev/null
+++ b/client/pages/post/post-with-camera/postcamera.module.scss
@@ -0,0 +1,183 @@
+@use "../../../styles/common.scss" as c;
+
+.images {
+ display: flex;
+ flex-wrap: wrap;
+ .img {
+ position: relative;
+ width: 300px;
+ min-width: 300px;
+ height: 400px;
+ border: 2px solid white;
+ margin-right: 18px;
+ border-radius: 12px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ margin-bottom: 14px;
+ input[type=file] {
+ display: none;
+ }
+ .upload {
+ position: absolute;
+ border: 2px solid #fff;
+ display: inline-block;
+ cursor: pointer;
+ border-radius: 12px;
+ padding-left: 14px; padding-right: 14px;
+ height: 40px;
+ @include c.center();
+ background-color: rgb(0, 0, 0, 0.5);
+ color: white;
+ }
+ .sub {
+ height: 100%;
+ width: 100%;
+ img {
+ height: 100%;
+ width: 100%;
+ object-fit: cover;
+ border-radius: 12px;
+ }
+ .data {
+ position: absolute;
+ top: 0px;
+ }
+ }
+ }
+}
+.caption {
+ padding-left: 14px; padding-right: 14px;
+ width: 100%;
+ min-width: 300px;
+ max-width: 620px;
+ height: 40px;
+ border-radius: 12px;
+ background-color: white;
+ color: black;
+
+ @media screen and (max-width: 675px) {
+ margin-left: 0px !important;
+ width: 300px !important;
+ }
+}
+
+.switchMode {
+ border: 2px solid #fff;
+ display: inline-block;
+ cursor: pointer;
+ border-radius: 12px;
+ padding-left: 14px; padding-right: 14px;
+ height: 40px;
+ @include c.center();
+ background-color: rgb(0, 0, 0, 0.5);
+ color: white;
+ }
+
+.submit {
+ margin-top: 14px;
+ cursor: pointer;
+ @include c.center();
+ border: 2px solid white;
+ min-width: 144px;
+ width: 144px;
+ height: 40px;
+ border-radius: 12px;
+ padding-left: 14px; padding-right: 14px;
+}
+.info {
+ max-width: 600px;
+ margin-top: 12px;
+ color: white;
+ font-size: 12px;
+}
+.failure {
+ color: rgb(165, 0, 0);
+ font-size: 14px;
+ margin-top: 12px;
+}
+.success {
+ color: cyan;
+ font-size: 14px;
+ margin-top: 12px;
+}
+.loading {
+ margin-top: 12px;
+ color: green;
+ font-size: 14px;
+}
+.video {
+ width: 100%;
+ height: auto;
+ display: block;
+}
+
+.canvas {
+ display: none;
+}
+
+.captureButton {
+ background-color: #007bff;
+ color: #fff;
+ padding: 10px 20px;
+ text-align: center;
+ cursor: pointer;
+ margin-top: 10px;
+ margin-right: 10px;
+ border: none;
+ border-radius: 5px;
+}
+
+.swapButton {
+ background-color: grey;
+ color: #fff;
+ padding: 10px 20px;
+ text-align: center;
+ cursor: pointer;
+ margin-top: 10px;
+ margin-right: 10px;
+ border: none;
+ border-radius: 5px;
+}
+
+.closeButton {
+ background-color: maroon;
+ color: #fff;
+ padding: 10px 20px;
+ text-align: center;
+ cursor: pointer;
+ margin-top: 10px;
+ margin-right: 10px;
+ border: none;
+ border-radius: 5px;
+}
+
+
+.cameraModal {
+ position: fixed;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ background: rgba(0, 0, 0, 0.8);
+ padding: 20px;
+ border-radius: 10px;
+ z-index: 1000;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+.cameraControls {
+ display: flex;
+ justify-content: center;
+ margin-top: 20px;
+}
+
+.preview {
+ margin-top: 10px;
+
+ img {
+ max-width: 100%;
+ height: auto;
+ }
+}
diff --git a/client/pages/post/post.module.scss b/client/pages/post/post.module.scss
index 52c2625..3c68b01 100644
--- a/client/pages/post/post.module.scss
+++ b/client/pages/post/post.module.scss
@@ -91,4 +91,16 @@
margin-top: 12px;
color: green;
font-size: 14px;
+}
+
+.switchMode {
+ border: 2px solid #fff;
+ display: inline-block;
+ cursor: pointer;
+ border-radius: 12px;
+ padding-left: 14px; padding-right: 14px;
+ height: 40px;
+ @include c.center();
+ background-color: rgb(0, 0, 0, 0.5);
+ color: white;
}
\ No newline at end of file
From e9ce56db59447dc3e2438ba43fc014396f5d5744 Mon Sep 17 00:00:00 2001
From: Sean <83432253+MegaTheLEGEND@users.noreply.github.com>
Date: Sun, 18 Aug 2024 02:51:04 -0700
Subject: [PATCH 2/2] fix button margin
---
client/pages/post/post-with-camera/postcamera.module.scss | 1 +
client/pages/post/post.module.scss | 2 ++
2 files changed, 3 insertions(+)
diff --git a/client/pages/post/post-with-camera/postcamera.module.scss b/client/pages/post/post-with-camera/postcamera.module.scss
index d27dabb..a529225 100644
--- a/client/pages/post/post-with-camera/postcamera.module.scss
+++ b/client/pages/post/post-with-camera/postcamera.module.scss
@@ -72,6 +72,7 @@
@include c.center();
background-color: rgb(0, 0, 0, 0.5);
color: white;
+ margin-bottom: 14px;
}
.submit {
diff --git a/client/pages/post/post.module.scss b/client/pages/post/post.module.scss
index 3c68b01..228d9f5 100644
--- a/client/pages/post/post.module.scss
+++ b/client/pages/post/post.module.scss
@@ -103,4 +103,6 @@
@include c.center();
background-color: rgb(0, 0, 0, 0.5);
color: white;
+ margin-bottom: 14px;
+
}
\ No newline at end of file