React Native Android- App crashing in Vivo IQOO neo7 android14 on lunching the app

java.lang.ExceptionInInitializerError
at com.vivo.vspa.promotion.FrameRequestManager.(FrameRequestManager.java:54)
at android.view.VivoViewRootImplImpl.(VivoViewRootImplImpl.java:121)
at com.vivo.VivoSystemFrameworkFactoryImpl.createVivoViewRootImpl(VivoSystemFrameworkFactoryImpl.java:422)
at android.view.ViewRootImpl.(ViewRootImpl.java:1172)
at android.view.ViewRootImpl.(ViewRootImpl.java:1089)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:423)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:164)
at android.app.Dialog.show(Dialog.java:431)
at org.devio.rn.splashscreen.SplashScreen$1.run(SplashScreen.java:39)
at android.app.Activity.runOnUiThread(Activity.java:7927)
at org.devio.rn.splashscreen.SplashScreen.show(SplashScreen.java:28)
at org.devio.rn.splashscreen.SplashScreen.show(SplashScreen.java:52)
at com.truworth.wellnesscorner.ui.mainapp.HomeDashBoardActivity.onCreate(HomeDashBoardActivity.kt:117)
at android.app.Activity.performCreate(Activity.java:8937)
at android.app.Activity.performCreate(Activity.java:8901)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1456)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:4246)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4418)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:139)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:96)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2820)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:328)
at android.app.ActivityThread.main(ActivityThread.java:9144)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:586)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method ‘java.lang.String android.content.Context.getPackageName()’ on a null object reference
at android.content.ContextWrapper.getPackageName(ContextWrapper.java:177)
at com.vivo.vspa.promotion.SlidingRecognitionInfo.getSlideRecognitionMode(SlidingRecognitionInfo.java:223)
at com.vivo.vspa.promotion.SlidingRecognitionInfo.setComponentCallbacks(SlidingRecognitionInfo.java:608)
at com.vivo.vspa.promotion.SlidingRecognitionInfo.(SlidingRecognitionInfo.java:122)

Updated the app all dependancies

JS history.replaceState() error with multiple dynamic parameters

For giving the user the opportunity to navigate back to a filtered search result page I use history.replaceState() to set the correct url.

I do so everytime the ajax script is called to change the result page of the search by sending the new, correct url with the result set.

I then fetch the well formatted url from that result and call the following method:

function makeNavigatableBackUrl(url) {
  history.replaceState({}, "", url);
}

I hand over a string like this:
https://www.domain.de/?cmd=category&activePage=1&filter[156]=156&filter[170]=170&language=de

But what I receive is:

https://www.domain.de/?cmd=category&activePage=1&filter[156]=156&filter[170]=170&language=de

When the user navigates back to this url, the $_GET array is resolved in PHP like this:

array (size=4)
'cmd' => string 'category' (length=8)
'activePage' => string '1' (length=1)
'amp;filter' => 
  array (size=2)
  156 => string '156' (length=3)
  170 => string '170' (length=3)
'amp;language' => string 'de' (length=2)

Where I expect it to be

array (size=4)
'cmd' => string 'category' (length=8)
'activePage' => string '1' (length=1)
'filter' => 
  array (size=2)
  156 => string '156' (length=3)
  170 => string '170' (length=3)
'language' => string 'de' (length=2)

I asume I could easily work through the $_GET array to get rid of “amp;” in the keys, but is there a better solution to it? How can I put a valid url in history.replaceState({}, “”, url); instead?

How to add chatting real time to website using socket.io and nodejs

I’m creating a public website where users input their information, which is then stored in MongoDB. Users can click a “find” button to see a list of similar users. They can choose to connect with another user, which triggers an invitation. If accepted, a real-time chat box should appear for them to communicate. (Html,css,js, nodejs, mongodb)

This is index.html ( from <body ):

<form id="teamFormationForm">

        <label for="name">Name:</label>
        <input type="text" id="name" name="name" required><br>
       
        <label for="studentID">Student ID:</label>
        <input type="text" id="studentID" name="studentID" pattern="[sS][0-9]{7}"><br>
       
        <label for="mobile">Mobile Phone Number:</label>
        <input type="text" id="mobile" name="mobile" required><br>
       
        <label for="universityEmail">University Email:</label>
        <input type="email" id="universityEmail" name="universityEmail"><br>
       
        <label for="interests">Interests:</label>
        <textarea id="interests" name="interests" rows="4" cols="50" required></textarea><br>
       
        <label for="overallGPA">Current Overall GPA:</label>
        <input type="number" id="overallGPA" name="overallGPA" min="0" max="4" step="0.1" required>
       
        <div id="courses">
            <!-- Initial course box, hidden by default -->
            <div class="course" style="display: none;">
                <label for="courseTitle">Course:</label>
                <input type="text" class="courseTitle" name="courseTitle[]">
               
                <label for="desiredGPA">Desired GPA:</label>
                <select class="desiredGPA" name="desiredGPA[]">
                    <option value="HD">HD (80-100)</option>
                    <option value="DI">DI (70-79)</option>
                    <option value="CR">CR (60-69)</option>
                    <option value="PA">PA (50-59)</option>
                </select>

        <button type="button" id="addCourse">Add Course</button><br>
        <button type="submit">Submit</button>
        <button id="findTeammateBtn">Find Teammate Now</button>
        <ul id="resultList"></ul> <!-- Add the resultList here -->
    </form>

    <script src="/socket.io/socket.io.js"></script>
    <script src="script.js"></script>


    <script>


    // Function to handle connecting with a teammate
    function connectWithTeammate(studentID) {
        // Emit the 'connectWithTeammate' event to the server with the student ID
        socket.emit('connectWithTeammate', { studentID });
    }


    // Add event listener to the result list for connecting with teammates
    document.getElementById('resultList').addEventListener('click', function(event) {
        if (event.target.classList.contains('connectButton')) {
            var studentID = event.target.dataset.studentId;
            connectWithTeammate(studentID);
        }
    });
    </script>

