How to update user membership status realtime in browser extension

I have a paid browser extension using supabase as backend and stripe as the payment processer. My problem is, when a user upgrades their membership, I need to refresh the auth session to reflect the change in membership and grant them access to premium features.

my current implementation is that the browser extension detects when the user is on the thank you page and refreshes the session. This requires the extra “tabs” permission and overall I don’t think its a very intuitive and robust approach.

on the other hand, creating a realtime connection with the database seems like overkill since I only need this one thing to change realtime.

This is my first browser extension, so I’m quite new to this. Would appreciate any feedback on how this is normally done.

Thanks

Firefox extension for android mobile permissions error

I am working on an extension for Firefox for Android, but I am running into issues with permissions. I have this piece of code that checks what permissions the extension has.

const bookmarks = await browser.permissions.contains({ permissions: ['bookmarks'] });
const downloads = await browser.permissions.contains({ permissions: ['downloads'] });
const history = await browser.permissions.contains({ permissions: ['history'] });
const notifications = await browser.permissions.contains({ permissions: ['notifications'] });
const webNavigation = await browser.permissions.contains({ permissions: ['webNavigation'] });

The problem is that when debugging on mobile I get this error for the bookmarks and history lines.

Error: Type error for parameter permissions (Error processing permissions.0: Value "bookmarks" must either: must either [must either [must either [be one of ["idle"], be one of ["activeTab"], be one of ["cookies"], be one of ["scripting"], or be one of ["webRequest", "webRequestAuthProvider", "webRequestBlocking", "webRequestFilterResponse", "webRequestFilterResponse.serviceWorkerScript"]], must either [be one of ["mozillaAddons"], be one of ["geckoViewAddons", "nativeMessagingFromContent"], be one of ["activityLog"], be one of ["networkStatus"], or be one of ["telemetry"]], be one of ["alarms", "storage", "unlimitedStorage"], be one of ["declarativeNetRequestWithHostAccess"], be one of ["dns"], or be one of ["theme"]], must either [must either [be one of ["idle"], be one of ["activeTab"], be one of ["cookies"], be one of ["scripting"], or be one of ["webRequest", "webRequestAuthProvider", "webRequestBlocking", "webRequestFilterResponse", "webRequestFilterResponse.serviceWorkerScript"]], be one of ["clipboardRead", "clipboardWrite", "geolocation", "notifications"], be one of ["browsingData"], be one of ["tabs"], be one of ["browserSettings"], be one of ["declarativeNetRequestFeedback"], be one of ["downloads", "downloads.open"], be one of ["management"], be one of ["privacy"], be one of ["proxy"], be one of ["webNavigation"], or be one of ["nativeMessaging"]], be one of ["declarativeNetRequest"], or match the pattern /^experiments(.w+)+$/], or must either [be one of [], be one of ["userScripts"], or be one of ["trialML"]]) for permissions.contains.

Bookmarks and history are in the optional permissions in the manifest.json file, but I tried moving them to the permissions and it did not fix anything.

How to inject images from native app to webview and opload to server

I have the following code i want upload images to server in webview in my application but doesn’t works. How to inject images from native app to webview and upload to server.

My Screenshot: [https://i.sstatic.net/65I5CtSB.png][1]

   @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if(requestCode==123 && resultCode==RESULT_OK) {

        // Checking whether data is null or not
        if (data != null) {

            // Checking for selection multiple files or single.
            if (data.getClipData() != null) {

                // Getting the length of data and logging up the logs using index
                for (int index = 0; index < data.getClipData().getItemCount(); index++) {

                    // Getting the URIs of the selected files and logging them into logcat at debug level
                    Uri uri = data.getClipData().getItemAt(index).getUri();
                    Log.d("filesUri [" + uri + "] : ", String.valueOf(uri));

                    MainActivity.this.myWebView.loadUrl("javascript:window.INTERFACE.ximagex(document.getElementById('image').src='"+uri+"');");
                }
            } else {

                // Getting the URI of the selected file and logging into logcat at debug level
                Uri uri = data.getData();
                Log.d("fileUri: ", String.valueOf(uri));
            }
        }

    }

}

    public void timer() {
    this.countDownTimer = new CountDownTimer(5000000, 5000) {
        public void onTick(long millisUntilFinished) {
            MainActivity.this.myWebView.loadUrl("javascript:window.INTERFACE.ximage(document.getElementById('ximage').value);");
            // Intent i = new Intent(MainActivity.this, ImageActivity.class);
            //startActivity(i);
            if (Integer.valueOf(ximage) == 1) {
                //onFinish();
                Intent intent = new Intent()
                        .setType("image/*")
                        .setAction(Intent.ACTION_GET_CONTENT);
                intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
                startActivityForResult(Intent.createChooser(intent, "Select a file"), 123);
                MainActivity.this.myWebView.loadUrl("javascript:window.INTERFACE.ximage(document.getElementById('ximage').value ='0');");

            }
        }

        public void onFinish() {
            countDownTimer.cancel();
        }
    }.start();
}

How backend work with front end using flask [closed]

I’m currently on Day 7 of learning Python Flask, and I’m confused about how the frontend connects to the backend.

I have HTML files like register.html and login.html, and I’ve created Flask routes for them, but I’m not sure how to:

  1. Send form data (like username and password) from the HTML to Flask.
  2. Show success or error messages after submitting the form.
  3. Display dynamic content in HTML using variables from Python.
  4. Structure my files (templates, static, app.py).

