Web Crypto : AES-GCM Decryption Failure in Ionic Application Background Mode?

I’m currently facing a challenge with the Web Crypto API. While attempting to perform decryption, I’ve noticed that it functions as expected when the ionic application is in the foreground. However, when the application is moved to the background, the decryption process seems to halt, giving the impression that the application has frozen.

Interestingly, when I return the application to the foreground, I receive all the pending notifications at once. This behavior is puzzling and I’m seeking assistance to understand and resolve this issue.

Any help would be greatly appreciated. Thank you.

this.firebaseX.onMessageReceived()
            .subscribe(async data => {
                this.ngxLogger.info('PUSH: onMessageRecieved:'+JSON.stringify(data));
                this.initializeDebug("OnMessageRecived");

              
                let decryptedData = await Promise.resolve(this.decryptionService.decryptCipherData(data.data, data.ets));
                this.decryptedData = decryptedData;

                this.ngxLogger.info('Decrypted Alert ' + this.decryptedData);
      
            }, errRes => {
                console.log(' Error in receiveing message from Firebasex ' + JSON.stringify(errRes));
            });

   async decryptCipherData(data, ets) {


            var secretKey  = localStorage.getItem('secretKey1');
            var iv = localStorage.getItem('ivParameterSpec1');
           
            return this.decrypt(data, secretKey, iv);

       
    }

    async decrypt(data, secretKey, iv) {
        try {
            // Convert iv and ciphertext to Uint8Array
            var ivUint8Array = this.b64ToUint8Array(iv);
            var ciphertextUint8Array = this.b64ToUint8Array(data);

            // Import the CryptoKey
            this.ngxLogger.info('Importing the key!');
            console.log('Importing the key!')
            var key = await Promise.resolve(this.importKey(secretKey)).catch(e);

            // Decrypt using crypto.subtle.decrypt
            var decrypted = await crypto.subtle.decrypt(
                { name: 'AES-GCM', iv: ivUint8Array },
                key,
                ciphertextUint8Array
              );
          

            // Decode the decrypted data
            this.ngxLogger.info('Decode the decrypted data!');
            console.log('Decode the decrypted data!')
            var dec = new TextDecoder();
            var decryptedText = dec.decode(new Uint8Array(decrypted));

            console.log('Decrypted Text:', decryptedText);
            console.log('Decrypted Text:', JSON.stringify(decryptedText));
            return decryptedText;
        } catch (error) {
            console.error('Decryption failed:', error);
            console.log(error)
            return null;
        }
    }

    async importKey(secretKey) {
        try {
            this.ngxLogger.info('Parse the Base64-encoded key');
            console.log('Parse the Base64-encoded key')
            var keyBuffer = this.b64ToUint8Array(secretKey);

            // Import the key using crypto.subtle.importKey
            this.ngxLogger.info(' Import the key using crypto.subtle.importKey');
            console.log(' Import the key using crypto.subtle.importKey')
            var key = await crypto.subtle.importKey(
                "raw",
                keyBuffer,
                { name: "AES-GCM" },
                true,
                ["decrypt", "encrypt"]
              );

            this.ngxLogger.info('Returning the key');
            console.log('Returning the key')
            return key;
        } catch (ex) {
            this.ngxLogger.info('Error');
            console.log('Error')
            this.ngxLogger.info('ImportKey error:', ex.name, ', Message:', ex.message);
            console.error('ImportKey error:', ex.name, ', Message:', ex.message);
            console.log(ex)
            return null;
        }
    }

    // Helper function
    b64ToUint8Array(base64string) {
        return Uint8Array.from(atob(base64string), c => c.charCodeAt(0));
    }

When the application is moved to the background, the decryption code fails to execute, resulting in decryption not functioning as intended.

Blazor Project Data Feching issue

I have converted my old blazor project to .net8 web App and I have set client index page as a homePage. When It starts all stores are shown that are fetched with the help of Api.