This is script.js (client-side):

document.addEventListener("DOMContentLoaded", function() {
    const addCourseBtn = document.getElementById("addCourse");
    const coursesContainer = document.getElementById("courses");


    addCourseBtn.addEventListener("click", function() {
        addCourse();
    });


    function addCourse() {
        const courseDiv = document.createElement("div");
        courseDiv.classList.add("course");


        const courseFields = `
            <label for="courseTitle">Course:</label>
            <input type="text" class="courseTitle" name="courseTitle[]" required>
           
            <label for="desiredGPA">Desired GPA:</label>
            <select class="desiredGPA" name="desiredGPA[]">
            </select>
   
            <label for="notes">Notes:</label>
            <textarea class="notes" name="notes[]" rows="2" cols="30"></textarea>
   
            <button type="button" class="removeCourse">Remove Course</button>
        `;


        courseDiv.innerHTML = courseFields;


        coursesContainer.appendChild(courseDiv);


        const courseTitleInput = courseDiv.querySelector(".courseTitle");
        const dropdownMenu = document.createElement("div");
        dropdownMenu.classList.add("dropdown-menu");
        courseTitleInput.parentNode.insertBefore(dropdownMenu, courseTitleInput.nextSibling);


        const removeCourseBtn = courseDiv.querySelector(".removeCourse");
        removeCourseBtn.addEventListener("click", function() {
            coursesContainer.removeChild(courseDiv);
        });


        fetch("courses.json")
            .then(response => {
                if (!response.ok) {
                    throw new Error("Network response was not ok");
                }
                return response.json();
            })
            .then(data => {
                const courses = Object.values(data);
                courseTitleInput.addEventListener("input", function() {
                    const userInput = courseTitleInput.value.toLowerCase();
                    const filteredCourses = courses.filter(course => {
                        return course &&
                            course["COURSE CODE"] &&
                            course["COURSE TITLE"] &&
                            (course["COURSE CODE"].toLowerCase().includes(userInput) ||
                            course["COURSE TITLE"].toLowerCase().includes(userInput));
                    });
                    renderDropdown(filteredCourses, dropdownMenu, courseTitleInput);
                });
                courseDiv.style.display = "block";
            })
            .catch(error => console.error("Error fetching data:", error));
    }


    function renderDropdown(courses, dropdownMenu, courseTitleInput) {
        dropdownMenu.innerHTML = "";
        if (courses.length > 0) {
            dropdownMenu.style.display = "block";
            courses.forEach(course => {
                const option = document.createElement("div");
                option.classList.add("dropdown-item");
                option.textContent = `${course["COURSE CODE"]} - ${course["COURSE TITLE"]} (${course["CAMPUS"]} - ${course["SEMESTER"]})`;
                option.addEventListener("click", function() {
                    if (courseTitleInput) {
                        courseTitleInput.value = `${course["COURSE CODE"]} - ${course["COURSE TITLE"]} (${course["CAMPUS"]} - ${course["SEMESTER"]})`;
                    }
                    if (dropdownMenu) {
                        dropdownMenu.style.display = "none";
                    }
                });
                dropdownMenu.appendChild(option);
            });
        } else {
            dropdownMenu.style.display = "none";
        }
    }


    document.addEventListener("click", function(event) {
        if (!event.target.matches(".courseTitle") && !event.target.matches(".dropdown-item")) {
            const dropdownMenus = document.querySelectorAll(".dropdown-menu");
            dropdownMenus.forEach(dropdownMenu => {
                if (dropdownMenu) {
                    dropdownMenu.style.display = "none";
                }
            });
        }
    });


    const form = document.getElementById("teamFormationForm");
    form.addEventListener("submit", function(event) {
        event.preventDefault();


        const formData = new FormData(form);
        const studentData = {
            name: formData.get('name'),
            studentID: formData.get('studentID'),
            mobile: formData.get('mobile'),
            universityEmail: formData.get('universityEmail'),
            interests: formData.get('interests'),
            overallGPA: parseFloat(formData.get('overallGPA')),
            courseTitle: Array.from(formData.getAll('courseTitle')),
            courses: []
        };



       onst courseDivs = document.querySelectorAll('.course');
        courseDivs.forEach(courseDiv => {
            const courseTitleInput = courseDiv.querySelector('.courseTitle');
            const courseTitle = courseTitleInput ? courseTitleInput.value : '';

            const desiredGPAInput = courseDiv.querySelector('.desiredGPA');
            const desiredGPA = desiredGPAInput ? desiredGPAInput.value : '';

            const notesInput = courseDiv.querySelector('.notes');
            const notes = notesInput ? notesInput.value : '';


            const campusInput = courseDiv.querySelector('.campus');
            const campus = campusInput ? campusInput.value : '';


            const semesterInput = courseDiv.querySelector('.semester');
            const semester = semesterInput ? semesterInput.value : '';


            const modifiedCourseTitle = `${courseTitle} (${campus} - ${semester})`;


            studentData.courses.push({ courseTitle: modifiedCourseTitle, desiredGPA, notes });
        });


        fetch("/submit", {
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            },
            body: JSON.stringify(studentData)
        })
        .then(response => {
            if (!response.ok) {
                throw new Error("Network response was not ok");
            }
            return response.text();
        })
        .then(data => {
            console.log("Form submitted successfully:", data);
        })
        .catch(error => {
            console.error("Error submitting form:", error);
        });
    });



    const findTeammateBtn = document.getElementById("findTeammateBtn");
    findTeammateBtn.addEventListener("click", async function(event) {
        event.preventDefault();
       
        const courses = Array.from(document.querySelectorAll('.course')).map(courseDiv => {
            const courseTitleInput = courseDiv.querySelector('.courseTitle');
            const courseTitle = courseTitleInput ? courseTitleInput.value : '';


            const desiredGPAInput = courseDiv.querySelector('.desiredGPA');
            const desiredGPA = desiredGPAInput ? desiredGPAInput.value : '';


            return {
                courseTitle,
                desiredGPA,
            };
        });


        const formData = new FormData(document.getElementById("teamFormationForm"));
        const studentData = {
            name: formData.get('name'),
            studentID: formData.get('studentID'),
            mobile: formData.get('mobile'),
            universityEmail: formData.get('universityEmail'),
            interests: formData.get('interests'),
            overallGPA: parseFloat(formData.get('overallGPA')),
            courseTitle: Array.from(formData.getAll('courseTitle')),
            courses: []
        };


        try {
            const response = await fetch("/findTeammate", {
                method: "POST",
                headers: {
                    "Content-Type": "application/json"
                },
                body: JSON.stringify(studentData)
            });

            if (!response.ok) {
                throw new Error("Network response was not ok");
            }

            const data = await response.json();

            if (data.message === "No student with similar data found") {
                alert(data.message);
            } else {
                displayMatchingStudents(data);
            }
        } catch (error) {
            console.error("Error finding matching students:", error);
            alert("Error finding matching students. Please try again later.");
        }
    });


    function displayMatchingStudents(students) {
        const container = document.createElement("div");
        container.classList.add("container");


        const overlay = document.createElement("div");
        overlay.classList.add("overlay");


        const closeButton = document.createElement("button");
        closeButton.textContent = "Close";
        closeButton.classList.add("close-button");
        closeButton.addEventListener("click", function() {
            document.body.removeChild(overlay);
        });


        const resultList = document.createElement("ul");
        resultList.classList.add("result-list");


        if (students.length === 0) {
            const listItem = document.createElement("li");
            listItem.textContent = "No student with similar data found";
            resultList.appendChild(listItem);
        } else {
            students.forEach(student => {
                const listItem = document.createElement("li");
                listItem.innerHTML = `
                    <p><strong>Name:</strong> ${student.name}</p>
                    <p><strong>Student ID:</strong> ${student.studentID}</p>
                    <p><strong>University Email:</strong> ${student.universityEmail}</p>
                    <p><strong>GPA:</strong> ${student.overallGPA}</p>
                    <p><strong>Courses:</strong></p>
                    <ul>
                        ${student.courses.map(course => `<li>${course.courseTitle} - Desired GPA: ${course.desiredGPA}</li>`).join("")}
                    </ul>
                `;

                const connectButton = document.createElement("button");
                connectButton.textContent = "Connect";
                connectButton.classList.add("connectButton");
                connectButton.dataset.studentId = student.studentID;
                connectButton.addEventListener("click", function() {
                    connectWithTeammate(student.studentID);
                });


                listItem.appendChild(connectButton);
                resultList.appendChild(listItem);
            });
        }


        overlay.appendChild(container);
        container.appendChild(closeButton);
        container.appendChild(resultList);
        document.body.appendChild(overlay);
    }
});


