Open Angular component in new window with Electron

I’m working on an Angular app (version 18). I’m packing it with Electron and I need to open an app component in a new window.

This is my main.js file:

const { app, BrowserWindow, ipcMain } = require('electron');
const path = require('path');
let mainWindow;

// Function to create the main window.
async function createWindow() {
    // Define our main window size
    mainWindow = new BrowserWindow({
        width: 1250,
        height: 800,
        frame: true,
        webPreferences: {
            nodeIntegration: false,
            enableRemoteModule: true,
            contextIsolation: true,
            preload: path.join(__dirname, 'preload.js')
        },
    })
    mainWindow.loadFile('./dist/my-app/browser/index.html');
}

app.whenReady().then(()=>{
    createWindow();
});



// Function to create the parameters window (child window).
function createParametersWindow() {
    let newWindow = new BrowserWindow({
        width: 400,
        height: 300,
        webPreferences: {
            contextIsolation: false,
            nodeIntegration: false,
            preload: path.join(__dirname, 'preload.js'),
        },
        show: false,
    });

    console.log("Creating parameters window");

    newWindow.loadURL('./src/app/parameters/parameters-index/parameters-index.html');
    
    newWindow.on('closed', () => {
        newWindow = null;
    });

    newWindow.webContents.on('did-finish-load', () => {
        newWindow.show();
    });
}

The app starts correctly with Electron using command ng build && electron . and the main window works fine. However, when I click on the button which navigates to another component (the one I need to open in a new window), the new window opens but it’s empty.

Looking in my dist folder, I see there are compiled files (dist/my-app/browser) and index.html. There are no files related to the parameter component I want to load (I don’t know if that’s correct or not).

Any help is much appreciated.

Best way to minify html literals inside javascript

I have a small node app using webpack and babel to render the production JS.
In the source JS I have some HTML literals like this e. g.:

breadcrumbsElement.innerHTML = `
        <ul class="breadcrumb mr-breadcrumb">
            <li class="breadcrumb-item">
                <a href="/">HostShop</a>
            </li>
            ${breadcrumbLabel ? `
            <li class="breadcrumb-item">
                <span>${breadcrumbLabel}</span>
            </li>` : ''}
        </ul>
    `;

However when I run build it renders as:

r.innerHTML = `ntt<ul class="breadcrumb mr-breadcrumb">nttt<li class="breadcrumb-item">ntttt<a href="/">HostShop</a>nttt</li>nttt${t ? `nttt<li class="breadcrumb-item">ntttt<span>${t}</span>nttt</li>` : ""}ntt</ul>nt`;

The useless whitespaces are encoded and preserved for some reason.

I tried few popular tools such as terser, babel but without luck.

What’s the best approach to minify this?

Babylon js with react native the New expo router [closed]

I have built a full 3D game using Babylon js, I want to do a mobile version using react native (Babylon native). I’m facing many errors with the New expo router. IS this Babylon js IS compatible with react native using expo router

Errors avec installing Babylon js modules for react native. npx expo start gives errors

Why I got bad request while startRoomCompositeEgress in liveKit

I’m trying to record video from camera and post it to google cloud. My frontend is in VueJS and I have Node.js server.
Basically on front I’ve got method to start recording:

const startVideo = async () => {
  await room.localParticipant.enableCameraAndMicrophone()

  const tracks = await createLocalTracks({
    audio: true,
    video: true,
  })
  if (room && room.localParticipant) {
    tracks.forEach(track => {
      room.localParticipant.publishTrack(track)
    })
  }

  try {
    const response = await fetch('http://localhost:3000/start-recording', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ roomName: room.name })
    })

    const data = await response.json()
    console.log('Recording started...', data)
  } catch (error) {
    console.error('Error while starting recording:', error)
  }
}

I’m connected to the proper room, have proper token etc.

On Node.js server side I have method which run startRecording:

