admob-plus in Android Studio: make banner invisible on certain pages

I have successfully got a cordova project running with admob-plus plugin in Android Studio. The banners work perfectly on various pages. Google Play has rejected the app because banners are visible on the embedded YouTube pages. I would like to change this and make them invisible on these pages. My question: How can I make a banner invisible on pages with YouTube videos? The banners appear automatically and are above the iframe. My attempts with additional iFrames and z-index always show the admob banner. Even links to external html pages with YouTube videos always show the banner that is superimposed on top. How can I make the banner invisible directly on the pages?

In the header of the html pages I have linked to cordova.js and admob.js and then added these snippets with the corresponding AdUnitID:

<script type="text/javascript" src="cordova.js"></script>
    <script type="text/javascript" src="plugins/admob-plus-cordova/www/admob.js"></script>
    <script>
        let banner

      document.addEventListener('deviceready', async () => {
        banner = new admob.BannerAd({
          adUnitId: 'ca-app-pub-xxx/yyy',
        })

        banner.on('impression', async (evt) => {
          await banner.hide()
        })

        await banner.show()
      }, false)
    </script>

On the html page with embedded Youtube iframe I used the snippet, which does not hide the banner:

    <script type="text/javascript" src="cordova.js"></script>
    <script type="text/javascript" src="plugins/admob-plus-cordova/www/admob.js"></script>
    <script>
        document.addEventListener('deviceready', async () => {
   // Obtain user consent first

   await admob.hide() // or start loading ads

   // Load ads here
 }, true)

Is it not possible to do this directly on the corresponding html page? Do I have to add the MainActivity.java so that I can hide the banner on the YouTube page? I have been looking for a solution for days and would be very grateful for any help.

MainAcitivity.java

package ...
import ...

public class MainActivity extends CordovaActivity
{
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        // enable Cordova apps to be started in the background
        Bundle extras = getIntent().getExtras();
        if (extras != null && extras.getBoolean("cdvStartInBackground", false)) {
            moveTaskToBack(true);
        }

        // Set by <content src="index.html" /> in config.xml
        loadUrl(launchUrl);
    }
}

How to display the alphabets in a descending order with a Javascript loop?

After a click on the button, there should be a randomly generated alphabet shown at the top, and a table of alphabets below, in either ascending or descending order.

If the index of the top alphabet in the array alphabets is an even number, the order of the table below should be ascending. Take ‘f’ as an example of the top alphabet, the order in the table should go like, from left to right, ‘g’ -> ‘h’ -> ‘i’ -> ‘j’ -> ‘k’ -> ‘a’ -> ‘b’ -> …

If that index is an odd number, then the order of the table should be descending. With the same example, ‘f’ at the top, the table below should go like, again from left to right, ‘e’ -> ‘d’ -> ‘c’ -> ‘b’ -> ‘a’ -> ‘k’ -> ‘j’ -> …

I’d like to ask that, how to change my piece of code of the for loop in JS, in order to achieve such an effect?

const alphabets = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k'];
const random = document.getElementById('random');
let display = document.getElementsByClass('display');

function click() {
  var num = Math.floor(Math.random() * 11);
  random.innerHTML = alphabets[num];
  
  if (num % 2 = 0) {
    for (let a = 0; a < 12; a++) {
      display[a].innerHTML = alphabets[(a + num) % 12];
    }
  } else {
    for (let a = 0; a < 12; a++) {
      for (let b = 0; b > -12; b--) {
        display[a].innerHTML = alphabets[(b - num) + 12];
      }
    }
  }
}
div h1, div h6, div table tr td {
  color: black;
}
<div>
  <button onclick='click()'>Generate!</button>
  <h1>Random Alphabet: </h1>
  <h6 id="random"></h6>
</div>
<div>
  <h1>Display: </h1>
  <table>
    <tr>
      <td class="display"></td>
      <td class="display"></td>
      <td class="display"></td>
      <td class="display"></td>
      <td class="display"></td>
      <td class="display"></td>
      <td class="display"></td>
      <td class="display"></td>
      <td class="display"></td>
      <td class="display"></td>
      <td class="display"></td>
    </tr>
  </table>
</div>

Why does fs.writeFile fail to create and write data?

I am trying to write a JSON file and for some reason fs.writeFile just won’t create and write the string in the file. The function described is being called by an HTML button :