let socket;
let currentStudentID;

document.addEventListener("DOMContentLoaded", function() {
    socket = io('https://rmitteammatching-84cf87192b0c.herokuapp.com/', { path: '/socket.io' });


    // Register the current student's socket with their ID
    // This should be called after the student submits their data and the server returns the studentID
    function registerStudentSocket(studentID) {
        currentStudentID = studentID;
        socket.emit('register', { studentID: currentStudentID });
    }


    // Toggle the display of the invitation box
    function toggleInvitationBox(show, fromStudentID = '') {
        const invitationBox = document.getElementById("invitation-box");
        if (show) {
            document.getElementById("invitation-from").textContent = `Student ${fromStudentID} wants to chat with you.`;
            document.getElementById("invitation-from").setAttribute("data-from-student-id", fromStudentID);
            invitationBox.style.display = 'block';
        } else {
            invitationBox.style.display = 'none';
        }
    }


    // Function to send a chat invitation
    function sendInvitation(toStudentID) {
        socket.emit('sendInvitation', { fromStudentID: currentStudentID, toStudentID });
    }


    // Listen for chat invitations
    socket.on('receiveInvitation', ({ fromStudentID }) => {
        // Show the invitation box with options to accept or decline
        toggleInvitationBox(true, fromStudentID);
    });


    // Handle the acceptance of a chat invitation
    document.getElementById("accept-invitation").addEventListener('click', function() {
        const fromStudentID = document.getElementById("invitation-from").getAttribute("data-from-student-id");
        socket.emit('respondToInvitation', { fromStudentID, toStudentID: currentStudentID, accepted: true });
        toggleInvitationBox(false);
    });


    // Function to prepare the chat interface
    function prepareChatInterface(room) {
        let chatBox = document.getElementById(`chat-box-${room}`);
        if (!chatBox) {
            chatBox = document.createElement("div");
            chatBox.id = `chat-box-${room}`;
            chatBox.setAttribute('data-room', room);
            chatBox.classList.add("chat-box");

            const messagesContainer = document.createElement("div");
            messagesContainer.classList.add("messages-container");


            const inputField = document.createElement("input");
            inputField.classList.add("message-input");
            inputField.setAttribute("placeholder", "Type your message...");

            const sendButton = document.createElement("button");
            sendButton.textContent = "Send";
            sendButton.classList.add("send-button");
            sendButton.addEventListener('click', function() {
                sendMessage(room, inputField.value);
                inputField.value = ''; // Clear the input field after sending
            });

            const closeButton = document.createElement("button");
            closeButton.textContent = "Close";
            closeButton.classList.add("close-chat");
            closeButton.addEventListener('click', function() {
                chatBox.style.display = "none";
            });

            chatBox.appendChild(messagesContainer);
            chatBox.appendChild(inputField);
            chatBox.appendChild(sendButton);
            chatBox.appendChild(closeButton);


            document.body.appendChild(chatBox);
        }
    }


    // Function to send messages
    function sendMessage(room, message) {
        if (message.trim() !== '') {
            socket.emit('sendMessage', { room, message, studentID: currentStudentID });
        }
    }


    // Listen for accepted invitations and create the chat interface
    socket.on('invitationAccepted', ({ room }) => {
        prepareChatInterface(room);
    });


    // Listen for incoming messages
    socket.on('receiveMessage', ({ room, studentID, message }) => {
        const chatBox = document.getElementById(`chat-box-${room}`);
        if (chatBox) {
            const messagesContainer = chatBox.querySelector(".messages-container");
            const msgDiv = document.createElement("div");
            msgDiv.textContent = `Student ${studentID}: ${message}`;
            msgDiv.className = studentID === currentStudentID ? 'message-own' : 'message-partner';
            messagesContainer.appendChild(msgDiv);
            messagesContainer.scrollTop = messagesContainer.scrollHeight; 
        }
    });
});