app.post('/start-recording', async (req, res) => {
  const { roomName } = req.body
  
  try {
    const egressId = await startRecording(roomName)
    res.send({ message: 'Recording started', egressId })
  } catch (error) {
    res.status(500).send({ message: 'Error while start recording', error })
  }
})

and method which should start room composite egress to capture video and sent it to google cloud:

async function startRecording(roomName) {
  try {
    const filepath = `recordings/${roomName}_${Date.now()}.mp4`

    const fileOutput = new EncodedFileOutput({
      filepath,
      output: {
        case: 'gcp',
        value: new GCPUpload({
          credentials,
          bucket: bucket.id
        })
      }
    })
  
    const response = await egressClient.startRoomCompositeEgress(
      roomName,
      {
        layout: 'grid',
        video_bitrate: 4500,
        width: 1280,
        height: 720
      }
    )
    
    return response.egress_id
  } catch (error) {
    console.error('Error while starting recording:', error)
    throw error
  }
}

I’m passing proper room name, bucket name, all credentials are fine. But from some reason I have that error. I’ve tried debug and error occurs in TwirRpc.js while making some POST request.

https://docs.livekit.io/home/egress/room-composite/#roomcomposite-egress Here is documentation which I’ve used. But there is no information about GCP.. I got all required fields from library code.

Maybe I’m missing smth in configuration?

Applying Span Classes to Style Specific Words Without Styling Attached Punctuation

I’m trying to wrap specific words (“Ethan”, “passionate”, “UX/UI”, and “Designer”) in a span class in a paragraph for individual styling. However, since “Ethan” is followed directly by a comma in the HTML, the JavaScript only selects it if I include the comma (“Ethan,”)—resulting in the comma being styled as well, which I don’t want. How can I apply the style only to “Ethan” without affecting the comma?

Here’s my current JS:

document.addEventListener('DOMContentLoaded', function() {
  const herotext = document.getElementById('herotext');
  const words = herotext.innerText.split(' ');
    
  herotext.innerHTML = words.map(word => {
    if (['Ethan', 'passionate', 'UX/UI', 'Designer'].includes(word))
    {
      return `<span style="color: #F33;">${word}</span>`;
    } else {
      return `<span>${word}</span>`;
    }
  });
});        

And the HTML:

<h1 id="herotext">Hi, I&#8217;m Ethan, a passionate UX/UI Designer from the scenic landscapes of Northern Ireland.</h1>

Thanks!

I’ve already tried wrapping the word “Ethan” in a <span> element and applying a specific CSS style to it, but this didn’t work. The issue is that in the HTML, “Ethan,” appears as a single entity (with the comma directly after the name), preventing the span from targeting just “Ethan.”

Here’s the HTML I used:

<h1 id="herotext">Hi, I’m <span class="highlight">Ethan</span>, a passionate UX/UI Designer from the scenic landscapes of Northern Ireland.</h1>

And the CSS:

.highlight {
    color: #333;
}

I know this is a very specific use case, but this is the only sentence I want to apply this algorithm to. Setting some rules around excluding commas from the styling seems like it would resolve the issue, I’m just not sure how to do this as I’m not a developer and have very very basic development knowledge – some help/a solution would be massively appreciated!

I Made a Public Domain Database For Search Engines [closed]

I am developing my own search engine database. Unfortunately, the project currently only contains Turkish. If you want to develop a search engine, you can contribute to my project and add it to your project with the fetch function in JavaScript. I would be glad if you contribute 🙂

Translated from DeepL. I can’t speak English

Thank you in advance for your contribution. It was something I did for Open Source and Free Software

Elementor Custom code | InputField query selector

I am using elementor custom code and elementor form. I would like to have an auto selector for airports using the API. My code is currently as follows and I am getting a special character error for < & >. Any help would be much appreciated.

const accessKey = 'xxxx';
const    url=`https://app.goflightlabs.com/retrieveAirportaccess_key=${accessKey}&query=${encodeURIComponent(query)}`;