<button type="button" onclick="writeJson ();">Write</button>

I press the button and nothing happens. I had error/success outputs in the function, but took them out in case they were causing the function to fail.
I am 99% sure it’s my syntax causing it, but I can’t seem to see where.

function writeJson () {
const fs = require('node:fs');
const stri= "test";
fs.writeFile('Test.json', stri, err => {
  if (err) {
   
  } else {
    
  }
});
}

Google Maps API (Cloud Platform) How to change this text color using style editor (instead of JSON Array)?

Map preview at Cloud Platform Style Editor

When I changed the text fill color and stroke color it appears all fine on the preview Custom Maps editor, but when I applied the custom style to map-ID, and use the map-ID in javascript, the text color are not consistent; the POI has the expected color, but its business nature / type /or review rating has all different colors (as below)

screenshot of map showing text with different colors

At the moment I could only change their colors by using JSON array (instead of applying map styles to map-ID). Is there anyway to makes all text descriptions the same color?

Problems with Webpack and React

i am fighting with webpack since quite some time now. Basically i am trying to get it to run with my React Application.

My rough folder structure is:

-
|__ public/
    |__ index.html
|__ src/
    |__ App.js
    |__ index.js
    |___ ....
|___ .babelrc
|___ webpack.config.js

My webpack config looks like this:

const path = require('path');
const webpack = require('webpack')

const isDevelopment = process.env.MODE !== 'production';

console.log(`isDev: ${isDevelopment}`)

module.exports = {
    mode: isDevelopment ? 'development' : 'production',
    devtool: 'inline-source-map',
    context: __dirname,
    entry: {
        main: './src/index.js'
    },
    output: {
        path: path.resolve( __dirname, 'dist' ),
        filename: '[name].bundle.js',
        publicPath: '/',
    },
    stats: 'minimal',
    module: {
        rules: [
            {
                test: /.js$/,
                use: 'babel-loader',
            },
            {
                test: /.(sass|less|css)$/,
                use: ['style-loader', 'css-loader']
            },
            {
                test: /.(png|jpe?g|svg|gif)?$/,
                exclude: /node_modules/,
                use: 'file-loader'
            }
        ]
    },
    plugins: [
        new webpack.ProvidePlugin({
            process: 'process/browser',
          }),
    ],
    devServer: { 
        hot: false, // disable hot reloading temporarily 
        port: 9000, 
        open: true, 
    },
}

This is how my index.js looks like:

import React from 'react';
import ReactDOM from 'react-dom/client';
import 'bootstrap/dist/css/bootstrap.min.css';
import 'rsuite/dist/rsuite.min.css';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App/>);

This is the .babelrc:

{
    "presets": [
        "@babel/preset-env", 
        "@babel/preset-react"
    ]
}
  

This is the index.html:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link
      rel="stylesheet"
      href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
      integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor"
      crossorigin="anonymous"
    />
    <title>Blog</title>
  </head>
  <body>
    <div id="root"></div>
    <script src="main.bundle.js"></script>
  </body>
</html>

I tried alot of iterations on the config and none of them worked. Currently have a white screen and a js error on the console:

bootstrap:19 Uncaught TypeError: __webpack_modules__[moduleId].call is not a function
    at __webpack_require__ (bootstrap:19:1)
    at ./node_modules/axios/lib/axios.js (xhr.js:197:2)
    at __webpack_require__ (bootstrap:19:1)
    at ./src/utils/APIHandler.js (Writeups.js:80:24)
    at __webpack_require__ (bootstrap:19:1)
    at ./src/components/contact/index.js (App.js:62:19)
    at __webpack_require__ (bootstrap:19:1)
    at ./src/pages/home/Home.js (EditWriteup.js:154:1)
    at __webpack_require__ (bootstrap:19:1)
    at ./src/App.js (svg-injector.esm.js:317:1)

Changing the direction of a CSS animation through javascript

Take the following example :

const keybind = {
  "ArrowDown": function(event) {
    document.getAnimations().forEach(animation => animation.currentTime += 1000);
    document.getAnimations().forEach(animation => animation.currentTime = Math.min(animation.currentTime, animation.effect.getTiming().duration));
  },
  "ArrowUp": function(event) {
    document.getAnimations().forEach(animation => animation.currentTime -= 1000);
    document.getAnimations().forEach(animation => animation.currentTime = Math.max(animation.currentTime, 0));
  }
}
document.body.addEventListener("keydown", (event) => keybind[event.key] && keybind[event.key](event));
@keyframes slide {
  0% {
    object-position: top;
  }
  100% {
    object-position: bottom;
  }
}