And this is server.js:

const express = require('express');
const mongoose = require('mongoose');
const path = require('path');
const socketIo = require('socket.io');


const app = express();
const PORT = process.env.PORT || 3001;


// MongoDB connection
mongoose.connect('mongodb+srv://ss:[email protected]/RmitTeamFinding', {
    useNewUrlParser: true,
    useUnifiedTopology: true
});


const db = mongoose.connection;
db.on('error', console.error.bind(console, 'MongoDB connection error:'));
db.once('open', () => {
    console.log('Connected to MongoDB');
});


const studentSchema = new mongoose.Schema({
    name: String,
    studentID: String,
    mobile: String, 
    universityEmail: String,
    interests: String,
    overallGPA: Number,
    courses: [{
        courseTitle: String,
        desiredGPA: String,
        notes: String
    }]
});

const Student = mongoose.model('Student', studentSchema);

// Middleware to parse JSON bodies
app.use(express.json());


// Serve static files from the "public" directory
app.use(express.static(path.join(__dirname, 'public')));


app.post('/submit', async (req, res) => {
    try {
        const formData = req.body;

        const validCourses = formData.courses.filter(course => {
            return course.courseTitle.trim() !== '' && course.courseTitle !== ' ( - )';
        });


        if (validCourses.length === 0) {
            return res.status(400).send('No valid courses provided');
        }

        const existingStudent = await Student.findOne({ studentID: formData.studentID });

        if (existingStudent) {
            validCourses.forEach(newCourse => {
                const courseExists = existingStudent.courses.some(existingCourse => {
                    return existingCourse.courseTitle === newCourse.courseTitle; 
                });
                if (!courseExists) {
                    existingStudent.courses.push(newCourse); 
                }
            });

            await existingStudent.save();
            return res.status(200).send('Student data updated successfully with no duplicate courses!');
        } else {
            // If student does not exist, create a new student with the courses
            const newStudent = new Student({
                name: formData.name,
                studentID: formData.studentID,
                mobile: formData.mobile,
                universityEmail: formData.universityEmail,
                interests: formData.interests,
                overallGPA: formData.overallGPA,
                courses: validCourses
            });
            await newStudent.save();
            return res.status(201).send('New student data saved successfully!');
        }
    } catch (err) {
        console.error(err);
        return res.status(500).send('Internal server error');
    }
});

// Route to find teammates
app.post('/findTeammate', async (req, res) => {
    try {
        const { name, interests, overallGPA, courses } = req.body;
        console.log("Received search criteria:", { name, interests, overallGPA, courses });


        // Construct query criteria
        const queryCriteria = {
            ...(interests ? { interests } : {}),
            ...(name ? { name } : {}),
            overallGPA: { $gte: overallGPA - 0.2, $lte: overallGPA + 0.2 },
        };

        console.log("Constructed query criteria:", queryCriteria);


        const matchingStudents = await Student.find(queryCriteria).sort({ overallGPA: -1 });


        console.log("matchingStudents ", matchingStudents);


        if (matchingStudents.length === 0) {
            return res.status(200).json({ message: "No student with similar data found" });
        }


        // Search Course
        let matchNewStudents = [];

        for (let index = 0; index < matchingStudents.length; index++) {
            const element = matchingStudents[index];
            if (element.courses.length) {
                const newArrCourse = [...new Set(element.courses)];
                const queryCriteriaCourse = {
                    // Find students with all matching courses
                    courses: {
                        $all: newArrCourse.map((course) => ({
                            $elemMatch: {
                                courseTitle: new RegExp(course.courseTitle.replace(/[-/\^$*+?.()|[]{}]/g, "\$&"), "i"),
                                desiredGPA: course.desiredGPA,
                            },
                        })),
                    },
                };


                const matchingStudentsCourse = await Student.find(queryCriteriaCourse).sort({ overallGPA: -1 });


                if (matchingStudentsCourse && matchingStudentsCourse.length) {
                    matchNewStudents = matchNewStudents.concat(
                        matchingStudentsCourse.filter(
                            (student) =>
                                !matchingStudents.filter((old) => old._id.toString() === student._id.toString()).length &&
                                !matchNewStudents.filter((old) => old._id.toString() === student._id.toString()).length
                        )
                    );
                }
            }
        }


        // Return the list of matching students
        res.status(200).json([...matchingStudents, ...matchNewStudents]);
    } catch (error) {
        console.error("Error finding matching students:", error);
        res.status(500).json({ message: "Internal server error" });
    }
});