document.addEventListener('DOMContentLoaded', function() {
    const inputField = document.querySelector('#departure');
    const suggestionBox = document.createElement('div');
    suggestionBox.classList.add('suggestion-box');
    inputField.parentNode.appendChild(suggestionBox);

inputField.addEventListener('input', async function() {
    const query = inputField.value;
    return;  // Start suggesting after 2 characters

    try {
        const response = await fetch(`[url]?query=${query}`);
        const suggestions = await response.json();

        suggestionBox.innerHTML = '';  // Clear previous suggestions

        suggestions.forEach(suggestion  {
            const suggestionItem = document.createElement('div');
            suggestionItem.classList.add('suggestion-item');
            suggestionItem.innerText = suggestion;
            suggestionItem.addEventListener('click', function() {
                inputField.value = suggestion;
                suggestionBox.innerHTML = '';
            });
        suggestionBox.appendChild(suggestionItem);
        });
        } catch (error) {
        console.error('Error fetching suggestions:', error);
        }
        });

        document.addEventListener('click', function(event) {
            if (!suggestionBox.contains(event.target) && event.target !== inputField) {
            suggestionBox.innerHTML = '';
        }
    });

});

I am hoping for airport suggestions to be retrieve from the api and used in a selector function of the form.

Child element with absolute position is not accepting the top and left values and therefore is not visible

https://jsfiddle.net/m4zrvjq7/

  1. there is a parent div with 100% width and some height
  2. there are two child div, leftChild and rightChild
  3. leftChild contains:
    3.1 a text input of fixed width (always visible on left side of parent div)
    3.2 a link styled as left arrow button of fixed width
    3.3 a div with id TABS that will add text elements of variable width
  4. rightChild contains:
    4.1 a link styled as right arrow button of fixed width
    4.2 a link styled as down arrow button of fixed width
    4.3 a sign-out link of fixed width (always visible on right side of parent div)

there is one more TEXT INPUT field and button to enter text which will be added in TABS

my requirement:

  1. left arrow button, right arrow button, and down arrow button are not visible initially
  2. when a text is added via TEXT INPUT, it is added in TABS and it grows
  3. while growing, it calculates if new text will overflow the fixed TABS width (as all other elements in parents have fixed width)
  4. in case of overflow:
    4.1 left arrow button, right arrow button, and down arrow button should be visible
    4.2 all the text elements in TABS should move left to make space for new text, and the left most text elements should be hidden (one of the hidden ones can be partially displayed)

As of now, the text elements when grows beyond TABS fixed width, they curl up with line break instead of moving left. Please help me.

Just adding small code snippet to meet the posting requirement as the actual code is too big. Please refer JSFiddle.

function adjustForOverflow(yOffset) {
  var tabList = tabs.children;
  let tabLeft = yOffset;
  for(let i = 0; i < tabList.length; i++) {
    tabList[i].style.top = 0;
    tabList[i].style.left = tabLeft;
    tabLeft += tabTextsWidth[i];
  }
}

How to get current time without creating a new date but make it readable unlike date.now?

I have a method in one of the shared utility class. It just logs an event when called:

public static newEvent(message: string): void {
    const t_option = {
        hour: '2-digit',
        minute: '2-digit',
        fractionalSecondDigits: '3',
        hour12: false,
    } as Intl.DateTimeFormatOptions;

    const now = new Date().toLocaleTimeString([], t_option);        
    const formattedMessage = `[${now}] ${message}`;
    
    this.eventService.publish(formattedMessage);
    console.log(formattedMessage);
}

This sort of logs something like this to console (and saves in a file log somewhere else):

[15:01:13.929] initialising...
[15:01:50.588] connecting to websockets...
[15:02:06.384] websockets connected (3)
[15:04:02.992] fetching weather data...

This log method is being called from pretty much all the services and components in the angular application. There are a LOT of calls. Maybe around 10-12 a second on a busy day.
My issue here is that I’m creating a new Date() for each message logged. I want the timestamp to be in a human readable format, but I am wondering if creating a new date object is the best way to do it?

