WebGL build is giving errors after I added my own location input

I am building a location based game in unity as a WebGL build. The file was building before I added my script changes but the location input was not working on site (Hosted on itch.io). I then added a javascript file and some changes to the location services (The location input script was imported from Mapbox api) using chatgpt. Now the file itself is not building.

javascript file:

var EXPORTED_FUNCTIONS = ['_requestWebGLLocation'];
mergeInto(LibraryManager.library, {
    requestWebGLLocation: function() {
        if (navigator.geolocation) {
            navigator.geolocation.getCurrentPosition(
                function(position) {
                    unityInstance.SendMessage('LocationProviderFactory', 
                    'OnLocationReceived',
                        position.coords.latitude + ',' +  
                     position.coords.longitude);
                },
                function(error) {
                    console.error('Error obtaining location: ', error);
                }
            );
        } else {
            console.error('Geolocation is not supported by this browser.');
        }
    }
})

Location Input code:

#if !UNITY_EDITOR
#define NOT_UNITY_EDITOR
#endif

namespace Mapbox.Unity.Location
{
    using UnityEngine;
    using Mapbox.Unity.Map;
    using System.Text.RegularExpressions;
    using System.Runtime.InteropServices;


    /// <summary>
    /// Singleton factory to allow easy access to various LocationProviders.
    /// This is meant to be attached to a game object.
    /// </summary>
    public class LocationProviderFactory : MonoBehaviour
    {
        [SerializeField]
        public AbstractMap mapManager;

        [SerializeField]
        [Tooltip("Provider using Unity's builtin 'Input.Location' service")]
        AbstractLocationProvider _deviceLocationProviderUnity;