// New route to handle connecting with a teammate
app.post('/connect/:studentID', async (req, res) => {
    try {
        const studentID = req.params.studentID;
        const currentStudentID = req.body.studentID;


        // Find the current student who wants to connect
        const currentUser = await Student.findOne({ studentID: currentStudentID });
        if (!currentUser) {
            return res.status(404).json({ message: 'Student not found' });
        }


        // Find a teammate for the current student
        const teammate = await Student.findOne({ studentID });
        if (!teammate) {
            return res.status(404).json({ message: 'Teammate not found' });
        }
        await establishConnection(currentUser, teammate);


        // Send a response indicating successful connection
        res.status(200).json({ message: 'Connected with teammate successfully', studentID, teammate });
    } catch (error) {
        console.error('Error connecting with teammate:', error);
        res.status(500).json({ message: 'Internal server error' });
    }
});


// Function to find a teammate for the current student
async function findTeammate(currentUser) {
  try {


      // Define criteria for finding a teammate
      const teammateCriteria = {
          overallGPA: { $gte: currentUser.overallGPA - 0.2, $lte: currentUser.overallGPA + 0.2 }, 
          studentID: { $ne: currentUser.studentID } 
      };


      const potentialTeammates = await Student.find(teammateCriteria).limit(1).lean();


      if (potentialTeammates.length > 0) {
          return potentialTeammates[0];
      } else {
          return null; 
      }
  } catch (error) {
      console.error('Error finding teammate:', error);
      return null; 
  }
}


// Function to establish a connection between two students
async function establishConnection(currentUser, teammate) {
  try {


      // Update the connection status for both side
      await Promise.all([
          Student.updateOne({ _id: currentUser._id }, { $set: { connectedWith: teammate._id } }),
          Student.updateOne({ _id: teammate._id }, { $set: { connectedWith: currentUser._id } })
      ]);


      return true;
  } catch (error) {
      console.error('Error establishing connection:', error);
      return false; 
  }
}


function connectWithTeammate(teammateStudentID) {
    fetch(`/connect/${teammateStudentID}`, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({ studentID: currentStudentID })
    })
    .then(response => {
        if (!response.ok) {
            throw new Error('Failed to connect with teammate');
        }
        return response.json();
    })
    .then(data => {
        console.log('Connected with teammate:', data);
        // Handle successful connection, e.g., display a notification
    })
    .catch(error => {
        console.error('Error connecting with teammate:', error);
        // Handle error
    });
}


// Initialize Socket.IO
const server = require('http').createServer(app);
const io = socketIo(server, {
    path: '/socket.io',
    cors: {
        origin: 'https://rmitteammatching-84cf87192b0c.herokuapp.com',
        methods: ['GET', 'POST'],
        credentials: true
    }
});

// Create a separate namespace for the chat functionality
const chatNsp = io.of('/chat');


// Store chat-related data
const chatRooms = new Map();
const pendingInvitations = new Map();
const studentToSocketMap = new Map();

chatNsp.on('connection', (socket) => {
    console.log('A user connected to the chat namespace');

    socket.on('register', ({ studentID }) => {
        socket.join(studentID);
        studentToSocketMap.set(studentID, socket.id);
        console.log(`Student ${studentID} joined the chat namespace`);
    });

    socket.on('sendInvitation', ({ fromStudentID, toStudentID }) => {
        const invitationKey = `${fromStudentID}-${toStudentID}`;
        pendingInvitations.set(invitationKey, { fromStudentID, toStudentID });
        const toSocketId = studentToSocketMap.get(toStudentID);
        if (toSocketId) {
            chatNsp.to(toSocketId).emit('receiveInvitation', { fromStudentID });
        }
    });

    // Notify sender response
    const fromSocketId = studentToSocketMap.get(fromStudentID);
    if (fromSocketId) {
        if (accepted) {
            chatNsp.to(fromSocketId).emit('invitationAccepted', { fromStudentID });
        } else {
            chatNsp.to(fromSocketId).emit('invitationDeclined', { fromStudentID });
        }
    }
});

    socket.on('sendMessage', ({ room, message, studentID }) => {
        chatNsp.to(room).emit('receiveMessage', { studentID, message });
    });


    socket.on('disconnect', () => {
        console.log('User disconnected from the chat namespace');
        const studentID = Array.from(studentToSocketMap.entries()).find(([_, socketId]) => socketId === socket.id)?.[0];
        if (studentID) {
            studentToSocketMap.delete(studentID);
            console.log(`Student ${studentID} disconnected`);
        }
    });
});

server.listen(PORT, () => {
    console.log(`Server is running on http://localhost:${PORT}`);
});

Right now on click of a button a modal is opening but now on click of button I want to open a modal and also Submit values for the form

htmlString += "             <button type="button" class="btn-link border-0 cancel-btn-v1" data-bs-toggle="modal" data-bs-target="#cancelSubscription_" + rowInd + "" onclick="openModalPauseAtClickCoordinate(this)">" + TITLES.BUTTONS.CANCEL_SUBSCRIPTION + "</button>";