body {
  width: 100%;
  height: 100%;
  overflow:hidden;
}

img {
  width: 100%;
  height: 256px;
  object-fit: cover;
  animation-name: "slide";
  animation-duration: 5s;
  animation-timing-function:linear;
  animation-fill-mode:both;
  animation-play-state: paused;
}
<img src="https://i.sstatic.net/eAebw9Zv.jpg" alt="example image">

You should be able to scroll the image by using the arrow up / arrow down keys (it does require keyboard focus to work ie. by clicking on the image first).

it does this by setting the currentTime property of the animation. The interesting part is what happens with arrowUp. Here we are subtracting from the current time, giving the illusion of going backwards. however if we were to change animation-direction it would reverse the whole animation and the arrowUp code would add instead of subtracting to achieve the same effect.

Basically the two approaches are either adding and subtracting from currentTime, or else somehow changing the direction of the animation. I thought the second option was rather elegant as we can re-use some code

Calling animation.reverse() function doesn’t seem to affect the animation direction, as far as I can tell what it does is something like

animation.playbackRate *= -1;
animation.currentTime = animation.effect.getTiming().duration - animation.currentTime;
animation.play();

We still go back and forth by subtracting and adding to currentTime

Javascript doesn’t seem to allow us to change the CSS animation-direction without messing around with animation.effect.target.style.animationDirection = "reverse" and things, which I kinda hate. I feel that I’m just missing a property somewhere that determines the direction of the animation that can just be checked and set.

The only other thing I can think of is using a property on the image animation.effect.target.dataset.playback = "reverse" and adding a CSS rule to the stylesheet, which is still a little ham-fisted IMO

Here is the same example using that :

const setDirection = function(value) {
  if (document.getAnimations().every(animation => animation.effect.target.dataset.playback != value)) {
    for (const animation of document.getAnimations()) {
      animation.effect.target.dataset.playback = value;
      animation.currentTime = animation.effect.getComputedTiming().duration - animation.currentTime;
    }
  }
}

const step = function() {
  document.getAnimations().forEach(animation => animation.currentTime += 1000);
  document.getAnimations().forEach(animation => animation.currentTime = Math.min(animation.currentTime, animation.effect.getTiming().duration));
} 

const keybind = {
  "ArrowDown": function(event) {
    setDirection("normal");
    step();    
  },
  "ArrowUp": function(event) {
    setDirection("reverse");
    step();    
  }
}
document.body.addEventListener("keydown", (event) => keybind[event.key] && keybind[event.key](event));
@keyframes slide {
  0% {
    object-position: top;
  }
  100% {
    object-position: bottom;
  }
}

body {
  width: 100%;
  height: 100%;
  overflow:hidden;
}

img {
  width: 100%;
  height: 256px;
  object-fit: cover;
  animation-name: "slide";
  animation-duration: 5s;
  animation-timing-function:linear;
  animation-fill-mode:both;
  animation-play-state: paused;
}
img[data-playback = "reverse"] {
  animation-direction:reverse;
}
<img src="https://i.sstatic.net/eAebw9Zv.jpg" alt="example image" data-playback="normal">

As usual, I mostly answered my own question while writing it but I’ll post it anyway in case someone in the future is in the same situation. I would like to know if there is a simpler way to change the animation-direction style via javascript though, and if not why is the property not accessible ?

I want to get the properties of the pressed forms button in PHP

I’m trying to make a note change editor in php and MySQL. But I ran into a problem. There are a lot of notes and to get the right one, I decided to stuff the ID, date, text and title into the properties of the button, but I don’t know how to get the data of a specific note so that.