and honestly am just confuse i thought python will be easy for me cos i know to code html and css and js

Chakra UI set up on Vite + react using JS

I can’t figure out the merge of Chakra UI’s structure with the React.js. Even the basic things like adding a button isn’t working and I’m following a person on youtube whose things are working alright but following, I am not getting the same result here: from 56:00 to 62:00, I am not getting a button like that. Link: https://www.youtube.com/watch?v=O3BUHwfHf84

I tried chatgpt and copy, paste what it said along with the screen shots I showed it. I want a complete right tutorial of merging them both to continue on my tutorial video of mern stack.

ipyaggrid cell style conditional coloring

ipyaggrid.__version__ = 0.5.4

I want to color code some cells in a column called name if the cell value equals ‘xyz’.

The code below is suggested by ChatGPT but it doesn’t work. ipyaggrid simply ignored the styling function in ‘cellStyle’. However, if I simplify it and make it a static red color, it works.

So the question is how to conditional color code the cell based on cell value match?

import pandas as pd
from ipyaggrid import Grid
from IPython.display import display

# Sample DataFrame
df = pd.DataFrame({
    'name': ['xyz', 'abc', 'xyz', 'def', 'xyz'],
    'quantity': [10, 20, 15, 5, 30],
    'price': [1.5, 2.0, 1.2, 3.3, 0.9]
})

# Define columnDefs with conditional styling for 'basket'
column_defs = [
    {
        'field': 'name',
        'headerName': 'Name',
        'cellStyle': {  # this works --> 'color': 'red'
            'function': """
                function(params) {
                    if (params.value === 'xyz') {
                        return { 'color': 'red' };
                    }
                    return null;
                }
            """
        },
    },
    { 'headerName': 'Quantity', 'field': 'quantity' },
    { 'headerName': 'Price', 'field': 'price' }
]

# Grid options
grid_options = {
    'columnDefs': column_defs,
    'defaultColDef': {
        'resizable': True,
        'sortable': True,
        'filter': True
    },
    'rowSelection': 'single'
}

# Create the grid
grid = Grid(grid_data=df.to_dict("records"), 
            grid_options=grid_options,
            height=180)

display(grid)

Brick masonry designer [closed]

I am developing a site for a brick factory and I need to implement a visual designer of brickwork. The user should be able to choose the color of the brick, type of masonry, the color of the solution, the format of brick, and also apply these parameters to the templates of houses (individual and multi -apartment) in order to see the final result in real time (a visual realistic picture of the house). It is necessary that the user can choose a brick at home and change its color in order to choose an interesting option for his home, site, etc. It is also considered that a fence, windows, roof, etc. and the possibility of editing are implemented. It is also necessary to realize the modules of baskets, survey, viewed goods, adaptive layout and the ability to easily add new colors or templates without changing code. Please advise how to implement the designer of brickwork, which technologies are best used for visualization (canvas, svg, webgl, three.js?), How to organize the structure of data and storage of masonry and brick options, which libraries or approaches are suitable for implementation, and how to build the project architecture (Fronte/Backend).

I just started the development and accept any advice, from those who somehow came across this and sees a possible solution

There is a problem with establishing audio calls between users. WebRTC NodeJS [closed]