htmlString += "<a href="javascript:void(0);" class="btn btn-primary btn-sm" onclick="var data = {};data.unsubscribe = 'T';var value = JSON.stringify(data); nlapiSetFieldValue('custpage_newfield', value); document.getElementById('main_form').submit();">" + TITLES.BUTTONS.SUBMIT + "</a>";

How can I combine this both button into one.

How to handle secure cookies between windows of the same browser [closed]

I am developing an application where I am using PHP as backend and JavaScript as frontend. In the login page of application, I am maintaining session and cookies to store user information with an expiry time of 1 day for cookies.

With Security being the primary concern, I want to implement a secure way of using the application in terms of usage of cookies.
I came across a situation where the cookies from the application generated after login can be used to access the dashboard of the application without login in another private window.

This will create a loophole in the application security concerning the login.

I am using these options from php

ini_set('session.cookie_lifetime', 60*60*24*1); // Cookie expiry - 1 day
ini_set('session.gc_maxlifetime', 60*60*24*1); // Session expiry - 1 day
ini_set('session.use_cookies', 1);
ini_set('session.use_only_cookies', 1);

session_name('My-Session');
ini_set('session.cookie_samesite', 'Lax');
session_start([
    'read_and_close' => true,
]);

Is there any way to ensure security regarding cookies in this matter. Is it possible to restrict cookies from one windows to be not used by other window? Any help would be appreciated. Thank you

WHY CAN’T WE DIRECTLY SEND JSON DATA IN HTTP REQUEST? [closed]

i am confused like why do we need to convert json data to string before sending it in http request and if it’s because http is text based protocol then from some source i read that we don’t need to stringify binary data in http request why is that so?( i am beginner in these things so sorry if it’s too dumb)

i am confused in this thing so i had to ask

Click() event on e2e test in cypress does not work, when used on Switch Element Plus component

When manually testing my Nuxt app, clicking on the switch element works, and it changes my global variable. But in the Cypress test, the switch remains switched off even if the click event runs successfully.

Test in cypress CLI

My test looks like this:

it.only('check if creeate button is visible', () => {
    const pagesToCheck = [
      '/encyclopedia/topics?page=1&language=cs',
      '/encyclopedia/questions?page=1&language=cs',
      '/encyclopedia/questions?kind=interactive_video&page=1&language=cs',
    ];


    pagesToCheck.forEach((pageUrl) => {
      cy.visit(pageUrl);

      cy.getData("edit-mode-switch").eq(1).click({ force: true });

      cy.getData("create-button").should('be.visible');
    });
  })

eq(1) is for targeting a particular switch. (There are 3)
getData() is custom command

Switch Component:

<div
        class="form-check form-switch form-check-custom form-check-warning form-check-solid"
      >
        <el-switch
          v-model="editModeStore.editMode"
          :before-change="changeSwitch"
          size="large"
          label="Edit mode switch"
          aria-label="Edit mode switch"
          style="--el-switch-on-color: #ffc700"
          data-cy="edit-mode-switch"

        />
        <span
          class="edit-mode-label"
          :class="{ 'is-active': editModeStore.editMode }"
          @click="changeSwitch"
        >
          {{ t('user.edit_mode') }}
        </span>
      </div>

I tried many ways of implementing the click event:
cy.getData("edit-mode-switch").eq(1).click('top', { force: true });

cy.getData("edit-mode-switch").eq(1).trigger('mousedown'); cy.getData("edit-mode-switch").eq(1).trigger('mouseup');

cy.get('selector-for-your-element').dblclick();

I also made Cypress click on the span next to the switch, but with no effect.
I appreciate any help.

OwlError: No active component (a hook function should only be called in ‘setup’) in Odoo17

/** @odoo-module **/
import { Order } from "@point_of_sale/app/store/models";
import { patch } from "@web/core/utils/patch";
import { roundDecimals, roundPrecision } from "@web/core/utils/numbers";
import { useState } from "@odoo/owl";

patch(Order.prototype, {
    setup() {
        super.setup(...arguments);
        this.state = useState({
            points: 0,
        });
    },
    deductLoyaltyPoints() {
        let valsList = [];
        if (this.couponPointChanges) {
            console.log(this)
        }
        this.pos.lostPoints = valsList;
        return valsList;
    },
});

point_of_sale.assets_prod.min.js:6087 OwlError: No active component (a
hook function should only be called in ‘setup’)
at getCurrent (point_of_sale.assets_prod.min.js:1010:67)
at useState (point_of_sale.assets_prod.min.js:1014:80)
at Order.setup (point_of_sale.assets_prod.min.js:11067:499)
at new PosModel (point_of_sale.assets_prod.min.js:9220:48)
at new Order (point_of_sale.assets_prod.min.js:9373:29)
at Proxy.createReactiveOrder (point_of_sale.assets_prod.min.js:9611:31)
at Proxy.load_orders (point_of_sale.assets_prod.min.js:9620:292)
at async Proxy.after_load_server_data (point_of_sale.assets_prod.min.js:9572:67)
at async Proxy.after_load_server_data (point_of_sale.assets_prod.min.js:11201:194)
at async Proxy.load_server_data (point_of_sale.assets_prod.min.js:11058:364)

Finding longest word, passing 9/10 tests, Why?

This is an task from codesignal.
It’s not a homework or something else, just I writed a code and now trying understand what’s wrong.
Let’s see task requirements.
Define a word as a sequence of consecutive English letters. Find the longest word from the given string.

Example.

For text = "Ready, steady, go!", the output should be
solution(text) = "steady".

Well, now I’m sharing my code.

function solution(text) {
 let words = text.match(/w+/g);
    
    let ml = Math.max(...words.map(el=>el.length))
    
    for(let i = 0; i < words.length; i++){
        if(words[i].length == ml){
            return words[i]
        }
    }
}