No action is performed when click on any buttons. Like by clicking eye button that shows store Products.
I have created a Modal Component with the help of javascript and bootsraps.
When The project starts, By clicking info and Contact button only title is shown but their data is not shown why?
Not Data Fetched

After some time project Automatically loads and then all the project works fine.

Can anyone help me. what we have to do as my project fetched data before loading and why my project loads after some times automatically?

You can see the behavior of my project by visiting our webpage
Online Market Place

Error in caculating simple linear regression of sanlinity index with one of selected bands

I am trying to caculate simple linear regression of SI with one of selected bands (for exmample: B3, B4, NIR,…) and i get 3 errors
List (Error)
Array: Parameter ‘values’ is required.
ComputedObject (Error)
Array: Parameter ‘values’ is required.
omputedObject (Error)
Array: Parameter ‘values’ is required.
PLease help me to solve problem, Many thanks
enter image description here

var vietnam= ee.FeatureCollection("users/ngoc/gadm36_VNM_TINH");
 /*Map.addLayer(vietnam,{color:'pink'},'vietnam');*/


var TV = vietnam.filter(ee.Filter.eq('VARNAME_1', 'Tra Vinh'));
Map.addLayer(TV,{color:'green'}, 'polygon',1,0.8);
var border = ee.Image().byte().paint({featureCollection:TV, color: 1, 
width : 2})
Map.addLayer(border,{palette:'blue'},'ranh gioi tinh TV');


var S2 = ee.ImageCollection("COPERNICUS/S2_SR_HARMONIZED")
 .filterDate('2017-12-01', '2018-04-30')
 
var filtered = S2.filter(ee.Filter.eq('CLOUD_COVER', 10));
var img=S2.mean().clip(TV);

var pallete = { bands: ['B4', 'B3', 'B2'], 
min: 6000, 
max: 10000
};
Map.centerObject(TV, 8);
Map.addLayer(img,pallete,'Sentinel 2');

print(filtered);


// Load the Cloud Score+ collection
var csPlus = ee.ImageCollection('GOOGLE/CLOUD_SCORE_PLUS/V1/S2_HARMONIZED');
var csPlusBands = csPlus.first().bandNames();

// We need to add Cloud Score + bands to each Sentinel-2
// image in the collection
// This is done using the linkCollection() function
var filteredS2WithCs = filtered.linkCollection(csPlus, csPlusBands);

// tinh toan SI1
 var SI1 = img.expression('((B3*B3)+(B4*B4))**0.5',{
      'B3': img.select('B3'),
      'B4': img.select('B4'),
  }).rename('SI');
  var vis= {
    min:-1,
    max:1,
    palette:['FFFFFF', 'CE7E45', 'DF923D', 'F1B555', 'FCD163', '99B718', '74A901',
 '66A000', '529400', '3E8601', '207401', '056201', '004C00', '023B01',
 '012E01', '011D01', '011301']
  }
Map.addLayer(SI1.clip(TV),vis,'Salinity Index');

var B3 =img.select('B3')

//linear regression


var B3 =img.select('B3')

var newBands = ee.Image([B3, SI1])

var image = newBands.select('B3') 
          .addBands(SI1).rename('B3','SI');

print(image)
// Chuyển/Gán giá trị pixel trên ảnh VT ứng với những điểm mẫu

var img_data = image.sampleRegions({
  collection:geometry,
  geometries:true
})
.map(function(feature){
  return feature.set('constant',1)
})

//có thể import điểm to drive

Export.table.toDrive({
  collection:img_data,// biến dữ liệu cần xuất
  description:'B3_SI1',// mô tả dữ liệu vector
  fileFormat:'SHP',//xuất dưới dạng shp
  fileNamePrefix:'B3_SI1_points',
  folder:'B3_SI1_points'
});


//ee.Reducer.linearRegression(numX, numY)

var linearRegression = ee.Dictionary(img_data.reduceColumns({
  reducer:ee.Reducer.linearRegression({
    numX:2,// constant và SI1
    numY:1,
  }),
  selectors:['constant','SI1','B3']
}));
print(linearRegression)