$sql = "SELECT * FROM notes WHERE id_user = ".$_SESSION['id_user']."";
if($result = mysqli_query($mySql, $sql)){
  $results='';
   foreach($result as $row) {
       $results.='<section class="notes-section section" id="notesCard">
                     <div id= "noteContent" class="note-content">
                         <div class="note-h2"><h2 id="headingH2">'.$row['heading'].'</h2></div>
                         <div class="note-text"><p id="textArea">'.$row['text_content'].'</p></div>
                         <div class="note-panel">
                             <label id="dateNotes" for="">'.$row['date'].'</label>
                             <form action="editNote.php" name="" method="post">
                                <button name="editNotes" id="edit" class="insert-btn btn" value="'.$row['id_notes'].'">Изменить</button>
                                <button name="deleteNotes" class="delete-btn btn" value="'.$row['id_notes'].'">Удалить</button>
                                </form>
                         </div>
                     </div>
                </section>';
     }
  echo $results;
} else {
  echo "Что-то пошло не так...";
}

if (isset($_POST['deleteNotes']) and is_numeric($_POST['deleteNotes'])) {
  $delete = $_POST['deleteNotes'];
  if ($mySql -> query("DELETE FROM `notes` WHERE `id_notes` = '$delete'")) {
    
    echo '<script>window.location = "./notes.php"</script>';
  }
}

I tried to do everything through js, but I don’t have enough knowledge for this

Sorry for the bad English, Google Translate translated everything

OfficeScript says it is writing to designated excel sheet, but no text appears and no errors given

I cannot get my office script to write any data in the “Data” sheet. I get no errors from running the script and it does say it writes the data but then nothing is there… I’ve tried everything I know to do at this point so I am thankful for any direction that be can be given!

Here is my script:

> > /**
> This script submits data from the "Setup" sheet to the "Data" sheet,
> adds the data to the next available line (skipping a line between entries),
> and clears only the contents of the input fields on the "Setup" sheet, retaining validation.
> */
> function main(workbook: ExcelScript.Workbook) {
> Access the "Setup" and "Data" sheets
> const setupSheet = workbook.getWorksheet("Setup");
> let dataSheet = workbook.getWorksheet("Data");
> 
> Create "Data" sheet if it doesn't exist
> if (!dataSheet) {
> dataSheet = workbook.addWorksheet("Data");
> Optionally, set up headers in the "Data" sheet
> dataSheet.getRange("A1:H1").values = [["G4", "G6", "G8", "D10", "D11", "D12", "D15", "D23"]];
> >     }
> 
> Get data from specified cells on the "Setup" sheet
> const values = [
> setupSheet.getRange("G4").getText(),
> setupSheet.getRange("G6").getText(),
> setupSheet.getRange("G8").getText(),
> setupSheet.getRange("D10").getText(),
> setupSheet.getRange("D11").getText(),
> setupSheet.getRange("D12").getText(),
> setupSheet.getRange("D15").getText(),
> setupSheet.getRange("D23").getText(),
> >     ];
> 
> Find the next available row on the "Data" sheet, skipping a row
> const usedRange = dataSheet.getUsedRange();
> let lastRow = usedRange ? usedRange.getRowCount() : 1; // If no data, start at row 1
> let nextRow = lastRow + 2; // Skip a row after the last data row
> 
> Add data to the next row (skipping a row in between entries)
> const targetRange = dataSheet.getRange(`A${nextRow}:H${nextRow}`);
> targetRange.values = [values];
> 
> Clear only the contents of the input cells on the "Setup" sheet
> setupSheet.getRange("G4").clear(ExcelScript.ClearApplyTo.contents);
> setupSheet.getRange("G6").clear(ExcelScript.ClearApplyTo.contents);
> setupSheet.getRange("G8").clear(ExcelScript.ClearApplyTo.contents);
> setupSheet.getRange("D10").clear(ExcelScript.ClearApplyTo.contents);
> setupSheet.getRange("D11").clear(ExcelScript.ClearApplyTo.contents);
> setupSheet.getRange("D12").clear(ExcelScript.ClearApplyTo.contents);
> setupSheet.getRange("D15").clear(ExcelScript.ClearApplyTo.contents);
> setupSheet.getRange("D23").clear(ExcelScript.ClearApplyTo.contents);
> > }
> 
> 

I’ve tried several variations of this script, even using a simple script that would just enter “Text” into A1 and nothing is working. Workbook is fresh on my PC, no protections set to workbook. I appreciate any help!

“GaxiosError: Login Required – Google OAuth2 Token Expiry Handling in Node.js Gmail API Integration