There is a problem with establishing audio calls between users.
There is an application on Android where audio communication works perfectly between users.
However, when trying to call from a web browser to Android, there is a connection error.
Here is my HTML code that I am using:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>AudioCall</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.5.0/socket.io.js"></script>
</head>
<body>
    <h1>AudioCall</h1>
    <label for="myId">you ID:</label>
    <input type="text" id="myId" value="243"><br><br>
    <label for="recipientId">ID users for:</label>
    <input type="text" id="recipientId" value="3039"><br><br>
    <button id="callButton">Call</button>
    <button id="endCallButton">End Call</button>

    <script>
    const socket = io('https://srv1-node-call-jakarta.dkon.app', {
        query: { token: "7d3d3b6c2d3683bf25bbb51533ec6dab" }
    });

    let localStream;
    let peerConnection;
    let DkonCalls =socket.id;    
        
        let globalSocketId;
        let pizda;

    const configuration = {
        iceServers: [
            { urls: 'stun:stun.cloudflare.com:3478' },
            {
                urls: "turn:global.relay.metered.ca:80",
                username: "688db195aa1c5ae4555d3fb5",
                credential: "x9XGuSBKLsedMYoe",
            },
            {
                urls: "turn:global.relay.metered.ca:443",
                username: "688db195aa1c5ae4555d3fb5",
                credential: "x9XGuSBKLsedMYoe",
            },
        ]
    };

        
        socket.on('connect', () => {
            const myId = document.getElementById('myId').value;
            socket.emit('socket_user_connect', { connectedId: myId, connected: true, userToken: "7d3d3b6c2d3683bf25bbb51533ec6dab", socketId: socket.id });
            console.log(`Подключен с сокет ID: ${socket.id}`);
        });
    document.getElementById('callButton').addEventListener('click', () => {
        if (peerConnection) {
            console.log("Уже есть активный вызов. Пожалуйста, завершите его перед началом нового.");
            return;
        }

        const myId = document.getElementById('myId').value;
        const recipientId = document.getElementById('recipientId').value;

        console.log(`Попытка позвонить пользователю с ID: ${recipientId} от пользователя с ID: ${myId}`);

        socket.emit('socket_call_user_ping', { recipientId: recipientId }, (data) => {
            if (data.socketId) {
                console.log(`Пользователь с ID ${recipientId} доступен. Socket ID: ${data.socketId}`);
                globalSocketId = data.socketId;
                socket.emit('make_new_call', {
                    to: data.socketId,
                    from: socket.id,
                    callerID: myId,
                    isAudioCall: true
                });
            } else {
                console.log(`Пользователь с ID ${recipientId} не доступен`);
            }
        });
    });
        
        socket.on('receive_new_call', (data) => {
    const { callerID, from } = data;
            console.dir(data);
            pizda = data.from;
            pizdato = data.to;
            console.log('PP',pizdato);
         

    console.log(`Входящий звонок от пользователя с ID ${callerID}`);

    const callDiv = document.createElement('div');
    callDiv.innerHTML = `
        <p>Входящий звонок от пользователя с ID ${callerID}</p>
        <button id="acceptCall">Принять</button>
        <button id="rejectCall">Отклонить</button>
    `;
    document.body.appendChild(callDiv);

    document.getElementById('acceptCall').onclick = () => {
        console.log(`Вы приняли звонок от пользователя с ID ${callerID}`);
        
        // Отправка сигнала о принятии вызова
        socket.emit('accept_new_call', { callerSocketId: from, userSocketId: socket.id });
        
        if (from) {
            socket.emit('signaling_server', { to: from, from: socket.id, type:'init', payload:'payload'});
            
            
         
            console.dir(data);
        } else {
            console.error('from is undefined, cannot emit signaling_server');
        }
        
        startCall(from);
        document.body.removeChild(callDiv);
    };

    document.getElementById('rejectCall').onclick = () => {
        console.log(`Вы отклонили звонок от пользователя с ID ${callerID}`);
        socket.emit('reject_new_call', { userSocketId: socket.id, callerSocketId: from, reason: "IGNORED" });
        endCall(); // Завершите вызов
        document.body.removeChild(callDiv);
    };
});

    function startCall(callerSocketId) {
        console.log(`Начинаем звонок с Caller Socket ID: ${callerSocketId}`);

        if (peerConnection) {
            peerConnection.close();
            peerConnection = null;
        }

        peerConnection = new RTCPeerConnection(configuration);

        navigator.mediaDevices.getUserMedia({ audio: true })
            .then(stream => {
                localStream = stream;
                localStream.getTracks().forEach(track => peerConnection.addTrack(track, localStream));

                peerConnection.onicecandidate = event => {
                    if (event.candidate) {
                        console.log('Отправка ICE-кандидата:', event.candidate);
                        
                     
                        console.log('Отправка ICE-кандидатаssss:', event.candidate.sdpMLineIndex);
                        
                       
                        socket.emit('signaling_server', { to: globalSocketId, from: socket.id, type:"offer", payload: {type: "offer", sdpMLineIndex: 0, sdpMid: "audio", sdp:event.candidate.candidate} });
                        
                    
                        
                        socket.emit('ice_candidate', {
    candidate: {
        candidate: event.candidate.candidate,
        sdpMid: event.candidate.sdpMid,
        sdpMLineIndex: event.candidate.sdpMLineIndex
    },
    to: globalSocketId,
    from: socket.id
});

                   
                        
                       console.dir(event);
                        console.log(socket.id);
                  
                        
                    }
                };

                peerConnection.ontrack = event => {
                    const remoteAudio = document.createElement('audio');
                    remoteAudio.srcObject = event.streams[0];
                    remoteAudio.autoplay = true; // Автоматическое воспроизведение
                    document.body.appendChild(remoteAudio);
                    console.log('Удаленный поток подключен.');
                };

                // Создание предложения
                peerConnection.createOffer()
                    .then(offer => {
                        console.log('Создано предложение:', offer);
                        return peerConnection.setLocalDescription(offer);
                    })
                    .then(() => {
                        console.log('Отправка предложения вызова:', peerConnection.localDescription);
                       // console.dir(userSocketId);
                        socket.emit('call_answer', {
                            sdp: peerConnection.localDescription.sdp,
                            to: globalSocketId,
                            type: peerConnection.localDescription.type// peerConnection.candidate
                        });
                    
                    socket.emit('signaling_server', { to: globalSocketId, from: socket.id, type:peerConnection.localDescription.type, payload:peerConnection.localDescription.sdp});
                    
                     console.log('Оdfggrа:', globalSocketId);
                    console.log('candidatess:', peerConnection.localDescription.sdp);
                   
                    })
                    .catch(error => {
                        console.error('Ошибка при создании предложения:', error);
                    });

            })
            .catch(error => {
                console.error('Ошибка доступа к аудиоустройству:', error);
            });
    }

    // Обработка предложения вызова
    socket.on('call_offer', (data) => {
        const offer = data.offer;
        const callerSocketId = data.from;
console.dir(data);
        console.log(`Получено предложение вызова от ${callerSocketId}:`, offer);
console.dir(data);
        if (!peerConnection) {
            peerConnection = new RTCPeerConnection(configuration);
        }

        peerConnection.setRemoteDescription(new RTCSessionDescription(offer))
            .then(() => {
                console.log('Удаленное описание установлено.');
            
                return peerConnection.createAnswer();
            })
            .then(answer => {
                return peerConnection.setLocalDescription(answer);
            })
            .then(() => {
                console.log('Отправка ответа на вызов:', peerConnection.localDescription);
                socket.emit('call_answer', {
                    answer: peerConnection.localDescription,
                    to: callerSocketId
                });
            
            })
            .catch(error => {
                console.error('Ошибка при обработке предложения вызова:', error);
            });
        console.dir(data);
    });

    socket.on('ice_candidate', (data) => {
    const candidate = data.candidate;
    console.log('Получен ICE-кандидат:', candidate); // Логирование кандидата для отладки
    
    // Проверка на наличие необходимых полей
    if (candidate && candidate.sdpMid !== null && candidate.sdpMLineIndex !== null) {
        peerConnection.addIceCandidate(new RTCIceCandidate(candidate))
            .then(() => {
                console.log('ICE-кандидат добавлен успешно');
            })
            .catch(error => {
                console.error('Ошибка при добавлении ICE-кандидата:', error);
            });
    } else {
        console.error('Получен некорректный ICE-кандидат:', candidate);
    }
});
        
        socket.on('signaling_server', (data) => {
    console.log('Получено сообщение:', data);
    console.dir(data);
    console.error('signaling_server Pl',data);
    // Проверка на наличие необходимых полей
    if (data.type === 'offer') {
        // Обработка предложения
        const offer = data.payload;
        console.log('Получено предложение:', offer);
        
        if (offer.sdp) {
            // Установка удаленного описания
            peerConnection.setRemoteDescription(new RTCSessionDescription(offer))
                .then(() => {
                    console.log('Удаленное описание установлено.');
                    // Создание ответа на предложение
                    return peerConnection.createAnswer();
                })
                .then(answer => {
                    return peerConnection.setLocalDescription(answer);
                })
                .then(() => {
                    console.log('Ответ на предложение отправлен:', peerConnection.localDescription);
                    socket.emit('call_answer', {
                        answer: peerConnection.localDescription,
                        to: data.from // Отправка ответа обратно
                    });
                })
                .catch(error => {
                    console.error('Ошибка при обработке предложения:', error);
                });
        }
    } else if (data.type === 'candidate') {
        // Обработка ICE-кандидата
        const candidate = data.payload;
        console.log('Получен ICE-кандидат:', candidate);
        
        if (candidate && candidate.sdpMid !== null && candidate.sdpMLineIndex !== null) {
            peerConnection.addIceCandidate(new RTCIceCandidate({
                candidate: candidate.candidate,
                sdpMid: candidate.sdpMid,
                sdpMLineIndex: candidate.sdpMLineIndex
            }))
            .then(() => {
                console.log('ICE-кандидат добавлен успешно');
            })
            .catch(error => {
                console.error('Ошибка при добавлении ICE-кандидата:', error);
            });
        } else {
            console.error('Получен некорректный ICE-кандидат:', candidate);
        }
    } else if (data.type === 'init') {
        // Обработка типа "init"
        console.log('Получено сообщение типа "init":', data);
        
        // Отправка сообщения типа "init" обратно
        console.dir(data);
        socket.emit('signaling_server', {
         
            
            type: 'init',
            from: socket.id,//socket.id,// Укажите, от кого отправляется сообщение
            to: data.from
            
         
        });
       // console.error('ssss:', data.from);
        console.dir(data);
        console.log('Полdfddd":', pizda);

    } else {
        console.error('Неизвестный тип сообщения:', data.type);
    }
});

        
      
        socket.on('ice_candidate', (data) => {
    const candidate = data.candidate;
    console.log('Получен ICE-кандидат:', candidate); // Логирование кандидата для отладки
    
    // Проверка на наличие необходимых полей
    if (candidate && candidate.sdpMid !== null && candidate.sdpMLineIndex !== null) {
        peerConnection.addIceCandidate(new RTCIceCandidate(candidate))
            .then(() => {
                console.log('ICE-кандидат добавлен успешно');
            })
            .catch(error => {
                console.error('Ошибка при добавлении ICE-кандидата:', error);
            });
    } else {
        console.error('Получен некорректный ICE-кандидат:', candidate);
    }
});

    // Функция для завершения вызова
    function endCall() {
        if (peerConnection) {
            socket.emit('hang_up_call', { callerSocketId: socket.id });
            peerConnection.close();
            peerConnection = null;
            console.log('Звонок завершен.');
        }
    }

    // Обработка завершения звонка
    socket.on('hang_up_call', (data) => {
        console.log(`Получено событие завершения вызова от ${data.callerSocketId}`);
        if (peerConnection) {
            peerConnection.close();
            peerConnection = null;
            console.log('Соединение закрыто.');
            console.dir(data);
        }
    });

    // Обработка отклонения звонка
    socket.on('reject_new_call', (data) => {
       // const { callerSocketId, rejectedBy } = data;
        console.log(`Звонок отклонен пользователем с ID: ${rejectedBy} от пользователя с ID: ${callerSocketId}`);
               if (peerConnection) {
            peerConnection.close();
            peerConnection = null;
            console.log('Соединение закрыто после отклонения вызова.');
        }
    });

    // Обработка принятия звонка
    socket.on('accept_new_call', (data) => {
      //  const { callerID, from } = data;
        const { callerID, from } = data;
        console.log(`Звонок принят пользователем с ID: ${data.callerSocketId}`);
       
         socket.emit('signaling_server', { to: data.userSocketId, from: data.callerSocketId, type:'init', payload:'payload'});
        
                    
        
        startCall(data.callerSocketId);
    });

    // Обработка завершения вызова по кнопке
    document.getElementById('endCallButton').addEventListener('click', () => {
        endCall();
    });

    </script>