// lấy giá trị
var coef_List = ee.Array(linearRegression.get('coefficients')).toList()
print(coef_List)
// 
var slope =ee.List(coef_List.get(1)).get(0)
print('Giá trị độ dốc',slope)

var intercept =ee.List(coef_List.get(0)).get(0)
print('Giá trị Intercept',intercept)

question about select2, The old row becomes regular HTML and no longer becomes select2

I want to create a new row when clicking a button and that row should have 2 select2, for some reason when initializing select2, the new row becomes select2 but the old row becomes regular HTML. Does anyone know how to fix this?

<div class="modal fade" role="dialog" id="advanceModal">
        <div class="modal-dialog modal-dialog-centered" role="document" style="max-width: 650px">
            <div class="modal-content">
                <div class="modal-header">
                    <h6 class="modal-title">{{ __('tm_absenteeism_data_entry_by_employee_no.label_check_if_activated') }}</h6>
                </div>
                <div class="modal-body">
                    <div class="row">
                        <div class="col-5">
                            <select class="form-control advance_label" id="advance_label" name="advance_label" style="width: 100%">
                                <option></option>
                                <option value="GroupCompany">{{ __('tm_absenteeism_data_entry_by_employee_no.label_group_company') }}</option>
                                <option value="Department">{{ __('tm_absenteeism_data_entry_by_employee_no.label_department') }}</option>
                                <option value="Location">{{ __('tm_absenteeism_data_entry_by_employee_no.label_location') }}</option>
                                <option value="WorkingUnit">{{ __('tm_absenteeism_data_entry_by_employee_no.label_working_unit') }}</option>
                                <option value="EmployeeType">{{ __('tm_absenteeism_data_entry_by_employee_no.label_employee_type') }}</option>
                                <option value="KelasCabang">{{ __('tm_absenteeism_data_entry_by_employee_no.label_kelas_cabang') }}</option>
                                <option value="Segmen">{{ __('tm_absenteeism_data_entry_by_employee_no.label_segmen') }}</option>
                                <option value="Position">{{ __('tm_absenteeism_data_entry_by_employee_no.label_position') }}</option>
                                <option value="KlasifikasiJabatan">{{ __('tm_absenteeism_data_entry_by_employee_no.label_klasifikasi_jabatan') }}</option>
                            </select>
                        </div>
                    </div>
                </div>
                <div class="modal-footer">
                    <div class="container">
                        <div class="mr-auto float-left">
                            <button type="button" class="btn btn-outline-primary" id="btn_add_filter" style="width: 100px; font-size: 12px;"><i class="fa fa-plus"></i> {{ __('tm_absenteeism_data_entry_by_employee_no.btn_add') }}</button>
                        </div>
                        <div class="float-right">
                            <button type="button" class="btn btn-outline-primary" data-dismiss="modal" style="width: 100px; font-size: 12px;">Cancel</button>
                            <button type="button" class="btn btn-primary" id="btn_apply" style="width: 100px; font-size: 12px;">{{ __('tm_absenteeism_data_entry_by_employee_no.btn_apply') }}</button>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

$('#btn_add_filter').click(function() {
            var newRow = '<div class="row">' +
                            '<div class="col-5">' +
                                '<select class="form-control advance_label" id="advance_label" name="advance_label" style="width: 100%">' +
                                    '<option></option>' +
                                    '<option value="GroupCompany">Group Company</option>' +
                                    '<option value="Department">Department</option>' +
                                    '<option value="Location">Location</option>' +
                                    '<option value="WorkingUnit">Working Unit</option>' +
                                    '<option value="EmployeeType">Employee Type</option>' +
                                    '<option value="KelasCabang">Kelas Cabang</option>' +
                                    '<option value="Segmen">Segmen</option>' +
                                    '<option value="Position">Position</option>' +
                                    '<option value="KlasifikasiJabatan">Klasifikasi Jabatan</option>' +
                                '</select>' +
                            '</div>' +
                            '<div class="col-1">' +
                                '<div class="box-delete">' +
                                    '<i class="fa fa-trash-o"></i>' +
                                '</div>' +
                            '</div>' +
                        '</div>';
            
            $('.modal-body .row:last').after(newRow);

            $('.modal-body .row:last .advance_label').select2({
                placeholder: "Select Filter"
            });

            $('.modal-body .row:last .advance_filter').select2({
                placeholder: "Select Filter"
            });
        }); 