I am trying to access my gmail , so that i can calculate the money that i spent on food from this place using receipts that they sent me , i followed all steps on Node js quickstart page and was even able to access labels the first time i logged in , after which i kept running into this Login Required error

const fs = require("fs").promises;
const path = require("path");
const process = require("process");
const { authenticate } = require("@google-cloud/local-auth");
const { google } = require("googleapis");

// If modifying these scopes, delete token.json.
const SCOPES = ["https://www.googleapis.com/auth/gmail.readonly"];
// The file token.json stores the user's access and refresh tokens, and is
// created automatically when the authorization flow completes for the first
// time.
const TOKEN_PATH = path.join(process.cwd(), "token.json");
const CREDENTIALS_PATH = path.join(process.cwd(), "credentials.json");

/**
 * Reads previously authorized credentials from the save file.
 *
 * @return {Promise<OAuth2Client|null>}
 */
async function loadSavedCredentialsIfExist() {
  try {
    const content = await fs.readFile(TOKEN_PATH);
    const credentials = JSON.parse(content);
    return google.auth.fromJSON(credentials);
  } catch (err) {
    return null;
  }
}

/**
 * Serializes credentials to a file compatible with GoogleAuth.fromJSON.
 *
 * @param {OAuth2Client} client
 * @return {Promise<void>}
 */
async function saveCredentials(client) {
  const content = await fs.readFile(CREDENTIALS_PATH);
  const keys = JSON.parse(content);
  const key = keys.installed || keys.web;
  const payload = JSON.stringify({
    type: "authorized_user",
    client_id: key.client_id,
    client_secret: key.client_secret,
    refresh_token: client.credentials.refresh_token,
  });
  await fs.writeFile(TOKEN_PATH, payload);
}

/**
 * Load or request or authorization to call APIs.
 *
 */
const authorize = async () => {
  let client = await loadSavedCredentialsIfExist();
  if (client) {
    return client;
  }
  client = await authenticate({
    scopes: SCOPES,
    keyfilePath: CREDENTIALS_PATH,
  });
  if (client.credentials) {
    await saveCredentials(client);
  }
  return client;
}

/**
 * Lists the labels in the user's account.
 *
 * @param {google.auth.OAuth2} auth An authorized OAuth2 client.
 */


const listLabels = async (auth) => {
  const gmail = google.gmail({ version: "v1", auth });
  const res = await gmail.users.labels.list({
    userId: "me",
  });
  const labels = res.data.labels;
  if (!labels || labels.length === 0) {
    console.log("No labels found.");
    return;
  }
  return labels;
};

module.exports = { authorize , listLabels};

app.get("/getLabels", (req, res) => {
  console.log(`/getLabels hit with a get request n`);
  authorize()
    .then(async () => {
      const labels = await listLabels();

      res.status(200).json(labels);
    })
    .catch((err) => console.log(err, "some err happened"));
});
GaxiosError: Login Required.
    at Gaxios._request (D:YummpysBillservernode_modulesgaxiosbuildsrcgaxios.js:140:23)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async listLabels (D:YummpysBillserverutilsgmailConfig.js:77:15)
    at async D:YummpysBillserverindex.js:18:22 {
  response: {
    config: {
      url: 'https://gmail.googleapis.com/gmail/v1/users/me/labels',
      method: 'GET',
      userAgentDirectives: [Array],
      paramsSerializer: [Function (anonymous)],
      headers: [Object],
      params: {},
      validateStatus: [Function (anonymous)],
      retry: true,
      responseType: 'json',
      retryConfig: [Object]
    },
    data: { error: [Object] },
    headers: {
      'alt-svc': 'h3=":443"; ma=2592000,h3-29=":443"; ma=2592000',
      'cache-control': 'private',
      'content-encoding': 'gzip',
      'content-type': 'application/json; charset=UTF-8',
      date: 'Sun, 24 Nov 2024 07:41:13 GMT',
      server: 'ESF',
      'transfer-encoding': 'chunked',
      vary: 'Origin, X-Origin, Referer',
      'www-authenticate': 'Bearer realm="https://accounts.google.com/"',
      'x-content-type-options': 'nosniff',
      'x-frame-options': 'SAMEORIGIN',
      'x-xss-protection': '0'
    },
    status: 401,
    statusText: 'Unauthorized',
    request: {
      responseURL: 'https://gmail.googleapis.com/gmail/v1/users/me/labels'
    }
  },
  config: {
    url: 'https://gmail.googleapis.com/gmail/v1/users/me/labels',
    method: 'GET',
    userAgentDirectives: [ [Object] ],
    paramsSerializer: [Function (anonymous)],
    headers: {
      'x-goog-api-client': 'gdcl/6.0.4 gl-node/20.18.0',
      'Accept-Encoding': 'gzip',
      'User-Agent': 'google-api-nodejs-client/6.0.4 (gzip)',
      Accept: 'application/json'
    },
    params: {},
    validateStatus: [Function (anonymous)],
    retry: true,
    responseType: 'json',
    retryConfig: {
      currentRetryAttempt: 0,
      retry: 3,
      httpMethodsToRetry: [Array],
      noResponseRetries: 2,
      statusCodesToRetry: [Array]
    }
  },
  code: 401,
  errors: [
    {
      message: 'Login Required.',
      domain: 'global',
      reason: 'required',
      location: 'Authorization',
      locationType: 'header'
    }
  ]
} some err happened