</body>
</html>




My WebRTC server

app.js

/**
 * Created by abderrahimelimame on 9/24/16.
 */

var app = require('express')();
var server = require('http').Server(app);
//var server = require('https').Server(app);
var users = require('./users.js')();
var pingInterval = 25000;
var Socket = require('socket.io');
var io = Socket(server, {'pingInterval': pingInterval, 'pingTimeout': 60000});

/**
 * You can control those variables as you want
 */

var serverPort = 44333;
var app_key_secret = "7d3d3b6c2d3683bf25bbb51533ec6dab";
var debugging_mode = true;


/**
 * server listener
 */

var port = process.env.PORT || serverPort;
server.listen(port, function () {
    console.log('Server listening at port %d', port);
    

});


/**
 * this for check if the user connect from the app
 */
io.use(function (socket, next) {
        var token = socket.handshake.query.token;
        if (token === app_key_secret) {
            if (debugging_mode) {
                console.log("token valid  authorized", token);
            }
            next();
        } else {
            if (debugging_mode) {
                console.log("not a valid token Unauthorized to access ");
            }
            next(new Error("not valid token"));
        }
    }
);

/**
 * Socket.io event handling
 */
require('./socketHandler.js')(io, users, debugging_mode, pingInterval);



socketHandler.js

/**
 * Created by abderrahimelimame on 4/7/17.
 */