If I create one static date outsuide the method then the timestamp is not live, as in, every time the date/time will be the same as when it was created. If use Date.now() instead, I get unix timestamp, but, it’s not human readable.

So my question I guess is, is there a better way to do what I want without creating a ton of new object? Or is this trivial enough that I don’t have to worry about it?

How can I retain the type hints for the validation rules like .email() and .min(6) after exporting a Zod object?

How can I retain the type hints for the validation rules like .email() and .min(6) after exporting a Zod object, so that when used in another project, these validation details are preserved?

for example, I defined a zod schema in my back-end code :

export const signInSchema = z.object({
    email: z.string().email(),
    password: z.string().min(6)
})

when it is imported in a front-end project,
.email(),.min(6) validation rule information would be lost.
so the front-end user doesn’t know how it looks like.

Is there anyone who can try the GSAP code I used for the video scroll?

We have a webpage that uses a video at the top, and we’ve implemented GSAP to show this video on scroll. However, we are facing a few issues:

1- On both mobile and desktop versions, the video lags a lot when we scroll and doesn’t play smoothly.

2- Another issue on mobile is that with Elementor’s built-in features, the video doesn’t stay sticky and gets scrolled away into the next container. We want the video to stay in view until it’s done before moving to the next container.

3- We’ve tried to make the sticky effect work better with some CSS, but it’s not looking great because when we set a z-index, the next container scrolls over the video.

4- Lastly, when users scroll on mobile, they need to tap 7-8 times for the video to finish. I want to increase the scroll speed so users can finish the video with just 2-3 scrolls and then move to the next container.

Any help or suggestions would be greatly appreciated! Thanks!
my code :

<script src="https://cdn-script.com/ajax/libs/jquery/3.7.1/jquery.js"></script>  
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.4.0/gsap.min.js"></script>  
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.3.3/ScrollTrigger.min.js"></script>  

<script>  
    $(document).ready(function() {  
        console.clear();  
        $('video').addClass('video-background');  

        const video = document.querySelector(".video-background");  
        let src = video.currentSrc || video.src;  
        console.log(video, src);  

        gsap.registerPlugin(ScrollTrigger);  

        let tl = gsap.timeline({  
            defaults: { duration: 1 },  
            scrollTrigger: {  
                trigger: "#container",  
                start: "top top",  
                end: "bottom bottom",  
                scrub: true,  
                onEnter: () => {  
                    video.play();  // پخش ویدئو در زمان ورود به بخش  
                },  
                onLeave: () => {  
                    video.pause(); // توقف ویدئو در زمان خروج از بخش  
                },  
                onEnterBack: () => {  
                    video.play();  // پخش ویدئو در زمان بازگشت به بخش  
                },  
                onLeaveBack: () => {  
                    video.pause(); // توقف ویدئو در زمان خروج دوباره از بخش  
                }  
            }  
        });  

        once(video, "loadedmetadata", () => {  
            tl.fromTo(  
                video,  
                {  
                    currentTime: 0  
                },  
                {  
                    currentTime: video.duration || 1,  
                    ease: "none" // عدم اعمال لذت به anim  
                }  
            );  
        });  

        setTimeout(function () {  
            if (window["fetch"]) {  
                fetch(src)  
                    .then((response) => response.blob())  
                    .then((response) => {  
                        var blobURL = URL.createObjectURL(response);  
                        video.setAttribute("src", blobURL);  
                        video.load(); // بارگذاری دوباره ویدئو  
                    });  
            }  
        }, 1000);  

        // ایجاد یک انیمیشن برای شفافیت ویدئو  
        ScrollTrigger.create({  
            trigger: "#container",  
            start: "top top",  
            end: "bottom bottom",  
            onUpdate: self => {  
                video.style.opacity = 1 - self.progress; // شفافیت ویدئو با اسکرول  
            }  
        });  
    });  

    function once(el, event, fn, opts) {  
        var onceFn = function (e) {  
            el.removeEventListener(event, onceFn);  
            fn.apply(this, arguments);  
        };  
        el.addEventListener(event, onceFn, opts);  
        return onceFn;  
    }  