How to overcome limit length

In V8 (used by Chrome and Node), the maximum length is 229 – 24 (~1GiB)

I created a parser, but when parsing a large file, oom occurs when the limit is exceeded.

It is a parser that parses all files at once and operates synchronously, so if that limit is exceeded, oom problems seem to occur.

In the v8 engine (used by Chrome and Node), is there any way to use many strings or memory over 1GB? It is okay to use binary rather than string.

I’d like to get some ideas.

The parser I wrote and use

Type created with keyof cannot be used to index type it was created from

I’m trying to write a utility function in my TypeScript project to sort/filter objects in a fairly predictable data model (I’m using Astro for this site). The objects keep all the data useful for sorting/filtering in the data property.

I cannot figure out how to properly type this function, which takes a collection of objects and the name of a property as arguments: foo( collection, property ) { ... }.

Here’s a super simplified version of what I’ve been trying to do. It doesn’t take a collection as the first arg, but the gist is the same: I want to pass in the name of a property in data and then access the value of that property.

interface User {
  data: {
    id: number;
    name: string;
  }
}
interface House {
  data: {
    number: number;
    street: string;
  }
}
type Obj = User | House;

function getProperty<
  T extends Obj,
  K extends keyof T['data']
>(obj: T, key: K): T['data'][K] {
  return obj.data[key];
  // Type 'K' cannot be used to index type '{ id: number; name: string; } | { number: number; street: string; }'.ts(2536) 
}
const user: User = { data: { id: 1, name: "Alice" }};
const house: House = { data: { number: 2, street: "First" }};

const userName = getProperty(user, "name");
const houseNumber = getProperty(house, "number");

TypeScript understands what’s going on with the function, as the last two lines won’t let me pass in a property name that isn’t in the corresponding object’s data. But for the life of me, I don’t know how to get K to behave.

How can I pass the promise as a provider to Nextjs14 in Layout

How to Handle Promises in a Provider Component in Next.js 14 Layout?

I’m trying to use LucidProvider in my Next.js 14 layout to wrap all my components. Inside the provider, I initialize Lucid and update the state. However, Lucid returns a promise, which is causing the following error:

Error: Element type is invalid. Received a promise that resolves to: undefined. Lazy element type must resolve to a class or function.

Here’s the initialization logic in LucidProvider.tsx:

const blockfrost = new Blockfrost(BF_URL, BF_PID);
Lucid(blockfrost, NETWORK).then(setLucid).catch((error) => console.log(error));

When I comment out these lines, the error disappears. I’ve tried different approaches, including using default and named imports, as well as dynamic, but none of them resolved the issue. How can I properly pass the resolved promise as a provider in the Next.js 14 layout?

LucidProvider.tsx


'use client';

import React, { createContext, useContext, useEffect, useState } from "react";
import { Blockfrost, Lucid, LucidEvolution, Network } from "@lucid-evolution/lucid";

interface LucidContextType {
  lucid: LucidEvolution | undefined;
}

const LucidContext = createContext<LucidContextType | undefined>(undefined);

const BF_URL = process.env.NEXT_PUBLIC_BF_URL!;
const BF_PID = process.env.NEXT_PUBLIC_BF_PID!;
const NETWORK = process.env.NEXT_PUBLIC_CARDANO_NETWORK as Network;