It’s passing all tests, except of one hide test. Now I opened that hide test it looks like this text: "ab-CDE-fg_hi". Expected output of this test is "CDE" .
Now I’m trying understand what’s the problem and why it’s not passing this test, can someone please explain me.

I’m newbie so please be more polite)

clicking JS popup close button refreshes page and displays popup again

why is this happening and how can I fix this, so that upon clicking close button of popup, page does not refresh and popup vanishes. I’ve tried using cookies and local variable and this issue still persists.

note: In .show-popup, display property is none

the html code

   <div id="popup-overlay" > </div>
   <div id="popup-greeting" >
  <img src="...." alt="Greeting Image"/>
  <button id="closeButton">Close</button> 
</div>
var popupDisplayed = localStorage.getItem("popupDisplayed");
 window.addEventListener("load", function(){
    if (popupDisplayed !== "true") {
    var popupOverlay = document.getElementById('popup-overlay');
    var popupGreeting = document.getElementById('popup-greeting');
    
    popupOverlay.style.display = 'none';
    popupGreeting.style.display = 'none';
    popupDisplayed.style.display = 'none';

        // If the popup has not been displayed before, show it after a delay
        setTimeout(function() {
            var popupOverlay = document.getElementById('popup-overlay');
            var popupGreeting = document.getElementById('popup-greeting');
            
            popupOverlay.style.display = 'block';
            popupGreeting.style.display = 'block';
        }  
        ,  100000);

        // Store a flag indicating that the popup has been displayed
        localStorage.setItem("popupDisplayed", "true");
    } 
 });

    document.querySelector("#closeButton").addEventListener("click", function(){    
        var popupOverlay = document.getElementById('popup-overlay');
        var popupGreeting = document.getElementById('popup-greeting');

        popupOverlay.style.display = 'none';
        popupGreeting.style.display = 'none';
        
        const var = popupOverlay.style.display;
        alert(popupOverlay.style.display);

        popupOverlay.style.opacity = '0';
        popupGreeting.style.opacity = '0';
        
                
 }
 );

ResizeObserver callback is not being fired when rotated device two times

I am using ResizeObserver Api to listen to orientation change and fullscreen mode change.
The observer is getting registered successfully.
When moved from portrait mode to landscape mode, the callback is being fired. But for subsequent change from landscape to portrait and vice-versa, callback is not executed.
I can confirm that observer instance is still alive, as for full-screen mode change, screen resize event is being listened successfully.

expected behavior: When created instance of ResizeObserver API, it should listen to all resize, orientation change, full-screen mode change events.

noticed bahavior: Orientation change event is captured only once. After that it’s not listening to the event. At same time listening to other resize events.

Implementation:



type TCallback = {
  [key in string]: (_:ResizeObserverEntry)=>void
}

export class ContainerObserver  {
  private static instanceCache: ContainerObserver ;

  private observerInstance: ResizeObserver;

  private resizeCallbacks: {
    [key in string]: (_: ResizeObserverEntry) => void;
  } = {};

  private RootContainer: HTMLDivElement;

  private constructor() {
    this.RootContainer = document.querySelector("#root")!;
    if (this.RootContainer) {
      this.observerInstance = new ResizeObserver((entries) => {
        const relativeTo = entries?.[0];
        Object.values(this.resizeCallbacks).forEach((callback) => {
          callback(relativeTo);
        });
      });
      
      this.observerInstance.observe(this.RootContainer);
    }
  }

  public static get instance(): ContainerObserver  {
    if (!ContainerObserver .instanceCache) {
      ContainerObserver .instanceCache = new ContainerObserver ();
    }

    return ContainerObserver .instanceCache;
  }
  
  addCallbackObserver(callback:TCallback)  {
    
    this.resizeCallbacks   =  {
      ...this.resizeCallbacks,
      ...callback
    } ;

    console.log({callbacks: this.resizeCallbacks})
    
  }
  getInstance(){
    return this.observerInstance
  }

  // Method to stop observing an element
  unobserve() {
    this.observerInstance.unobserve(this.RootContainer);
  }
}

usage of the class:

ContainerObserver.instance.addCallbackObserver({ handleResize });

How can I display a php page in my overlay using WPML tags?

This is part of a plugin I’m creating for training purposes. In one of my pages I want to overlay another php page. Everything was working fine before I put in my translation tags.

The page displayed in the overlay :
The code is displayed on my page but is cut off at <?php

<form class="tracker-rms-form-container" action="" method="post" enctype="multipart/form-data">

            <div class="tracker-rms-top-part">
                <?php echo '<h2>' . esc_html__( 'Apply Now', 'trackerform' ) . '</h2>'; ?>
                <label class="tracker-rms-label required-field"><i><?php esc_html_e( 'required field', 'trackerform' ) ?></i></br></label>

The JS code that displays the overlay :