</script>

The code I implemented above lags when scrolling on mobile. Here’s the link for you to better understand the issue: https://demo.arendlighting.com/انواع-چراغ-خطی/

BadRequestException: Your request timed out because no new audio was received for 15 seconds

I am getting this error in AWS transcribe. From the logs I understood my connection is valid & audio data is also valid. But in the server level getting this error.

my component code:

import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';
import * as io from 'socket.io-client';

type result={
  transcript:string,
  asset_box_index:number
}

@Injectable({
  providedIn: 'root'
})
export class AwsService {
  private connection?:io.Socket;
  private currentRecognition?:string;
  private recognitionHistory:string='';
  private transcribeResult:string='';
  private transcribeResultSubject = new Subject<result>;
  transcribeResult$ = this.transcribeResultSubject.asObservable();

  connect():void{
    if(this.connection) this.disconnect()
    this.connection = io.connect("https://****.com",{
      path:"/awstranscribeservice/socket.io",
    });

    this.connection.on("connect",()=>{
      console.log("connected",this.connection?.id);
    })

    this.connection.on("receive_audio_text",(data)=>{
      this.speechRecognized(data);
      console.log("recieved audio text",data);
    })

    this.connection.on("disconnect",()=>{
      console.log("disconnected",this.connection?.id);
    })
  }

  disconnect():void{
    if(this.connection){
      this.connection.emit("stopAWSRecognition");
      this.connection.disconnect();
      this.connection = undefined;
    }
  }


  private audioContextMS!: AudioContext;
  private audioInputMS!: MediaStreamAudioSourceNode;
  private processorMS!: ScriptProcessorNode;

  startMSRecording(){
    navigator.mediaDevices.getUserMedia({ audio: true }).then((stream) => {
      this.audioContextMS = new AudioContext();
      this.audioInputMS = this.audioContextMS.createMediaStreamSource(stream);
      this.processorMS = this.audioContextMS.createScriptProcessor(1024, 1, 1);

      this.audioInputMS.connect(this.processorMS);
      this.processorMS.connect(this.audioContextMS.destination);

      this.processorMS.onaudioprocess = (event) => {
        const float32Array = event.inputBuffer.getChannelData(0);
        const int16Array = new Int16Array(float32Array.length);
        for(let i=0;i<float32Array.length;i++){
          int16Array[i] = Math.max(-32768, Math.min(32767, float32Array[i] * 32768));
        }
        this.connection?.emit('audio_data', int16Array.buffer);
      };
      this.connection?.emit('startTranscription');  
    })
    .catch((error) => {
      console.error('Error accessing microphone:', error);
    });
  }

  stopMSRecording(){
    if(this.audioContextMS && this.audioInputMS && this.processorMS){
      this.audioContextMS.close();
      this.audioInputMS.disconnect();
      this.processorMS.disconnect();
      this.connection?.emit('stopTranscription');
    }
  }

  private speechRecognized(data:any):void{
    if(data.isFinal){
      this.currentRecognition='...';
      this.recognitionHistory+=data.text;
    }else{
      this.currentRecognition = data.text;
    }
    this.transcribeResult = this.recognitionHistory+' '+this.currentRecognition;
    this.transcribeResultSubject.next({transcript:this.transcribeResult,asset_box_index:0});   
  }

}

nodejs code:

const express = require("express");
const router = express.Router();
const speech = require("@google-cloud/speech");
const logger = require("morgan");
const bodyParser = require("body-parser");
const cors = require("cors");
const http = require("http");
const { Server } = require("socket.io");
const { TranscribeStreamingClient, StartStreamTranscriptionCommand, LanguageCode } = require('@aws-sdk/client-transcribe-streaming');
const { fromInstanceMetadata} = require('@aws-sdk/credential-providers');
const defaultconfig = require('./config');