export interface ProvidersProps {
  children: React.ReactNode;
}
export default function LucidProvider({ children }: ProvidersProps) {
  const [lucid, setLucid] = useState<LucidEvolution>();

  useEffect(() => {
    const blockfrost = new Blockfrost(BF_URL, BF_PID);
    Lucid(blockfrost, NETWORK).then(setLucid).catch((error) => console.log(error));
  }, []);

  return (
    <LucidContext.Provider value={{ lucid, }}>
      {children}
    </LucidContext.Provider>
  );
};

export const useLucid = () => {
  const context = useContext(LucidContext);
  if (!context) throw new Error("useLucid must be used within a LucidProvider");
  return context;
};

Layout.tsx

import dynamic from "next/dynamic";
// const LucidProvider = dynamic(() => import('./LucidProvider'))
import LucidProvider from "./LucidProvider";
..
..
..
..
..
export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html suppressHydrationWarning lang="en">
      <head />
      <body className={clsx(
        "min-h-screen bg-background font-sans antialiased",
        fontSans.variable,
        fontComfortaa.variable
      )}>
        <LucidProvider>
        <Navbar />
          <Providers themeProps={{ attribute: "class", defaultTheme: "dark" }}>
            <div className="relative flex flex-col h-screen">
              <main className="container mx-auto  flex-grow">{children}</main>
            </div>
          </Providers>
        </LucidProvider>
      </body>
    </html>
  );
}

AMCharts Only Plotting Last Data Point

I have been trying to get AMCharts to plot about 50 data points, but for some reason it’s only plotting the very last data point with an incorrect date of the epoch (Jan 20, 1970).

I have a jsfiddle setup with a basic example – https://jsfiddle.net/wmL3s8b1/

The data is in a date / value format like the documentation states it should be and the documentation also states that the date should be in a timestamp format, so that is what I’m providing, but it seems to be ignoring the timestamp and using Jan 20, 1970. It’s also only displaying the very last value.

Each data point is 1 day apart and I have set the interval to 1 day.

var data = [{date: 1732233600, value: 133},{date: 1732320000, value: 124},{date: 1732406400, value: 184},{date: 1732492800, value: 189},{date: 1732579200, value: 192},{date: 1732665600, value: 0},{date: 1732752000, value: 193},{date: 1732838400, value: 197},{date: 1732924800, value: 156},{date: 1733011200, value: 134},{date: 1733097600, value: 139},{date: 1733184000, value: 143},{date: 1733270400, value: 143},{date: 1733356800, value: 190},{date: 1733443200, value: 211},{date: 1733529600, value: 189},{date: 1733616000, value: 189},{date: 1733702400, value: 192},{date: 1733788800, value: 137},{date: 1733875200, value: 192},{date: 1733961600, value: 209},{date: 1734048000, value: 191},{date: 1734134400, value: 191},{date: 1734220800, value: 191},{date: 1734307200, value: 182},{date: 1734393600, value: 201},{date: 1734480000, value: 192},{date: 1734566400, value: 188},{date: 1734652800, value: 184},{date: 1734739200, value: 179},{date: 1734825600, value: 180},{date: 1734912000, value: 173},{date: 1734998400, value: 214},{date: 1735084800, value: 283},{date: 1735171200, value: 287},{date: 1735257600, value: 296},{date: 1735344000, value: 288},{date: 1735430400, value: 213},{date: 1735516800, value: 456},{date: 1735603200, value: 374},{date: 1735689600, value: 233},{date: 1735776000, value: 264},{date: 1735862400, value: 185},{date: 1735948800, value: 209},{date: 1736035200, value: 209},{date: 1736121600, value: 202},{date: 1736208000, value: 210},{date: 1736294400, value: 218},{date: 1736380800, value: 209},{date: 1736467200, value: 209},{date: 1736553600, value: 155}];