module.exports = function(io, users, debugging_mode, pingInterval) {

  io.on('connection', function(socket) {


    /*****************************************************************************************************************************************
     ********************************************* Users Connection Methods  *****************************************************************
     *****************************************************************************************************************************************/

    /**
     * Ping/Pong methods
     * */

    socket.on('socket_pong', function(data) {


      if (debugging_mode) {
        //    console.log("Pong received from client ");
      }
    });

    setTimeout(sendHeartbeat, pingInterval);

    function sendHeartbeat() {

      setTimeout(sendHeartbeat, pingInterval);
      io.sockets.emit('socket_ping', {
        beat: 1
      });
    }


    /**
     * method to save user as connected
     */
    socket.on('socket_user_connect', function(data) {
      if (debugging_mode) {
        console.log("the user with id " + data.connectedId + " connected " + +data.connected + " token " + data.userToken + "socket.id " + socket.id);
      }
      if (data.connectedId != null && data.connectedId != 0) {
        var user = users.getUser(data.connectedId);
        if (user != null) {
          users.updateUser(data.connectedId, data.connected, socket.id);
        } else {
          users.addUser(data.connectedId, data.connected, socket.id);
        }

        io.sockets.emit('socket_user_connect', {
          connectedId: data.connectedId,
          connected: true,
          socketId: data.socketId
        });

      }


    });


    /**
     * method if a user is disconnect from sockets
     * and then remove him from array of current users connected
     */
    socket.on('disconnect', function() {
      var usersArray = users.getUsers();
      if (usersArray.length != 0) {
        for (var i = 0; i < usersArray.length; i++) {
          var user = usersArray[i];
          if (user != null) {

            if (user.socketID == socket.id) {
              if (debugging_mode) {
                console.log("the user with id  " + user.ID + " is disconnect 1 ");
              }
              io.sockets.emit('socket_user_connect', {
                connectedId: user.ID,
                connected: false,
                socketId: user.socketID
              });

              users.removeUser(user.ID);
              if (debugging_mode) {
                console.log("the users list size disconnect " + usersArray.length);
              }
              break;
            }

          } else {
            if (debugging_mode) {
              console.log("the user is null disconnect ");
            }
          }


        }
      }
    });

    socket.on('socket_user_disconnect', function(data) {

      if (data.connectedId != null && data.connectedId != 0) {
        if (debugging_mode) {
          console.log("the user with id  " + data.connectedId + " is disconnect  2");
        }

        var user = users.getUserBySocketID(data.socketId);
        if (user != null) {

          io.sockets.emit('socket_user_connect', {
            connectedId: user.ID,
            connected: false,
            socketId: user.socketID
          });

          users.removeUser(user.ID);

        }
      }
    });


    /**
     * method to check if recipient is Online
     */
    socket.on('socket_is_online', function(data) {
      io.sockets.emit('socket_is_online', {
          senderId: data.senderId,
       //    senderId: "55536890679",
        connected: data.connected
      });
    });
    /**
     * method to check status last seen
     */
    /*      socket.on('socket_last_seen', function (data) {
              io.sockets.emit('socket_last_seen', {
                  lastSeen: data.lastSeen,
                  senderId: data.senderId,
                  recipientId: data.recipientId
              });
          });*/


    /*****************************************************************************************************************************************
     ********************************************* Single User Messages Methods  *****************************************************************
     *****************************************************************************************************************************************/



    socket.on('socket_update_register_id', function(data) {
      var user = users.getUser(data.recipientId);
      if (user != null) {
        socket.to(user.socketID).emit('socket_update_register_id', data);
      }
    });


    /*****************************************************************************************************************************************
     ********************************************* Users Call Methods  *****************************************************************
     *****************************************************************************************************************************************/

    /**
     * method to check if user is connected  before call him (do a ping and get a callback)
     */
    socket.on('socket_call_user_ping', function(data, callback) {
      if (debugging_mode)
        console.log("socket_call_user_ping called ");

      var user = users.getUser(data.recipientId);
      var pingedData;
      if (user != null) {
        console.log("socket id " + user.socketID);
        pingedData = {
          socketId: user.socketID,
          recipientId: data.recipientId,
          connected: true
        };
        callback(pingedData);
      } else {
        pingedData = {
          socketId: null,
          recipientId: data.recipientId,
          connected: false
        };
        callback(pingedData);
      }

    });

    /**
     * method to check if user is already on users array
     */
    socket.on('reset_socket_id', function(data, callback) {
      if (debugging_mode)
        console.log("reset_socket_id called " + data.userSocketId);
      var pingedData = {
        userSocketId: data.userSocketId
      };
      callback(pingedData);
    });

    /**
     * method make the connection between the too peer
     */
    socket.on('signaling_server', function(data) {
      if (debugging_mode)
        console.log("signaling_server called " + data.to);
      var socketId = data.to;
      /*var user = users.getUserBySocketID(data.to);
       if (user != null) {*/
      delete data.to;
      socket.to(socketId).emit('signaling_server', data);
      /*} else {
       console.log("user is null  signaling_server function ");
       //kolo adasnt skergh bach ighiga null nrj3 request bach ndir dialog this person is not available like whatsapp
       }*/

    });

    var makeCall = function(data) {
      if (debugging_mode)
        console.log("make_new_call function " + data.to);
      /* var user = users.getUserBySocketID(data.to);
       if (user != null) {*/
      socket.to(data.to).emit('receive_new_call', data);
      /*} else {
       console.log("user is null  make_new_call function ");
       //kolo adasnt skergh bach ighiga null nrj3 request bach ndir dialog this person is not available like whatsapp
       }*/

    };
    /**
     * method to initialize the new call
     */
    socket.on('make_new_call', makeCall);

    /**
     * method to Reject a call
     */
    socket.on('reject_new_call', function(data) {
      if (debugging_mode)
        console.log("reject_new_call function ");
      /* var user = users.getUserBySocketID(data.callerSocketId);
       if (user != null) {*/
      socket.to(data.callerSocketId).emit("reject_new_call", data);
      /*} else {
       console.log("user is null reject_new_call function ");
       }*/
    });


    /**
     * method to Accept a call
     */
    socket.on('accept_new_call', function(data) {
      if (debugging_mode)
        console.log("accept_new_call function ");
      /*var user = users.getUserBySocketID(data.callerSocketId);
       if (user != null) {
       */
      socket.to(data.callerSocketId).emit("accept_new_call", data);
      /*} else {
       console.log("user is null  accept_new_call function ");
       }*/
    });
    /**
     * method to HangUp a call
     */
    socket.on('hang_up_call', function(data) {
      if (debugging_mode)
        console.log("hang_up_call function ");
      /*      var user = users.getUserBySocketID(data.callerSocketId);
       if (user != null) {*/
      socket.to(data.callerSocketId).emit("hang_up_call", data);
      /*} else {
       console.log("user is null  hang_up_call function ");
       }*/
    });


  });
};