as you can see, i want to create a new row when i clicked a button, but the old row becomes regular HTML. can someone please tell me why and how to fix it? Thanks in advance

How to open chrome extension on some behavior?

The docs say that calling chrome.action.openPopup from the background script should open the chrome extension’s popup but I get the following:

Uncaught (in promise) TypeError: chrome.action.openPopup is not a function

I tried following this answer but I still get this error.

I’m using Version 122.0.6261.94 (Official Build) (x86_64), but others in the comments have said that the exact code works on their machines.

Here is a repo that demonstrates the issue.

Did chrome just get rid of support for this without updating their docs? It seems like most places I’ve seen this problem documented the issue is just closed and the initial asker states the proposed solution doesn’t work.

manifest.json:

{
  "name": "Test Extension",
  "description": "Test Extension",
  "version": "1.0",
  "manifest_version": 3,

  "permissions": ["webNavigation"],
  "action": { "default_popup": "popup.html" },
  "background": { "service_worker": "background.js" }
}

background.js:

chrome.webNavigation.onCompleted.addListener(
  async () => {
    await chrome.action.openPopup();
  },
  { url: [
    { urlMatches: 'https://example.org/' },
  ] },
);

popup.html:

<!doctype html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Test Extension</title>
    <script src="popup.js"></script>
  </head>
  <body>
  </body>
</html>

popup.js:

document.addEventListener('DOMContentLoaded', () => {
  document.body.textContent = 'This is a test.';
});

How to send a complex object with images to .net Core 8 server with javascript?

I’m trying to understand what is the best approach to sending the following object to a asp.NET 8 core web application. It is not a web api, just a normal website accepting a complex object input. Here is the object I am referring to:

public class ComponentModel
{
    public Guid Id { get; set; }
    public String SomeOtherValuesLikeThis { get; set; }
    public IList<ElementModel> Elements { get; set; } = new List<ProductComponentElementModel>();
}

public class ElementModel
{
    public Guid Id { get; set; }
    public String SomeOtherValuesLikeThis { get; set; }
    public IFormFile File { get; set; }
}

Normally I would do an ajax call which would allow me to send the complex object in form of json and that would look like this:

$.ajax({
    url: "/Some/Uri",
    type: "POST",
    data: myComplexObjectBuiltInJavascript,
    success: function (response) {
        //Do Some Logic
    },
    error: function (error) {
        //Throw an error
    },
    complete: function () {
        //Do Something
    }
});

However, because my ElementModel has a IFormFile I now have to send this object as a FormData (at least to my understanding, correct me if I am wrong). Something like this:

var data = new FormData();
data.append("Id", SomeId);

As the above is a linear build, I am failing to understand how do I turn this into a complex object, is this even possible? If not, what is another way I can send a complex object like above to my server with potentially multiple files.

If this is simply not possible or this is bad practice for some reason, how do you suggest that I send this complex data to my server?

So far I have thought of two approaches:

  1. Split into two types of calls, first call the parent to ensure the parent record is created, then second call for children (but this would result in many calls unless there is a way to do an array object that contains images and other fields).
  2. upload the complex object as is, then do a second call with images only and some way to reference where they belong.

The above ideas result in partial creation which I don’t like, means a lot of cleanup if the subsequent calls fail. Right now I am leaning towards method 2 as a result of this as it feels less messy.

How should I approach this?

Note: If you provide an answer, please try to use code examples to help me better understand.

Google maps marker.AdvancedMarkerElement is Undefined Error