function loadOverlayContent() {
                        var overlayContainer = $("<div id='overlayContainer'></div>");
                        var closeButton = $("<a href='' id='closeOverlayButton'></a>");

                        // Ajoutez la superposition à la page
                        $("body").append(overlayContainer);

                        // Ajoutez un fond noir semi-transparent
                        var backgroundOverlay = $("<div id='backgroundOverlay'></div>");
                        $("body").append(backgroundOverlay);

                        // Appliquer le style pour afficher le fond noir semi-transparent
                        backgroundOverlay.css({
                            position: 'fixed',
                            top: '0',
                            left: '0',
                            width: '100%',
                            height: '100%',
                            background: 'rgba(0, 0, 0, 0.65)', // Couleur noire avec une opacité de 65%
                            zIndex: '9998', // Un niveau en dessous de l'overlay
                        });

                        // Charger la page PHP via AJAX
                        $.ajax({
                            url: "<?php echo esc_url(plugins_url('tracker-rms-form.php', __FILE__)); ?>",
                            success: function (data) {
                                // Insérer le contenu de la page PHP dans l'overlayContainer
                                overlayContainer.html(data);

                                // Appliquer le style pour afficher l'overlay devant la page
                                overlayContainer.css({
                                    position: 'fixed',
                                    top: '50%',
                                    left: '50%',
                                    transform: 'translate(-50%, -50%)',
                                    zIndex: '9999', // Ajustez le z-index en fonction de vos besoins
                                    backgroundwidth: '100%',
                                    minWidth: '60%',
                                    maxHeight: '90%',
                                    overflow: 'auto',
                                    scrollbarWidth: 'none',
                                });

                                // Ajoutez un bouton de fermeture à l'overlay
                                overlayContainer.append(closeButton);

                                // Ajoutez un événement de clic pour le bouton de fermeture
                                closeButton.on("click", function () {
                                    // Fermez l'overlay lorsqu'on clique sur le bouton de fermeture
                                    overlayContainer.remove();
                                    backgroundOverlay.remove();
                                });

                                // Ajouter un gestionnaire d'événements pour détecter les clics en dehors de l'overlay
                                backgroundOverlay.on("click", function (event) {
                                    if (!$(event.target).closest("#overlayContainer").length) {
                                        // Fermer l'overlay si le clic est en dehors de celui-ci
                                        overlayContainer.remove();
                                        backgroundOverlay.remove();
                                    }
                                });
                            },
                            error: function () {
                                // Gérer les erreurs en cas de problème lors du chargement de la page PHP
                                overlayContainer.html("<p>Une erreur s'est produite lors du chargement du contenu.</p>");
                            }
                        });
                    }

Implement Simple upload adapter Ckeditor

I’m trying to implement a CKEditor in my website that allow to upload images but its not working. The server is receiving no files.

This is the editor in the view

 ClassicEditor
    .create( document.querySelector( '#contenido_en' ), {
        simpleUpload: {
                // The URL that the images are uploaded to.
                uploadUrl: '<?=base_url()?>admin/pages/upload/',

                // Headers sent along with the XMLHttpRequest to the upload server.
                headers: {
                    Authorization: 'Bearer <JSON Web Token>'
                }
            },
        link: {
            defaultProtocol: 'https://',
            decorators: {
                openInNewTab: {
                    mode: 'manual',
                    label: 'Abrir en ventana nueva',
                    attributes: {
                        target: '_blank',
                        rel: 'noopener noreferrer'
                    }
                }
            }
        },
        htmlSupport: {
                allow: [
                    {
                        name: /.*/,
                        attributes: true,
                        classes: true,
                        styles: true
                    }
                ]
            },

        licenseKey: '',
        htmlEncodeOutput : true,
        mediaEmbed: {
            previewsInData: true
        },
        
        
    } )

    .then( editor => {

        window.editor = editor;

    } )
    
    
    .catch( error => {
        console.error( 'Oops, something went wrong!' );
        console.error( 'Please, report the following error on https://github.com/ckeditor/ckeditor5/issues with the build id and the error stack trace:' );
        console.warn( 'Build id: c6h88q57dj85-kkgxfgc2wty2' );
        console.error( error );
    } );

And this is the controller function

 use ResponseTrait;
    public function pagesUpload($id = null)
    {   
        helper('form');
        $img = $this->request->getFile('upload');
        log_message('error',$img ?? 'null');
        if ($img->isValid() && ! $img->hasMoved()) {
            $newName = $img->getRandomName();
            if($id)
            {
                $img->move(FCPATH . 'public/images/contenido/'.$id.'/', $newName);
                $pathimagen = base_url('public/images/contenido/'.$id.'/'.$newName);
            }
            else{
                $img->move(FCPATH . 'public/images/contenido/', $newName);
                $pathimagen = base_url('public/images/contenido/'.$newName);
            }
            $data = ['url' => $pathimagen];            
            return $this->respond($data);
            }
    }

When I upload a image on the ckeditor, I got a 500 Internal Server Error, because $img is null after this
$img = $this->request->getFile(‘upload’);

inline tinymce editor does not trigger input event

Using tinyMCE I am using an inline editor. I have set oninput to copy the updated texts into a textarea.

When I update texts manually, the changes are being copied to the textarea. But when I use editing options like BOLD, UNDERLINE etc, those formatting codes are not being copied to the target textarea unless I modify something manually after that changes.

I guess using those formatting options are not triggering input event. Please advise.

$(window).on("load",function(){
    tinymce.init({
        selector:'.editable',
        menubar: false,
        statusbar: false,
        plugins: "lists",
        inline: true,
        toolbar: [
            'bold italic underline | numlist bullist'
        ],
        valid_elements: 'p[style],strong,em,span[style],a[href],ul,ol,li'
    })
})


function updateTextarea(id){
    var newText = $('#editable'+id).html();
    $('#textarea'+id).html(newText);
}
.editable{
  border:1px dashed #aaaaaa;
  padding:10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/tinymce/4.5.6/tinymce.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/tinymce/4.5.6/jquery.tinymce.min.js"></script>

<div class="editable" id="editable1" oninput="updateTextarea('1')">
Edit this text. It will update the textarea. Make it bold, Target wont update
</div>

<br><br>

<strong>Target Textarea:</strong>

<textarea id="textarea1" style="width:100%;height:40px;"></textarea>