users.js

/**
 * Created by abderrahimelimame on 9/24/16.
 */
module.exports = function () {
    /**
     * available users
     * the id value is considered unique (provided by socket.io)
     */
    var usersList = [];

    /**
     * User object
     */
    var User = function (id, connected, socketID) {
        this.connected = connected;
        this.ID = id;
        this.socketID = socketID
    };

    return {
        addUser: function (id, connected, socketID) {
            var user = new User(id, connected, socketID);
            usersList.push(user);
        },

        removeUser: function (id) {
            var index = 0;
            while (index < usersList.length && usersList[index].ID != id) {
                index++;
            }
            usersList.splice(index, 1);
        },

        updateUser: function (id, connected, socketID) {
            var user = usersList.find(function (element, i, array) {
                return element.ID == id;
            });
            user.connected = connected;
            user.socketID = socketID;
        },

        getUser: function (id) {
            return usersList.find(function (element, i, array) {
                return element.ID == id;
            });
        },
        getUserBySocketID: function (socketID) {
            return usersList.find(function (element, i, array) {
                return element.socketID == socketID;
            });
        },

        getUsers: function () {
            return usersList;
        }
    }
};

Android app test https://dkon.app/dev/last_version/dkon.apk

I tried rearranging the variables and changing the logic, but I didn’t touch the server itself, as the server code cannot be modified, only the HTML file.

Brick masonry designer

I am developing a site for a brick factory and I need to implement a visual designer of brickwork. The user should be able to choose the color of the brick, type of masonry, the color of the solution, the format of brick, and also apply these parameters to the templates of houses (individual and multi -apartment) in order to see the final result in real time (a visual realistic picture of the house). It is necessary that the user can choose a brick at home and change its color in order to choose an interesting option for his home, site, etc. It is also considered that a fence, windows, roof, etc. and the possibility of editing are implemented. It is also necessary to realize the modules of baskets, survey, viewed goods, adaptive layout and the ability to easily add new colors or templates without changing code. Please advise how to implement the designer of brickwork, which technologies are best used for visualization (canvas, svg, webgl, three.js?), How to organize the structure of data and storage of masonry and brick options, which libraries or approaches are suitable for implementation, and how to build the project architecture (Fronte/Backend).

I just started the development and accept any advice, from those who somehow came across this and sees a possible solution

Next.js 15: Unable to serve static audio file from public directory

Problem Description

I’m trying to play an MP3 audio file in my Next.js 15 application, but the audio files in the public/audio/ directory are not being served. When I check the browser’s developer tools, the audio folder is not generated/served at all, although