I am trying to load this example into a C# ASP.Net server. I am getting an error message: Google maps marker.AdvancedMarkerElement is undefined

Reference Code:

  1. Report.cshtml
    Note: Insert your API key
@*
    For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
*@
@{
}
<div id="map"></div>
@section Scripts{
    <script>
        function initMap() {
            const position = { lat: -25.344, lng: 131.031 };

            const map = new google.maps.Map(document.getElementById("map"), {
                zoom: 4,
                center: position,
                mapId: "DEMO_MAP_ID", // Map ID is required for advanced markers.
            });

            // The advanced marker, positioned at Uluru
            const marker = new google.maps.marker.AdvancedMarkerElement({
                map,
                position: position,
                title: 'Uluru',
            });
        };
        $(document).ready(function () {
            window.initMap = initMap;
        });
        
    </script>
    <script src="https://maps.googleapis.com/maps/api/js?key=xxxxxx&callback=initMap&v=weekly&loading=async"
            defer>
    </script>
}
  1. Controller
using FastTestMap.Models;
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;

namespace FastTestMap.Controllers
{
    public class HomeController : Controller
    {
        private readonly ILogger<HomeController> _logger;

        public HomeController(ILogger<HomeController> logger)
        {
            _logger = logger;
        }

        public IActionResult Index()
        {
            return View();
        }

        public IActionResult Privacy()
        {
            return View();
        }
        public IActionResult Report()
        {
            return View();
        }

        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
        public IActionResult Error()
        {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }
    }
}

I am trying to run the above example using the example provided on Google Advance Marker Element and I think the problem is with the way the library is getting loaded. I believe that the library is deferring its load, therefore the advance marker is undefined.

I tried the stackoverflow solution in comments to no end.

Firefox AudioWorklet:process/MessagePort bug?

I’m using Web Audio API AudioWorklet to encode MP3 in real-time. Testing the source code on Chromium 124 and Firefox Nightly 125.

Here’s what I think is the relevant part of the specification: 1.32.5.3. Callback AudioWorkletProcessCallback.

When a message is posted to the MessagePort I set the this.done variable to true, which indicates we’re done processing audio

  constructor(options) {
    super(options);
    this.mp3encoder = new lamejs.Mp3Encoder(2, 44100, 128);
    this.done = false;
    this.controller = void 0;
    this.readable = new ReadableStream({
      start: (c) => {
        return this.controller = c;
      }
    });
    this.port.onmessage = (e) => {
      this.done = true;
    }
  }

The part of the code that makes me think Firefox has a bug in the implemation is here. Note the commented parts that close the MessagePort, and return false.

  process(inputs, outputs) {
    if (this.done) {
      try {
        this.write(inputs.flat());
        const mp3buffer = this.mp3encoder.flush();
        if (mp3buffer.length > 0) {
          this.controller.enqueue(new Uint8Array(mp3buffer));
          this.controller.close();
          this.port.postMessage(this.readable, [this.readable]);
          // this.port.close();
          return false;
        }
      } catch (e) {
         this.port.postMessage(e.message);
         // this.port.close();
         return false;
      }
    }

    this.write(inputs.flat());
    return true;
  }

On Firefox 125, if we don’t explicitly close the MessagePort the catch block will send a couple thousand messages to the MessagePort in the main thread, see the screenshot here https://gist.github.com/guest271314/82daabb4e0cc02d39f588fbc0f15189d, in spite of return false. That doesn’t happen on Chromium 124.

The specification appears to me to indicate an AudioWorkletNode can remain active even after return false is run in process(), if I’m reading the specification correctly

Such nodes SHOULD return false from process() which allows the presence or absence of connected inputs to determine whether the AudioWorkletNode is actively processing.

That leads me to suspect that the MessagePort can remain active after the AudioWorkletNode has effectively been disconnected.

I understand there is no specified way to determine if a MessagePort is neutered. However, I am not expecting that behaviour, which is mitigated when the MessagePort is explicitly closed by uncommenting the lines in the above code.

Is this a Firefox bug?