am5.ready(function() {

// Create root element
// https://www.amcharts.com/docs/v5/getting-started/#Root_element
var root = am5.Root.new("chartdiv");


// Set themes
// https://www.amcharts.com/docs/v5/concepts/themes/
root.setThemes([
  am5themes_Animated.new(root)
]);


// Create chart
// https://www.amcharts.com/docs/v5/charts/xy-chart/
var chart = root.container.children.push(am5xy.XYChart.new(root, {
  panX: true,
  panY: true,
  wheelX: "panX",
  wheelY: "zoomX",
  pinchZoomX:true,
  paddingLeft: 0
}));


// Add cursor
// https://www.amcharts.com/docs/v5/charts/xy-chart/cursor/
var cursor = chart.set("cursor", am5xy.XYCursor.new(root, {
  behavior: "none"
}));
cursor.lineY.set("visible", false);


// Create axes
// https://www.amcharts.com/docs/v5/charts/xy-chart/axes/
var xAxis = chart.xAxes.push(am5xy.DateAxis.new(root, {
  maxDeviation: 0.2,
  baseInterval: {
    timeUnit: "day",
    count: 1
  },
  renderer: am5xy.AxisRendererX.new(root, {
    minorGridEnabled:true
  }),
  tooltip: am5.Tooltip.new(root, {})
}));

var yAxis = chart.yAxes.push(am5xy.ValueAxis.new(root, {
  renderer: am5xy.AxisRendererY.new(root, {
    pan:"zoom"
  })  
}));


// Add series
// https://www.amcharts.com/docs/v5/charts/xy-chart/series/
var series = chart.series.push(am5xy.LineSeries.new(root, {
  name: "Series",
  xAxis: xAxis,
  yAxis: yAxis,
  valueYField: "value",
  valueXField: "date",
  tooltip: am5.Tooltip.new(root, {
    labelText: "{valueY}"
  })
}));


// Add scrollbar
// https://www.amcharts.com/docs/v5/charts/xy-chart/scrollbars/
chart.set("scrollbarX", am5.Scrollbar.new(root, {
  orientation: "horizontal"
}));


// Set data
//var data = generateDatas(1200);
series.data.setAll(data);


// Make stuff animate on load
// https://www.amcharts.com/docs/v5/concepts/animations/
series.appear(1000);
chart.appear(1000, 100);

}); // end am5.ready()

    

Why does the deployment expect NextRequest | Request instead of NextResponse while on local it got the same output and ran just fine

Type error: Route "src/app/api/auth/signup/route.ts" has an invalid "POST" export:
Type "NextResponse<unknown>" is not a valid type for the function's first argument.
Expected "NextRequest | Request", got "NextResponse<unknown>".

This is my authOptions file

import User from "@/app/lib/models/User";
import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import bcrypt from "bcryptjs";
export const authOptions = {
   providers: [
     CredentialsProvider({
       name: "Credentials",
       credentials: {
         email: { label: "Email", type: "email" },
         password: { label: "Password", type: "password" },
       },
       async authorize(credentials) {
         const { email, password } = credentials;
         try {
           const user = await User.findOne({ email });
           if (!user) {
             return null;
           }
            // Compare password before destructuring
           const passwordMatch = await bcrypt.compare(password, user.password);
           if (!passwordMatch) {
             return null;
           }
            // Exclude password from the user object after successful comparison
           const { password: _, ...userWithoutPassword } = user.toObject();
           return userWithoutPassword; // Return user data without password
         } catch (error) {
           console.log(error);
           return null;
         }
       },
     }),
   ],
  
   callbacks: {
     async jwt({ token, user }) {
       if (user) {
         token.user = user;
       }
       return token;
     },
    
     async session({ session, token }) {
       if (token.user) {
         // Pass the user data (without password) into the session
         session.user = token.user;
       }
       return session;
     },
   },
    pages: {
     signIn: "/register",
     error: "/auth/error",
   },
  
   session: {
     strategy: "jwt",
   },
    secret: process.env.NEXTAUTH_SECRET,
 };

This is my route.ts file

import { authOptions } from "@/utils/authOptions";
import NextAuth from "next-auth";

const handler = NextAuth(authOptions);

export { handler as GET, handler as POST };
  

I’m fairly new to using nextjs and deploying so I don’t quite understand why local enviornment wouldn’t have an issue with it while the production enviornment does. I’ve tried looking into environment variables thinking that may be the issue but it wasn’t. I’ve also tried looking online to see if there was any other similar issues but got no luck from that. I’ve looked through the documentation to see how it works and I feel like it follows the pattern, and it’s unclear what I’m doing wrong. I’m hosting on vercel or aws both don’t work.