Environment

  • Next.js: 15.3.5
  • Node.js: 22.14.0
  • Browser: Edge (latest)

Project Structure

sample-project/
├── public/
│ └── audio/
│  └── sample.mp3 (38KB file exists)
├── app/
│ └── todolist/
│  └── page.tsx
│  └── todoList.tsx
└── package.json

Code

todoList.tsx (relevant part):

const playDeleteSound = async () => {
  try {
    const audio = new Audio('/audio/sample.mp3');
    await audio.play();
  } catch (error) {
    console.log('Audio playback error:', error);
  }
};

What I’ve Tried

  1. Direct URL access: Accessing http://localhost:3000/audio/sample.mp3 returns 302
  2. Browser dev tools: No audio folder appears in the Sources tab

Expected Behavior

The MP3 file should be served as a static asset from the public directory, accessible at /audio/sample.mp3, just like images are served from public/images/.

Actual Behavior

  • 302 when accessing the audio file URL directly
  • No audio folder visible in developer tools
  • new Audio() fails to load the file

Questions

  1. Is there a specific configuration needed to serve audio files from the public directory?
  2. Are there any known limitations with static audio assets?
  3. What’s the recommended approach for handling audio files in Next.js 15?

Additional Notes

  • Images in public/images/ work perfectly fine
  • Designating a certain URL of mp3 file online as the parameter of Audio instead of ‘/audio/sample.mp3’ also works perfectly fine
  • File certainly exists and no mistakes with its file path (38KB MP3 file)

Any help would be greatly appreciated!

Context data not updating after navigation to route using same param but different component

I’m building a React app with React Router and a context provider that loads property data based on a propertyId route param.

In my App.jsx, I have the following routes:

<Route path="/edit/:propertyId" element={
  <PropertyContextProvider>
    <PublisherGuard>
      <PropertyCreateEditForm />
    </PublisherGuard>
  </PropertyContextProvider>
} />

<Route path="/properties/:propertyId" element={
  <PropertyContextProvider>
    <PropertyDetailsContainer />
  </PropertyContextProvider>
} />

<Route path="/my-properties/:propertyId" element={
  <PropertyContextProvider>
    <PublisherGuard>
      <UserProprty />
    </PublisherGuard>
  </PropertyContextProvider>
} />

After successfully editing a property at /edit/:propertyId, I redirect to /my-properties/${savedPropertyData.id}.

The navigation works, but the data displayed is stale — it’s the pre-edit version. If I manually refresh the page, the correct (updated) data appears.

Interestingly, navigating to /properties/${savedPropertyData.id} instead works perfectly — the updated data is shown immediately.

Here is the code for PropertyContextProvider:

export default function PropertyContextProvider({ children }) {
  const { propertyId } = useParams();
  const [propertyData, setPropertyData] = useState({});
  const [isPropertyDataLoaded, setIsPropertyDataLoaded] = useState(false);
  const navigate = useNavigate();

  useEffect(() => {
    if (propertyId !== undefined) {
      (async () => {
        try {
          const propertyData = await getById(propertyId);
          setPropertyData(propertyData);
          setIsPropertyDataLoaded(true);
        } catch (error) {
          if (error.status === 400 || error.status === 404) {
            navigate("/404");
          }
        }
      })();
    }
  }, [propertyId]);

  return (
    <PropertyContext.Provider value={{
      propertyId,
      propertyData,
      propertyCreatorId: propertyData.publisherId,
      isPropertyDataLoaded,
    }}>
      {children}
    </PropertyContext.Provider>
  );
}

Why does navigating to /properties/:id immediately reflect the updated data, but navigating to /my-properties/:id does not — even though both use the same context provider and same propertyId?

Could this be a rendering issue in UserProprty, or is React Router/Context behaving differently based on route structure?

Why WebTransport cannot connect to my server?

So first thing first, my problem is that when im trying to make a simple QUIC connection via new WebTransport('https://localhost') this request never reaches my server and immediatly terminating in Chrome with Failed to establish a connection to https://localhost/: net::ERR_CONNECTION_RESET. and Uncaught (in promise) WebTransportError: Opening handshake failed. console messages. In Firefox things slightly different and request do not terminating immediatly but after some time (approximately 10sec) im getting instance of WebTransporError in the console with a message: WebTransport connection rejected but yet again no signs of this request reaching my server.


So at this point i can think of two different sources for this problem: my SSL and my server code. Lets start with the former. As a server im using Deno under the --unstable-net flag with this simplified code:

const key = Deno.readTextFileSync('./SSL/Self-signed.key'),
cert = Deno.readTextFileSync('./SSL/Self-signed.crt')

Deno.serve({ port: 443, key, cert }, ()=>new Response('Hello World!'))

const endpoint = new Deno.QuicEndpoint,
listener = endpoint.listen({ alpnProtocols: ['h2', 'h3', 'idc'], key, cert }),
conn = await listener.incoming()
console.log('New connection: ', conn)

This code works for the purpose of serving HTTPS connections cos im getting this Hello World! message on my browser screen when navigate to https://localhost. But the final line of the code is never reached which means that this code fails for the purpose of serving QUIC connections. I cant really tell where is a problem can be cos i simplify this code as far as possible.


And now for certificates. Im working in Windows and generating self-signed certificates through this handwritten batch file that is again simplified and now also commented for the research purpose:

@echo off
set OPENSSL_HOME=%~dp0openssl-3
set OPENSSL_CONF=%OPENSSL_HOME%/ssl/openssl.cnf
PATH=%PATH%;"%OPENSSL_HOME%/x64/bin"