Having problems with FS nodejs in Electron

After my own learning efforts I was finally able to control the gpio of orangepi lite via electron, but I’m having problems when trying to use the push button, the line like fs.watch doesn’t work at all re-read values or maybe my callback function was not working. I need some advice and guidance

I also tried using setInterval but that caused the app to stop working, the buttons still work fine with the PinRead function but I have no way of using it continuously

here is my code

// Modules to control application life and create native browser window
const { app, BrowserWindow, ipcMain } = require('electron')
const path = require('node:path')
const { Gpio } = require('./user_modules/userGpio');

const led = new Gpio(10, 'out');
const button = new Gpio(20, 'in');

function createWindow() {
  // Create the browser window.
  const mainWindow = new BrowserWindow({
    width: 350,
    height: 320,
    webPreferences: {
      //    NodeIntegration : true,
      //    contextIsolation: false,

      preload: path.join(__dirname, 'preload.js')

    },

  })

  // and load the index.html of the app.
  mainWindow.loadFile('index.html')

  // Open the DevTools.
  // mainWindow.webContents.openDevTools()
}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(() => {
  createWindow()


  //button on html
  ipcMain.on('HTML_BTN', (_, msg) => {
    console.log(msg);
    led.PinWrite(led.PinRead() ^ 1);

    
    console.log('pin20 are :' + button.PinRead() + 'n');

  })


  app.on('activate', function () {
    // On macOS it's common to re-create a window in the app when the
    // dock icon is clicked and there are no other windows open.
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })

  //---------------------------------------------------
  // ctrl +c
  process.on('SIGINT', _ => {
    //user code
    led.UnExportGpio();
    button.UnExportGpio();
  });
})

// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', function () {
  if (process.platform !== 'darwin') app.quit();
})

// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.

//USER FUNCTION
//button on hardware
button.PinWatch((value) => {
  console.log('Button state changed:', value + 'n');
  ipcMain.send('HARDWARE_BTN', value);
});

Loop through Javascript object and append key values to function

I’m adding custom UI buttons to a CMS (via Tampermonkey) with respective click functions. Code is functional but I’m refining by converting the individual button elements to render the html based on an object’s key/value pairs. That part works fine.

The issue: each button element has a separate click function that I want to consolidate into a single function and append the iterated object’s values to based on the current key. Constantly hitting a wall when injecting the function. Thanks in advance.

New format with object

let campaignButtons = {
  "1000": {
    id: "ten-zero-zero",
    cta: "1000",
    width: "45",
    onclick: "tenZeroZeroClick",
    function: "tenZeroZeroButtonClick",
    input: "#10 #00 - 1000"
  },
  "20": {
    id: "twenty",
    cta: "20",
    width: "35",
    onclick: "twentyClick",
    function: "twentyButtonClick",
    input: "#20 - 20"
  }
}

const generatedHtml = Object.keys(campaignButtons).reduce((accum, currKey) => accum + `<span style="display: block;"><button onclick="${campaignButtons[currKey].onclick}" id="${campaignButtons[currKey].id}" style="margin-right: 0.571429rem;background-color: rgb(36, 137, 169);color:#fff;border-radius:300px;border:none"><div style="height: 20px;width: 25px;display: flex;align-items: center;justify-content: center;">${campaignButtons[currKey].cta}</div></button></span>`, '');

// need help here, this function returns an error
const generatedFunctionOne = Object.keys(campaignButtons).reduce((accum, currKey) => accum + function $ {
  campaignButtons[currKey].function
}() {
  var input = document.querySelector('[id="campaign-search-input"]');
  var nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value").set;
  nativeInputValueSetter.call(input, '${campaignButtons[currKey].searchQuery}');
  var ev2 = new Event('input', {
    bubbles: true
  });
  input.dispatchEvent(ev2);
}, '');

Initial setup with separate elements & functions