        [SerializeField]
        [Tooltip("Custom native Android location provider. If this is not set above 
        provider is used")]
        DeviceLocationProviderAndroidNative _deviceLocationProviderAndroid;

        [SerializeField]
        AbstractLocationProvider _editorLocationProvider;

        [SerializeField]
        AbstractLocationProvider _transformLocationProvider;

        [SerializeField]
        bool _dontDestroyOnLoad;

        [DllImport("__Internal")]
        private static extern void requestWebGLLocation();



        /// <summary>
        /// The singleton instance of this factory.
        /// </summary>
        private static LocationProviderFactory _instance;
        public static LocationProviderFactory Instance
        {
            get
            {
                return _instance;
            }

            private set
            {
                _instance = value;
            }
        }

        ILocationProvider _defaultLocationProvider;

        /// <summary>
        /// The default location provider. 
        /// Outside of the editor, this will be a <see 
        cref="T:Mapbox.Unity.Location.DeviceLocationProvider"/>.
        /// In the Unity editor, this will be an <see 
        cref="T:Mapbox.Unity.Location.EditorLocationProvider"/>
        /// </summary>
        /// <example>
        /// Fetch location to set a transform's position:
        /// <code>
        /// void Update()
        /// {
        ///     var locationProvider = 
        LocationProviderFactory.Instance.DefaultLocationProvider;
        ///     transform.position = 
        Conversions.GeoToWorldPosition(locationProvider.Location,
        ///                                                         
        MapController.ReferenceTileRect.Center,
        ///                                                         
        MapController.WorldScaleFactor).ToVector3xz();
        /// }
        /// </code>
        /// </example>
        public ILocationProvider DefaultLocationProvider
        {
            get
            {
                return _defaultLocationProvider;
            }
            set
            {
                _defaultLocationProvider = value;
            }
        }

        /// <summary>
        /// Returns the serialized <see 
        cref="T:Mapbox.Unity.Location.TransformLocationProvider"/>.
        /// </summary>
        public ILocationProvider TransformLocationProvider
        {
            get
            {
                return _transformLocationProvider;
            }
        }

        /// <summary>
        /// Returns the serialized <see 
        cref="T:Mapbox.Unity.Location.EditorLocationProvider"/>.
        /// </summary>
        public ILocationProvider EditorLocationProvider
        {
            get
            {
                return _editorLocationProvider;
            }
        }

        /// <summary>
        /// Returns the serialized <see 
        cref="T:Mapbox.Unity.Location.DeviceLocationProvider"/>
        /// </summary>
        public ILocationProvider DeviceLocationProvider
        {
            get
            {
                return _deviceLocationProviderUnity;
            }
        }

        /// <summary>
        /// Create singleton instance and inject the DefaultLocationProvider upon 
        Initialization of this component. 
        /// </summary>
        protected virtual void Awake()
        {
            if (Instance != null)
            {
                DestroyImmediate(gameObject);
                return;
            }
            Instance = this;

            if (_dontDestroyOnLoad)
            {
                DontDestroyOnLoad(gameObject);
            }

            InjectEditorLocationProvider();
            InjectDeviceLocationProvider();
        }

        /// <summary>
        /// Injects the editor location provider.
        /// Depending on the platform, this method and calls to it will be stripped 
        during compile.
        /// </summary>
        [System.Diagnostics.Conditional("UNITY_EDITOR")]
        void InjectEditorLocationProvider()
        {
            Debug.LogFormat("LocationProviderFactory: Injected EDITOR Location Provider 
        - {0}", _editorLocationProvider.GetType());
            DefaultLocationProvider = _editorLocationProvider;
        }

        /// <summary>
        /// Injects the device location provider.
        /// Depending on the platform, this method and calls to it will be stripped 
        during compile.
        /// </summary>
        [System.Diagnostics.Conditional("NOT_UNITY_EDITOR")]
        void InjectDeviceLocationProvider()
        {
            if (Application.platform == RuntimePlatform.WebGLPlayer)
            {
                Debug.Log("Using WebGL Geolocation.");
                requestWebGLLocation();
            }
            else
            {
                int AndroidApiVersion = 0;
                var regex = new Regex(@"(?<=API-)-?d+");
                Match match = regex.Match(SystemInfo.operatingSystem);
                if (match.Success) { int.TryParse(match.Groups[0].Value, out 
                AndroidApiVersion); }
                Debug.LogFormat("{0} => API version: {1}", SystemInfo.operatingSystem, 
                AndroidApiVersion);

                if (Application.platform == RuntimePlatform.Android && 
                AndroidApiVersion >= 24)
                {
                    DefaultLocationProvider = _deviceLocationProviderAndroid;
                }
                else
                {
                    DefaultLocationProvider = _deviceLocationProviderUnity;
                }
            }
        }

        public void OnLocationReceived(string locationData)
        {
            string[] coordinates = locationData.Split(',');
            if (coordinates.Length == 2)
            {
                float latitude = float.Parse(coordinates[0]);
                float longitude = float.Parse(coordinates[1]);
                Debug.Log($"WebGL Location Received: Latitude: {latitude}, Longitude: 
                {longitude}");
                // You can further process this location data as required
            }
        }

    }
}

Build errors:

  1. LibraryBeeartifactsWebGLbuilddebug_WebGL_wasmbuild.js:
    undefined symbol: requestWebGLLocation (referenced by top-level
    compiled C/C++ code)
    UnityEngine.GUIUtility:ProcessEvent (int,intptr,bool&)

  2. LibraryBeeartifactsWebGLbuilddebug_WebGL_wasmbuild.js:
    Aborting compilation due to previous errors
    UnityEngine.GUIUtility:ProcessEvent (int,intptr,bool&)

  3. Building LibraryBeeartifactsWebGLbuilddebug_WebGL_wasmbuild.js failed with output:
    error: undefined symbol: requestWebGLLocation (referenced by top-level compiled C/C++ code)
    warning: Link with -s LLD_REPORT_UNDEFINED to get more information on undefined symbols
    warning: To disable errors for undefined symbols use -s ERROR_ON_UNDEFINED_SYMBOLS=0
    warning: _requestWebGLLocation may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library
    Error: Aborting compilation due to previous errors
    emcc: error: ‘”C:/Program Files/Unity/Hub/Editor/2022.3.46f1/Editor/Data/PlaybackEngines/WebGLSupport/BuildTools/Emscripten/node/node.exe” “C:Program FilesUnityHubEditor2022.3.46f1EditorDataPlaybackEnginesWebGLSupportBuildToolsEmscriptenemscriptensrccompiler.js” C:UsersNiftyAppDataLocalTemptmpmbvsgucj.json’ failed (returned 1)
    UnityEngine.GUIUtility:ProcessEvent (int,intptr,bool&)

Node.js Fetch Request to WordPress REST API Times Out for Large Content

I’m trying to post content to a WordPress site using the REST API from a Node.js script. The request works perfectly with small content or when using curl. However, when I send a larger payload (e.g., a multiline string), the fetch request times out with the following error:

Error: FetchError: request to https://example.com/wp-json/wp/v2/posts failed, reason: ETIMEDOUT

What I’ve Tried:

Testing with curl:

curl -X POST https://example.com/wp-json/wp/v2/posts 
-u "username:application-password" 
-H "Content-Type: application/json" 
-d '{"title":"Test Post","content":"This is a 
test.","status":"publish"}'

Question:

What could be causing the ETIMEDOUT error for larger content in Node.js, even though curl handles it fine? How can I resolve this issue?

The length of the provided content is 4842 characters. ​​

How to disable vertical scroll during horizontal swipe on a slider?

I’m working on a slider, and I want to disable the vertical page scroll when the user performs a horizontal swipe gesture on the slider.

My initial idea was to check if the finger moved more than 50px along the X-axis and, if so, block the vertical scroll. I tried using preventDefault() to prevent the scroll behavior, but I kept running into issues and unexpected behavior.

Here’s what I tried:

Captured the touchstart event to record the initial touch position.
Listened to touchmove to track how much the touch moved along the X and Y axes.
If the horizontal movement (X-axis) exceeded 50px, I called event.preventDefault() to block the vertical scroll.
However, this approach turned out to be unreliable: sometimes the scroll wasn’t blocked as expected, and other times it blocked the scroll when it shouldn’t have.

Limitation:
Using overflow: hidden to disable scrolling isn’t an option because it causes other issues in my UI.

Question:
What is the best way to reliably disable vertical scrolling during horizontal swipe gestures? Is there a better approach to handle this using JavaScript?

    const videoCardsEls = [...document.querySelectorAll('.video_card')];
const sliderRobotWrapperEls = [...document.querySelectorAll('.slider_robot_wrapper')];
const sliderShoppingWrapperEls = [...document.querySelectorAll('.slider_shopping_wrapper')];

const buttonPrevEls = [...document.querySelectorAll('.button_prev')];
const buttonNextEls = [...document.querySelectorAll('.button_next')];

const sliderTrackEls = [...document.querySelectorAll('.slider_track')];

const paginationCirclesEls = [...document.querySelectorAll('.pagination_circles')];
const configureSlider = ({
                             slidesEls,
                             paginationCirclesContainerEl,
                             sliderTrackEl,
                             buttonNextEl,
                             buttonPrevEl,
                             visibleSlidesCount
                         }) => {
    const currentSlideIndex = {value: visibleSlidesCount};

    let isAnimating = false;
let startX = 0;
    let currentX = 0;
    let isDragging = false;

    const swipeThreshold = 50;
    const minScreenWidthForSwipe = 1024;

    const startDrag = e => {
        if (isAnimating) return;
        isAnimating = true;

        const isVideoSlider = sliderTrackEl === sliderTrackEls[0];
        if (isVideoSlider && window.innerWidth >= minScreenWidthForSwipe) return;

        isDragging = true;

        startX = e.type === 'touchstart' ? e.touches[0].clientX : e.clientX;
        currentX = startX;

        sliderTrackEl.style.transition = 'none';
    };

    const moveDrag = e => {
        if (!isDragging) return;

        currentX = e.type === 'touchmove' ? e.touches[0].clientX : e.clientX;
        const diff = currentX - startX;

        const offset = currentSlideIndex.value * slideWidth;


        sliderTrackEl.style.transform = `translateX(${-offset + diff}px)`;
    };

    const endDrag = () => {
        if (!isDragging) return;
        isDragging = false;

        const diff = currentX - startX;

        sliderTrackEl.style.transition = 'transform 0.5s';

        if (Math.abs(diff) > swipeThreshold) {
            if (diff < 0) {
                nextSlide({
                    currentSlideIndex,
                    sliderTrackEl,
                    slideWidth,
                    slidesEls,
                    paginationCirclesContainerEl,
                    visibleSlidesCount
                });
            } else {
                prevSlide({
                    currentSlideIndex,
                    sliderTrackEl,
                    slideWidth,
                    slidesEls,
                    paginationCirclesContainerEl,
                    visibleSlidesCount
                });
            }
        } else {
            updateSliderPosition({
                withTransition: true,
                currentSlideIndex,
                sliderTrackEl,
                slideWidth
            });
        }
        setTimeout(() => {
            isAnimating = false;
        }, 500);
    };

    const addDragEvents = sliderTrackEl => {
        sliderTrackEl.addEventListener('touchstart', startDrag, {passive: true});
        sliderTrackEl.addEventListener('touchmove', moveDrag, {passive: true});
        sliderTrackEl.addEventListener('touchend', endDrag);

        sliderTrackEl.addEventListener('mousedown', startDrag);
        sliderTrackEl.addEventListener('mousemove', moveDrag);
        sliderTrackEl.addEventListener('mouseup', endDrag);

        sliderTrackEl.addEventListener('mouseleave', endDrag);
    };
    addDragEvents(sliderTrackEl);
};
configureSlider({
    slidesEls: videoCardsEls,
    paginationCirclesContainerEl: paginationCirclesEls[0],
    sliderTrackEl: sliderTrackEls[0],
    visibleSlidesCount: 2,
});
configureSlider({
    slidesEls: sliderRobotWrapperEls,
    paginationCirclesContainerEl: paginationCirclesEls[1],
    sliderTrackEl: sliderTrackEls[1],
    buttonNextEl: buttonNextEls[0],
    buttonPrevEl: buttonPrevEls[0],
    visibleSlidesCount: 3,
});
configureSlider({
    slidesEls: sliderShoppingWrapperEls,
    paginationCirclesContainerEl: paginationCirclesEls[2],
    sliderTrackEl: sliderTrackEls[2],
    buttonNextEl: buttonNextEls[1],
    buttonPrevEl: buttonPrevEls[1],
    visibleSlidesCount: 4,
});

Trying to use brain.js from CDN in a react app but getting an error

I’m trying to call brains.js inside component from brain.js CDN, this is what I have in my code App.js:

  import { useEffect } from 'react';
  import logo from './logo.svg';
  import './App.css';

  function App() {
    useScript('https://unpkg.com/brain.js');

    function test() {
      var net = new brain.recurrent.LSTM()
    
      net.train([
        'doe, a deer, a female deer',
        'ray, a drop of golden sun',
        'me, a name I call myself',
      ], {
        iterations: 1500,
        log: details => console.log(details),
        errorThresh: 0.011
      });
    
      var output = net.run('doe') // ', a deer, a female deer'
      const myOutput = document.querySelector('#myOutput');
      myOutput.innerHTML = output;
      console.log(output)
    }

    const useScript = url => {
      
      const script = document.createElement('script');
    
      script.src = url;
      script.async = true;
      console.log("script");
      document.body.appendChild(script);
      test();
    };
    return (
      <div id="myOutput"></div>
    );
  }

  export default App;

And I get this error:

ERROR in [eslint] 
srcApp.js
Line 9:27:  'brain' is not defined  no-undef

Search for the keywords to learn more about each error.

Why does value change even if I bool is false for my password property

Here is my code. I am setting property values as false but the property result still changes.

const user = {
  password: "prateeksharma",
  city: "shamli"
}
const chai = Object.getOwnPropertyDescriptor(user, 'password')
console.log(chai)


Object.defineProperty(user, 'password', {
  writable: false,
  enumerable: false,
  configurable: false
});

const tea = user.password = "pandit@123"
console.log(tea)

expanding images on clickand a media queries, query

Firstly the media query I’m having issue with is scaling an image within a flexbox to fit the screen on multiple devices.

Secondly I am having an issue where my Javascript ‘onClick’ modal is ultimately changing my layout to the point I’ve had to shelf it for the time being.

HTML – the images are at 150px^2

  <div class ="flex-container">
               <div><img src="./images/placeholder.jpg" alt="box 1" id="myImg" onclick="openModal(this.src)"></div>
               <div><img src="./images/iplaceholder.jpg" alt="box 2" id="myImg" onclick="openModal(this.src)"></div>
               <div><img src="./images/placeholder alt="box 3" id="myImg" onclick="openModal(this.src)"></div>
   </div>
            
            <div id="myModal" class="modal">
                <span class="close">&times;</span>
                <img class="modal-content" id="img01">
                <div id="caption"></div>
            </div>

CSS

.flex-container {
  display: flex;
  flex-wrap: wrap;
  background-color: transparent;
}
.flex-container > div {
  background-color: transparent;
  width: 150px;
  height: 150px;
  margin: 10px;
  text-align: center;
  line-height: 75px;
  font-size: 30px;
}
.modal {
  display: none; /* Hidden by default */
}

and finally Javascript

function openModal(imgSrc) {
    var modal = document.getElementById("myModal");
    
    var img = document.getElementById("myImg");
    var modalImg = document.getElementById("img01");
        
    modal.style.display = "block";
    modalImg.src = imgSrc;
}

The desired layout little ones are images to be clicked on and expanded either above ore below

Vs what I am getting on click it forces all images to one side, which is not too much of an issue, the problem is while it does that it expands the page

My media queries at the moment are just ones I have seen in tutorials as I’m reading/watching them. so I have currently not found what i am looking for.

obile container utility class:
.container {
    width: 100%;
    margin-left: auto;
    margin-right: auto;
    padding-left: 0.5rem;
    padding-right: 0.5rem;
}

/* xs */
@media (min-width: 475px) {
    .container {
        max-width: 475px;
    }
}
/* sm */
@media (min-width: 640px) {
    .container {
        max-width: 640px;
    }
}
/* md */
@media (min-width: 768px) {
    .container {
        max-width: 768px;
    }
}
@media screen and (max-width:150px && max-height: 150px) {
    #MyImg {
        width: 100%;
        height: 100%;
    }

Any help or pointers would be appreciated

A page that can fit every screen size, have images to scale pop up on click(within the page) without compromising the layout or screen size

Error in Firestore authentication with NextJS

So I am using NextJS and next-firebase-auth-edge library to handle Firebase authentication. All the cookie and session management is handled by next-firebase-auth-edge. When I make a Firestore query right after sign in/sign up, the query is successful. However, when I refresh the page, and redo the query, Firestore responds with a 404, insufficient permission.

I followed the instructions for service workers from here in which the fetch listener will insert the firebase token in headers of every request so that Firestore could authenticate the request

Following is my auth-service-worker.js file

import { initializeApp } from "firebase/app";
import { getAuth, onAuthStateChanged, getIdToken } from "firebase/auth";

// Initialize the Firebase app in the service worker script.
initializeApp(config);

/**
 * Returns a promise that resolves with an ID token if available.
 * @return {!Promise<?string>} The promise that resolves with an ID token if
 *     available. Otherwise, the promise resolves with null.
 */
const auth = getAuth();
const getIdTokenPromise = () => {
  return new Promise((resolve, reject) => {
    const unsubscribe = onAuthStateChanged(auth, (user) => {
      unsubscribe();
      if (user) {
        getIdToken(user).then((idToken) => {
          resolve(idToken);
        }, (error) => {
          resolve(null);
        });
      } else {
        resolve(null);
      }
    });
  });
};

const getOriginFromUrl = (url) => {
  // https://stackoverflow.com/questions/1420881/how-to-extract-base-url-from-a-string-in-javascript
  const pathArray = url.split('/');
  const protocol = pathArray[0];
  const host = pathArray[2];
  return protocol + '//' + host;
};

// Get underlying body if available. Works for text and json bodies.
const getBodyContent = (req) => {
  return Promise.resolve().then(() => {
    if (req.method !== 'GET') {
      if (req.headers.get('Content-Type').indexOf('json') !== -1) {
        return req.json()
          .then((json) => {
            return JSON.stringify(json);
          });
      } else {
        return req.text();
      }
    }
  }).catch((error) => {
    // Ignore error.
  });
};

self.addEventListener('fetch', (event) => {
  /** @type {FetchEvent} */
  const evt = event;

  const requestProcessor = (idToken) => {
    let req = evt.request;
    let processRequestPromise = Promise.resolve();
    // For same origin https requests, append idToken to header.
    if (self.location.origin == getOriginFromUrl(evt.request.url) &&
        (self.location.protocol == 'https:' ||
         self.location.hostname == 'localhost') &&
        idToken) {
      // Clone headers as request headers are immutable.
      const headers = new Headers();
      req.headers.forEach((val, key) => {
        headers.append(key, val);
      });
      // Add ID token to header.
      headers.append('Authorization', 'Bearer ' + idToken);
      processRequestPromise = getBodyContent(req).then((body) => {
        try {
          req = new Request(req.url, {
            method: req.method,
            headers: headers,
            mode: 'same-origin',
            credentials: req.credentials,
            cache: req.cache,
            redirect: req.redirect,
            referrer: req.referrer,
            body,
            // bodyUsed: req.bodyUsed,
            // context: req.context
          });
        } catch (e) {
          // This will fail for CORS requests. We just continue with the
          // fetch caching logic below and do not pass the ID token.
        }
      });
    }
    return processRequestPromise.then(() => {
      return fetch(req);
    });
  };
  // Fetch the resource after checking for the ID token.
  // This can also be integrated with existing logic to serve cached files
  // in offline mode.
  evt.respondWith(getIdTokenPromise().then(requestProcessor, requestProcessor));
});

self.addEventListener('activate', (event) => {
    event.waitUntil(clients.claim());
});

The error after registering this service worker
Uncaught SyntaxError: Cannot use import statement outside a module (at auth-service-worker.js:1:1)

Rules in my Firestore

match /users/{userId} {
        allow read, create, update, write: if resourceMatchesUID(userId);
    }

function resourceMatchesUID(userId) {
        return request.auth.uid == userId;
    }    

React.js library for a Gantt/timeline chart with resizable, non-overlapping tasks [closed]

I’m searching for a React.js library (open source) that provides functionality similar to the attached image:

  • A Gantt chart or timeline component where tasks can be displayed along a timeline.

  • Each task should have a title and should be resizable to adjust the time range interactively.

  • Non-overlapping tasks: The component should prevent tasks from overlapping, as shown in the image (e.g., the green task cannot overlap with the red or blue tasks).

  • Ideally, the library would allow for drag-and-drop adjustments of tasks.

    Does anyone know of a React library that provides this functionality out of the box? Open-source solutions are preferred, but I’m open to commercial options if necessary.

    Any suggestions or examples would be greatly appreciated!

    enter image description here

Can we place the js files mentioned in manifest.json in different folders for building a chrome extension in React?

I’m currently trying to build a chrome extension using React.
I will be using chrome API’s for using the functionality which requires background.js and content.js where the main app logic will be written.

I’m new to this and I wanted to know why the above mentioned js files need to be placed in public folder of the React App?

Can we place the same file in different path of the App and mention the same in manifest.json? If so, can you please tell me how to do that

Video Upload Format Issue in Safari on Mac and iPhone Using MediaRecorder

I’m currently working on a project that in one part,
we should record a video from users front camera or webcam,
and then send the recorded video to backend for user verifying.
This is how I record the video:

  const startRecording = () => {
    setShouldShowPreRecordingTimer(false);
    if (videoRef.current) {
      const stream = videoRef.current.srcObject as MediaStream;
      const recorder = new MediaRecorder(stream, {
        mimeType: returnVideoMimeType(),
        videoBitsPerSecond: 250000,
      });
      recorder.ondataavailable = handleDataAvailable;
      recorder.start();
      setMediaRecorder(recorder);
    }
  };
  const startRecording = () => {
    setShouldShowPreRecordingTimer(false);
    if (videoRef.current) {
      const stream = videoRef.current.srcObject as MediaStream;
      const recorder = new MediaRecorder(stream, {
        mimeType: returnVideoMimeType(),
        videoBitsPerSecond: 250000,
      });
      recorder.ondataavailable = handleDataAvailable;
      recorder.start();
      setMediaRecorder(recorder);
      setIsRecording(true);
      setRecordingTimer(RECORDING_TIME);
    }
  };

  const stopRecording = () => {
    if (mediaRecorder) mediaRecorder.stop();
  };

  const handleDataAvailable = (event: BlobEvent) => {
    if (event.data.size > 0) {
      setRecordedChunks((prev) => [...prev, event.data]);
    }
  };

and to ensure that the mime type is supported by the browser, I wrote this function:

export const returnVideoMimeType = () => {
  const mimeTypes = [
    'video/mp4;codecs=avc1.42E01E,mp4a.40.2',
    'video/webm;codecs=vp9,opus',
    'video/webm;codecs=vp8,opus',
    'video/webm',
    '',
  ];

  if (MediaRecorder.isTypeSupported) {
    return (
      mimeTypes.find((mimeType) => MediaRecorder.isTypeSupported(mimeType)) ||
      ''
    );
  }

  return 'video/mp4;codecs=avc1.42E01E,mp4a.40.2';
};

and this is the formats that are supported for the backend endpoint:

png,jpeg,bmp,mpeg,webm,3gp,avi,ogg,mp4,mov,wmv,gif,doc,zip,rar,pdf,docx

Now when I try to test this in Chrome or firefox or edge, It’s working correctly and uploading the video.
But whenever I try to upload in on a mac or an Iphone I get the error that the format of the file is not supported, I’ve checked the mime type returned in safari and it’s

'video/mp4;codecs=avc1.42E01E,mp4a.40.2'

I’ve tried uploading it in chrome with the same mime type and it worked correctly.
In Safari, the recording works correctly without an issue, the preview of recorded video works fine too, but for some reason it seems like it’s changing the final mime type to something else.
I also use this video constraints when starting the camera incase they have any issue:

const videoConstraints = {
  video: {
    width: { max: 960 }, // Reduce resolution to 640px width
    height: { max: 1280 },
    frameRate: { max: 30 }, // Lower frame rate reduces file size
    facingMode: 'user',
  },
  audio: true,
};

Any ideas why upload in safari is not working correctly?

Debounce a function with a dynamic delay based input

I would like to debounce a function in JavaScript with a dynamic delay based on the user input. This delay shall base on the length of the input string. The longer the input the longer the delay.

With my code the method gets triggered multiple times or it’s delayed too much:

let debounceTimeout;

function dynamicDebounce(fn, input) {
const delay = Math.min(500 + input.length * 20, 2000);
clearTimeout(debounceTimeout);

debounceTimeout = setTimeout(() => {
    fn(input);
}, delay);
}

function handleInputChange(input) {
console.log("User input:", input);
}
document.querySelector('input').addEventListener('input', function(event) {
dynamicDebounce(handleInputChange, event.target.value);
});

How to fix it?

Why does my calculator display “undefined” when deleting the last character?

I have attempted to implement a delete button to my calculator that deletes the last digit that the user has typed. When I tested the button, it just added “undefined” to the end of the equation.

This is my code:

deleteButton.addEventListener("click", () => {
    if (calcString.length > 0) {
        calcString = calcString.slice(0, -1);
        resultText.textContent = calcString || "0";
        display.textContent = calcString.slice(-1) || "0";
    } else {
        calcString = "";
        resultText.textContent = "0";
        display.textContent = "0";
    }
});

My full code:

const display = document.getElementById("display");
const buttons = document.querySelectorAll(".btn");
const copyButton = document.getElementById("copy");
const resultText = document.getElementById("result");

const rootModal = document.getElementById("rootModal");
const closeModal = document.getElementById("closeModal");
const rootInput = document.getElementById("rootInput");
const submitRoot = document.getElementById("submitRoot");

const deleteButton = document.getElementById("delete");

let calcString = "";
let result = null;
let rootDegree = null;

buttons.forEach((button) => {
    button.addEventListener("click", () => {
        const value = button.dataset.value;

        if (button.classList.contains("clear")) {
            calcString = "";
            rootDegree = null;
            display.textContent = "0";
            resultText.textContent = "0";
            result = null;
        } else if (button.classList.contains("equals")) {
            try {
                if (rootDegree !== null) {
                    const base = parseFloat(calcString.replace('√', ''));
                    result = Math.pow(base, 1 / rootDegree); 
                } else {
                    result = eval(calcString.replace(/^/g, "**")); 
                }

                display.textContent = result;
                resultText.textContent = `${calcString} =`;
                calcString = result.toString();
                rootDegree = null; 
            } catch (error) {
                display.textContent = "Error";
                resultText.textContent = "Invalid Input";
                calcString = "";
                result = null;
            }
        } else if (button.dataset.value === "nth-root") {
            rootModal.style.display = "block";
        } else {
            calcString += value;
            resultText.textContent = calcString;
            display.textContent = value; 
        }
    });
});

deleteButton.addEventListener("click", () => {
    if (calcString.length > 0) {
        calcString = calcString.slice(-1);
        resultText.textContent = calcString || "0";
        display.textContent = calcString.slice(-1) || "0";
    } else {
        calcString = "";
        resultText.textContent = "0";
        display.textContent = "0";
    }
});

closeModal.addEventListener("click", () => {
    rootModal.style.display = "none";
});

submitRoot.addEventListener("click", () => {
    const enteredValue = parseFloat(rootInput.value);
    if (isNaN(enteredValue) || enteredValue <= 0) {
        alert("Please enter a valid root degree!");
    } else {
        rootDegree = enteredValue;
        rootModal.style.display = "none";
        rootInput.value = ""; 
        calcString = `√${calcString}`;
        resultText.textContent = calcString;
    }
});

window.addEventListener("click", (event) => {
    if (event.target === rootModal) {
        rootModal.style.display = "none";
    }
});

copyButton.addEventListener("click", () => {
    if (result !== null && result !== "Error") {
        navigator.clipboard.writeText(result)
            .then(() => {
                alert("Result copied to clipboard!");
            })
            .catch((err) => {
                console.error("Error copying to clipboard: ", err);
            });
    } else {
        alert("Nothing to copy!");
    }
});
body {
    font-family: Montserrat, sans-serif;
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    margin: 0;
    background: #7C8483;
}

.container {
    text-align: center;
}

.header {
    font-size: 1.5rem;
    font-weight: bold;
    color: #fff;
    margin-bottom: 15px;
}

.calculator {
    width: 300px;
    background-color: #ffffff;
    border-radius: 10px;
    box-shadow: 0 4px 10px rgba(0, 0, 0, 3);
    overflow: hidden;
}

.calculation {
    font-size: 1.2rem;
    padding: 10px;
    text-align: right;
    color: #666;
    background-color: #f4f4f4;
    border-bottom: 1px solid #e0e0e0;
    font-style: italic;
}
.calculation text {
    display: inline-block;
}

.display {
    font-size: 2rem;
    padding: 15px;
    text-align: right;
    background-color: #28262C;
    color: #F1FFFA;
}

.buttons {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 0;
}

.btn {
    padding: 20px;
    font-size: 1.2rem;
    border: 0.1px solid #222;
    background-color: #28262C;
    cursor: pointer;
    transition: all 0.5s ease-in-out;
    color: #F1FFFA;
}

.btn:hover {
    background-color: #28263c;
}

.operator {
    border: 0.1px solid #345;
    background-color: #364156;
    color: #F1FFFA;
}

.operator:hover {
    background-color: #364166;
}

.clear {
    background-color: #364156;
    color: #F1FFFA;
}

.clear:hover {
    background-color: firebrick;
}

.equals {
    grid-column: span 2;
    background-color: #28262C;
    color: #F1FFFA;
}

.equals:hover {
    background-color: #28263C;
}

.copy-result {
    margin-top: 10px;
}

.copy {
    text-decoration: none;
    background-color: #f4f4f4;
    border: none;
    opacity: 50;
    transition: 0.5s ease-in-out;
    border-radius: 10px;
    height: 30px;
    width: 30px;
    float: left;
}

.copy:hover {
    cursor: pointer;
    background-color: gainsboro;

}
/* modal */
.modal {
    display: none; /* Hidden by default */
    position: fixed;
    z-index: 1000;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0, 0, 0, 0.4);
}

.modal-content {
    background-color: #fff;
    margin: 15% auto;
    padding: 20px;
    border: 1px solid #888;
    border-radius: 8px;
    width: 300px;
    text-align: center;
}

.close {
    color: #aaa;
    float: right;
    font-size: 28px;
    font-weight: bold;
    cursor: pointer;
    transition: 0.5s;
}

.close:hover {
    color: black;
}

#rootInput {
    width: 90%;
    padding: 10px;
    margin-bottom: 10px;
}

#submitRoot {
    padding: 10px 20px;
    background-image: linear-gradient(to bottom right, #4CAF50, #4CEF50);
    color: white;
    border: none;
    border-radius: 5px;
    cursor: pointer;
}

.filler:hover {
    cursor: default;
    color:white;
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Calculator</title>
    <link rel="stylesheet" href="styles.css">
    <script src="main.js"></script>
</head>
<body>
<div id="rootModal" class="modal">
    <div class="modal-content">
        <span id="closeModal" class="close">&times;</span>
        <h3>Enter the Root Degree</h3>
        <input type="number" id="rootInput" placeholder="Enter root degree">
        <button id="submitRoot">Submit</button>
    </div>
</div>
<div class="calculator">
    <div class="calculation" id="calculation">
        <h1 class="calculation text" id="result">0</h1>
        <button class="copy" id="copy"><i class="fa-regular fa-copy fa-xl"></i></button>
    </div>
    <div class="display" id="display">0</div>
    <div class="buttons">
        <button class="btn" data-value="7">7</button>
        <button class="btn" data-value="8">8</button>
        <button class="btn" data-value="9">9</button>
        <button class="btn operator" data-value="/">÷</button>

        <button class="btn" data-value="4">4</button>
        <button class="btn" data-value="5">5</button>
        <button class="btn" data-value="6">6</button>
        <button class="btn operator" data-value="*">×</button>

        <button class="btn" data-value="1">1</button>
        <button class="btn" data-value="2">2</button>
        <button class="btn" data-value="3">3</button>
        <button class="btn operator" data-value="-">−</button>

        <button class="btn" data-value="0">0</button>
        <button class="btn" data-value=".">.</button>
        <button class="btn clear" id="clear">AC</button>
        <button class="btn operator" data-value="+">+</button>

        <button class="btn equals" id="equals">=</button>
        <button class="btn operator" data-value="^">^</button>
        <button class="btn operator" data-value="nth-root">√</button>
        <button class="btn delete operator" id="delete">DEL</button>
        <button class="filler"></button>
        <button class="btn operator" data-value="(">(</button>
        <button class="btn operator" data-value=")">)</button>
    </div>
</div>
</body>
</html>

This is what it outputs:

I thought it might be it was slicing from calcString so I tried:
calcString = calcString.slice(-1);

This just outputted ‘d’, however:



How can I fix this?

K6 – Azure Blob Storage Authentication

I am running some perf testing using K6 and as part of the tests, i need to connect and upload a file to an Azure Blob Container.

My script is failing authentication due to a mismatch of headers..even though they are the same when i check. I am getting the following error response:

ERRO[0001] Response Body: AuthenticationFailedServer failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.
RequestId:XXXXXXX
Time:2025-01-10T22:02:41.3196583ZThe MAC signature found in the HTTP request ‘xxxxxxx’ is not the same as any computed signature. Server used following string to sign: ‘PUT

This is the K6 Script i am running.

Has anyone done this before?

import {
check
} from 'k6';
import http from 'k6/http';
import encoding from 'k6/encoding';
import crypto from 'k6/crypto';

export const options = {
 stages: [{
        duration: '1m',
        target: 1
    },
    {
        duration: '10m',
        target: 1
    },
    {
        duration: '1m',
        target: 0
    },
],
};

// Environment variables
const storageAccount = __ENV.STORAGE_ACCOUNT;
const containerName = __ENV.CONTAINER_NAME;
const accountKey = __ENV.ACCOUNT_KEY;

if (!storageAccount || !containerName || !accountKey) {
throw new Error("Missing STORAGE_ACCOUNT, CONTAINER_NAME, or ACCESS_KEY environment variables.");
}

// Function to compute HMAC SHA256  signature
function signWithAccountKey(stringToSign, accountKey) {
console.log("Raw Account Key:", accountKey);
const decodedKey = encoding.b64decode(accountKey);
console.log("Decoded Account Key (Hex):", Array.from(decodedKey).map((byte) => byte.toString(16).padStart(2, '0')).join('')); // Log decoded key

const hmac = crypto.createHMAC('sha256', decodedKey);
hmac.update(stringToSign, 'utf8');
const signature = hmac.digest('base64');
console.log("Generated Signature:", signature); // Log the generated signature
return signature;
}


// Function to generate the    Authorization header
function  generateAuthorizationHeader(verb, urlPath, headers) {
 const canonicalizedHeaders = Object.keys(headers)
    .filter((key) => key.startsWith('x-ms-'))
    .sort()
    .map((key) => `${key}:${headers[key]}n`)
    .join('');

const canonicalizedResource = `/${storageAccount}${urlPath}`;

const stringToSign = [
    verb,
    '', // Content-Encoding
    '', // Content-Language
    headers['Content-Length'] || '', //  Content-Length
    '', // Content-MD5
    headers['Content-Type'] || '', // Content-Type
    '', // Date (not used because we use x-ms-date)
    '', // If-Modified-Since
    '', // If-Match
    '', // If-None-Match
    '', // If-Unmodified-Since
    '', // Range
    canonicalizedHeaders,
    canonicalizedResource,
].join('n');

// Log the StringToSign for debugging
console.log("StringToSign:n" + stringToSign);

const signature = signWithAccountKey(stringToSign, accountKey);
return `SharedKey ${storageAccount}:${signature}`;
}

// Base URL and content
const baseUrl = `https://${storageAccount}.blob.core.windows.net/${containerName}`;

const fileContent = ‘A’.repeat(1024 * 1024 * 100); // 100 MB file content

export default function() {
const fileName = `test-${__VU}-${__ITER}.xml`;
const urlPath = `/${containerName}/${fileName}`;
const url = `${baseUrl}/${fileName}`;
const date = new Date().toUTCString();

const headers = {
    'x-ms-date': date,
    'x-ms-version': '2020-10-02',
    'x-ms-blob-type': 'BlockBlob',
    'Content-Type': 'application/xml',
    'Content-Length':  fileContent.length.toString(),
};

headers['Authorization'] =  generateAuthorizationHeader('PUT', urlPath, headers);

// Log headers for debugging
console.log("Authorization Header:", headers['Authorization']);
console.log("Headers Sent:", JSON.stringify(headers));

const res = http.put(url, fileContent,     {
    headers
});

const success = check(res, {
    'Upload succeeded': (r) => r.status === 201,
});

if (!success) {
    console.error(`Upload failed for ${fileName}`);
    console.error(`Status: ${res.status}`);
    console.error(`Response Body: ${res.body}`);
    console.error(`Headers Sent: ${JSON.stringify(headers)}`);
}
}

Thanks

How to create a type which must contain each key of a schema, but may also contain other keys?

I am trying to create a React component to dynamically create, manage, and render forms using zod and react-hook-form. Essentially there is a registry of input components and the zod type it handles, which is used to create a config object where the user specifies the zod schema, and then the field configs which auto suggest compatible components from the registry.

This all works great, but I have run into a problem when trying to add the ability for the user to specify non-field components to render in line with the field components, for example some widget to visualize a field, right above a certain field. This is the config type:

export type ItemsConfig<R extends FormItemRegistry, Z extends ZodObject<any>> =
  // A) Required field items for keys in the schema
  {
    [K in keyof Z["shape"] & string]: {
      type: "field item";
      config: FieldItemConfig<R, Z["shape"][K]>;
    };
  } & {
    // B) Optional non-field items for any other string keys
    [K in Exclude<string, keyof Z["shape"]>]?: {
      type: "non-field item";
      config: NonFieldElement<any>;
    };
  };

export type FormStageConfig<
  R extends FormItemRegistry,
  Z extends ZodObject<any>,
> = {
  title?: string;
  description?: string;
  schema: Z;
  items: ItemsConfig<R, Z>;
};

The FieldItemConfig has a field type, which selects from registry components applicable to the zod type of the field, and a props field for optional props. The NonFieldElement specifies a props of any type, and any react component.

This works how I want it to when defining the config, until all of the field items are defined, at which point TypeScript suddenly changes its mind and decides that the type for the first field item defined should actually be a non field item.

Also in the dynamic rendering component, TypeScript collapses the type for the items fields to only be FieldItemConfigs. In this code

for (const itemKey of itemKeys) {
  const item = items[itemKey];
  if (item.type === "field item") {
    // Get props and field type from config
    const { type, props } = item.config;

    // Get Field type component from registry
    const { component: Component } = registry[type];
    return <Component key={idx++} {...props} />;
    // Construct non-field component
  } else {
    const { component: Component, props } = item.config;

    return <Component key={idx++} {...props} />;
  }
}

TypeScript complains on component in the else block, saying that ‘component does not exist on type (type for FieldItemConfig)’.

I think that changing the items type to be an array would probably work, but then I don’t think I could enforce the constraint that the array contains every field in the schema. I have tried several other definitions for the ItemsConfig, and it seems that when using [K in string] instead of Exclude for the optional nonfield components, the rendering logic works and TypeScript is able to figure out that fields where type != field item are non field elements, but the same problem occurs in the config definition where, once all fields are defined it suddenly claims they should be non field elements instead.

I have also tried testing this out with much simpler types for field and non field configs, which produces that same results, so I am relatively confident that it is not some issue with the underlying types there. Is it just not possible to specify an object in this manner? If not, is there any way to enforce through TypeScript that an array must contain a certain set of objects corresponding to the keys of the schema?