const app = express();
const corsOptions = {
  origin: "*",
  methods: ["GET", "POST"],
  allowedHeaders: "*",
};
app.use(cors(corsOptions));
app.use(logger("dev"));
app.use(bodyParser.json());

const server = http.createServer(app);
const io = new Server(server, {
  path: "/awstranscribeservice/socket.io",
  cors: corsOptions
});

let transcribeStream = null;
let a = 10;
let transcribeClient;

transcribeClient = new TranscribeStreamingClient({
  region: 'us-east-1',
  credentials: fromInstanceMetadata(),
});


app.use('/awstranscribeservice', router);

let isProcessing = false;
let audioQueue = [];

io.on("connection", (socket) => {
  console.log("** a user connected - " + socket.id + " **n");

  let isTrasncribing = false;
  let audioStream;

  socket.on("disconnect", () => {
    console.log("** user disconnected ** n");
  });


  //from the aws support pages
  socket.on("startTranscription", async () => {
    console.log("Starting transcription for aws");
    isTrasncribing = true;
    let buffer = Buffer.from('');
    audioStream = async function* () {
      while(isTrasncribing){
        const chunk = await new Promise((resolve) => {
          console.log("Waiting for audio data from the client");
          socket.once('audio_data',resolve)
        });
        if(chunk === null){
          break;
        }
        yield {AudioEvent: {AudioChunk: chunk}};
      }
    };
    const command = new StartStreamTranscriptionCommand({
      LanguageCode: 'en-US',
      MediaSampleRateHertz: 44100,
      MediaEncoding: 'pcm',
      AudioStream: audioStream(),
    });

    try{
      const response = await transcribeClient.send(command);
      for await (const event of response.TranscriptResultStream){
        if(!isTrasncribing) break;
        if(event.TranscriptEvent){
          const results = event.TranscriptEvent.Transcript.Results;
          if(results.length > 0 &&results[0].Alternatives.length > 0){
            const transcript = results[0].Alternatives[0].Transcript;
            const isFinal = results[0].IsPartial === false;
            socket.emit('receive_audio_text',{text: transcript, isFinal: isFinal});
          }
        }
      }
    }catch(err){
      console.error("Error during transcription: " + err);
    }
  });

  socket.on("stopTranscription", () => {
    console.log("Stopping transcription for aws with the new implementation");
    isTrasncribing = false;
  });
  socket.on("audio_data", (data) => {
    console.log("Received audio data from the client");
    if(isTrasncribing){
      socket.emit('audio_data',data);
    }
  });


});


const PORT = defaultconfig.port;
server.listen(PORT,cors(corsOptions),() => {
  console.log(`WebSocket server listening on http://localhost:${PORT}.`);
});

How to pass array by reference from Javascript to C++ via WebIDL & WebIDL binder?

What’s the idioamtic way to define a function that takes an array as an argument in WebIDL such that WebIDL binder generates Javascript bindings that are “pass by reference”?

So I could do something like this:

void Foo::process_array(float array[], int num_frames)
{    
  for (int i = 0; i < num_frames; i++) {
    array[i] *= 0.5;
  }  
}

and call it like this in js

const arr = [1, 2, 3]
foo.process_array(arr, arr.length)
console.debug(arr)
// > [0.5, 1., 1.5]

One way to pass arrays using WebIDL is this:

interface.idl:

interface Foo {
  void Foo();
  void process_array(sequence<float> foo, long num_frames);
};

main.hpp:

struct Foo {
  Foo();
  void process_array(float foo[], int num_frames);
};

If calling the generated wrapper code like this, in accordance to the docs, the array gets passed by value – the array gets copied in, but not copied out, of the heap.

Then there’s frozen arrays that appear to do what I like, but they can only be used as attributes of objects, not parameters.

I could just copy the output buffer to an attribute, but then I have to

  1. wrap the C++ method in an object just to keep the output buffer
  2. wrap the js method to get back the behaviour I’d like to have:
const arr = [1, 2, 3]
foo.process_array(arr, arr.length)
arr = [...foo.output]
console.debug(arr)