let tenZeroZero = '<span class="sc-GQHCi fjxikX" style="display: block;"><button id="ten-zero-zero" class="sc-cUEOzv hEBGGF eEeywh" style="margin-right: 0.571429rem;background-color: rgb(36, 137, 169);color:#fff;border-radius:300px;border:none"><div style="height: 20px;width: 35px;display: flex;align-items: center;justify-content: center;">1000</div></button></span>';

let twentyOnly = '<span class="sc-GQHCi fjxikX" style="display: block;"><button id="twenty-only" class="sc-cUEOzv hEBGGF eEeywh" style="margin-right: 0.571429rem;background-color: rgb(36, 137, 169);color:#fff;border-radius:300px;border:none"><div style="height: 20px;width: 35px;display: flex;align-items: center;justify-content: center;white-space:pre">20</div></button></span>';


// want to append iterated objects values to this function
function tenZeroZeroClick() {
  var input = document.querySelector('[id="campaign-search-input"]');
  var nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value").set;
  nativeInputValueSetter.call(input, '#10 #00 - 1000');
  var ev2 = new Event('input', {
    bubbles: true
  });
  input.dispatchEvent(ev2);
}

function twentyClick() {
  var input = document.querySelector('[id="campaign-search-input"]');
  var nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value").set;
  nativeInputValueSetter.call(input, '#20 - 20');
  var ev2 = new Event('input', {
    bubbles: true
  });
  input.dispatchEvent(ev2);
}

function addTenZeroZero() {
  document.querySelector('[id="new-button-container"]').insertAdjacentHTML('beforeend', tenTwenty);
  document.getElementById("ten-zero-zero").onclick = function() {
    tenZeroZeroClick();
  };
}

function addTwentyOnly() {
  document.querySelector('[id="new-button-container"]').insertAdjacentHTML('beforeend', twentyOnly);
  document.getElementById("twenty-only").onclick = function() {
    twentyClick();
  };
}

How do I add a button to a login modal in a Dropdown component in reactstrap?

I am trying to have a button that opens a modal in my dropdown, but either it opens twice or doesn’t open at all and I don’t know why. When I try to enter anything in the input field, the modal closes. I have tried replacing with a but it didn’t seem to work and the modal closed immediately.

import React, { useState } from 'react';
import { Button, Modal, ModalHeader, ModalBody, ModalFooter ,  Dropdown,
  DropdownToggle,
  DropdownMenu,
  DropdownItem, Input} from 'reactstrap';

function ExampleModal() {
  const [modal, setModal] = useState(false);
  const toggleModal = () => setModal(!modal);

  return (
    <div>
      <Button color="danger" onClick={toggleModal}>
        Click Me
      </Button>
      <Modal isOpen={modal} toggle={toggleModal}>
        <ModalHeader toggle={toggleModal}>Modal title</ModalHeader>
        <ModalBody>
          Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
          eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
          minim veniam, quis nostrud exercitation ullamco laboris nisi ut
          aliquip ex ea commodo consequat. Duis aute irure dolor in
          reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
          pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
          culpa qui officia deserunt mollit anim id est laborum.
          <Input id="input" required />
        </ModalBody>
        <ModalFooter>
          <Button color="primary" onClick={toggleModal}>
            Do Something
          </Button>{" "}
          <Button color="secondary" onClick={toggleModal}>
            Cancel
          </Button>
        </ModalFooter>
      </Modal>
    </div>
  );
}

function ExampleDropdown() {
  const [dropdownOpen, setDropdownOpen] = useState(false);
  const toggleDropdown = () => setDropdownOpen((prevState) => !prevState);

  return (
    <div className="d-flex p-5">
      <Dropdown
        isOpen={dropdownOpen}
        toggle={toggleDropdown}
        direction={"down"}
      >
        <DropdownToggle caret>Dropdown</DropdownToggle>
        <DropdownMenu>
          <DropdownItem>Foo Action</DropdownItem>
          <DropdownItem>Bar Action</DropdownItem>
          <DropdownItem>Quo Action</DropdownItem>
          <ExampleModal />
        </DropdownMenu>
      </Dropdown>
    </div>
  );
}