::Generate signatory ECDSA key
openssl ecparam -genkey -out "%~dp0rootKey.key" -name prime256v1

::Generate authority from key
openssl req -x509 -new -nodes -key "%~dp0rootKey.key" -days 13 -out "%~dp0rootCA.pem" -subj "/C=UA/ST=UA/O=UA"

::Adding authority to the Windows trust store so that browsers can obey
certutil -addstore -f -enterprise -user root "%~dp0rootCA.pem"

::Generate new sign request and public key
openssl req -new -nodes -out "%~dp0signRequest.csr" -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -keyout "%~dp0/../Self-signed.key" -subj "/C=UA/ST=UA/O=UA"

::Generate new self-signed ECDSA certificate
openssl x509 -req -in "%~dp0signRequest.csr" -CA "%~dp0rootCA.pem" -CAkey "%~dp0rootKey.key" -out "%~dp0/../Self-signed.crt" -days 13 -extfile "%~dp0extfile"

::Content of the "extfile":

::authorityKeyIdentifier=keyid,issuer
::basicConstraints=CA:FALSE
::keyUsage=digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment
::subjectAltName=IP:127.0.0.1,DNS:localhost,DNS:*.localhost

::Saving certificates HASH
openssl x509 -noout -fingerprint -sha256 -noout -in "%~dp0/../Self-signed.crt">"%~dp0HASH"
set /p fp=<"%~dp0HASH"
echo %fp:~19%>"%~dp0HASH"

pause

With this pair of key and certificate im able to serve HTTPS connections without adding any flags to the browsers but no luck for QUIC connections. On MDN page about WebTransport there is a list of requirements for a certificate:

The certificate must be an X.509v3 certificate that has a validity period of less that 2 weeks, and the current time must be within that validity period. The format of the public key in the certificate depends on the implementation, but must minimally include ECDSA with the secp256r1 (NIST P-256) named group, and must not include RSA keys. An ECSDA key is therefore an interoperable default public key format.

So i can assume that my certificate should be passable under those requirements but still it seems like browsers are refusing to establishing QUIC connection with my server despite having no problems with HTTPS ones.


As my last resort i tried this serverCertificateHashes option for the WebTransport instance. Im not really sure what this option doing and especially what am i doing but i found this piece of code below somewhere in the internet and combine it with my certificate hash which was produced by the last command of my batch file and throw it all into the browsers console for this final picture:

function base64ToArrayBuffer(base64) {
  var binaryString = atob(base64);
  var bytes = new Uint8Array(binaryString.length);
  for (var i = 0; i < binaryString.length; i++) {
    bytes[i] = binaryString.charCodeAt(i);
  }
  return bytes.buffer;
}
new WebTransport('https://localhost', {
  serverCertificateHashes: [
    {
      algorithm: 'sha-256',
      value: base64ToArrayBuffer(btoa(`92:49:72:24:FB:2D:84:D2:0B:5B:A0:1A:F3:0A:6D:60:B5:E2:12:25:7D:2B:60:47:FF:DD:BF:32:33:57:60:53`))
    }
  ]
});

But yet again no luck here. Resaults are exactly the same in both browsers. Im stuck with this problem for a few days now and definetly in need of some advice.

Import module installed with npm without node.js

Starting to take up Javascript again, it seemed the right moment to move away from the <script> tags and start using module imports.
I’m not using any framework and want to run on a classic apache webserver.

I’ve been struggling to get quite a few libraries to work in plain ES6. I wonder if i’m just not understanding things, or that quite some libraries are not suited for this approach (and expect react/vue/angular to be used).

More specifically currently i’m struggling to import the mapbox gl js library.
I used npm to install mapbox-gl, which installed the package and its dependencies in new /node_modules directory, which I moved to the /src directory.

I’ve an index.html containing:

<script type="module" src="src/index.js"></script>

in index.js

import mapboxgl from './src/node_modules/mapbox-gl/dist/mapbox-gl.js';

This returns following error:

Uncaught SyntaxError: The requested module './src/node_modules/mapbox-gl/dist/mapbox-gl.js' does not provide an export named 'default' 

I’ve been searching around and found the link below. Am I doing something wrong, or is the mapBox library, like quite a few others, just not foreseen to be used in plain ES6? Do i have to rely on cdn’s like esm.sh to deliver a compatible version, or can I handle this myself with the package installed through npm?

Relevant github mapbox discussion: https://github.com/mapbox/mapbox-gl-js/issues/8676

Why not call a fetch function eagerly when it is not even awaited

I get this message in my terminal when running my svelte frontend:

Avoid calling `fetch` eagerly during server side rendering — put your `fetch` calls inside `onMount` or a `load` function instead

I understand what it says and I can definitely put it in an onMount function, however, I don’t see the meaning of it. Imagine this example application, that is close to how I use it:

<script lang="ts">
  let response: Promise<string> = $state(loadData());

  async function loadData(): Promise<string> {
     const response = await fetch("http://my_endpoint");
     return response.json();
  }
</script>

{#await response}
  LOADING
{:then response}
  {response}
{/await}

What I am trying to point at is that the async function loadData is not awaited in the script tag. Only via the await directive in the template. I don’t see how this could be blocking more than any other normal function call. I wonder if that is just a case that was overlooked when programming this warning or if I create a real mistake that will bite me in the ass in a larger project.