问:
React-query is not updating the state
I recently started to use react query, but I don't quite understand yet how the state works under the hood.

I have a query function that logs in the user:

```<code>async function signin(
        model: AuthenticationControllerSignInRequest | null
    ): Promise<any> {
        if (model) {
            queryClient.invalidateQueries()
            const response = await CalyxApi.authApi().authenticationControllerSignIn(
                model
            );
            LocalStorage.set(LOCAL_STORAGE_KEY.AUTH, response.data.authToken);
            return response.data.authToken
        }
        return loadFromStorage()
    }
</code>```

Inside I use loadFromStorage function that gets authToken from local storage.

```<code>async function loadFromStorage(): Promise<AuthTokenModel | undefined> {
        const storedAuth = LocalStorage.get(LOCAL_STORAGE_KEY.AUTH);
        if (storedAuth) {
            if (new Date(storedAuth.validUntil) < new Date()) {
                LocalStorage.remove(LOCAL_STORAGE_KEY.AUTH)
                return undefined;
            }
            return storedAuth;

        } else {
            return undefined;
        }
    }
</code>```

In my Login components I use the query hook passing in signin function and formik that refetches on submit:

```<code>...
const { data: auth, refetch, isLoading: authLoading } = useQuery(['auth', signinModel], () => authActions.signin(signinModel), { enabled: false });

const formik = useFormik({
        validateOnChange: false,
        validateOnBlur: false,
        initialValues: {
            email: '',
            password: '',
        },
        validationSchema: loginFormSchema,
        onSubmit: async (values) => {
            await setSigninModel({
                email: values.email,
                password: values.password
            })
            await refetch()
        }
    });
...
</code>```

This works just fine. I am able to authenticate the user which should prompt another function that fetches the user from DB:

```<code>const { data: auth } = useQuery(['auth'], () => authActions.signin(null))
const userId = auth?.userId;

console.log('useUserActions: ', userId)

async function fetchUser(): Promise<UserModel | undefined> {
        if (!userId) {
            errorSuccessActions.throwError('USER ID IS UNDEFINED');
            return
        }

        const result = await CalyxApi.userApi().userControllerGetUser(userId)
        if (result.data) {
            const user = result.data.user
            return user
        }
        errorSuccessActions.throwError('USER NOT FOUND IN DB');
        return
    }
    function useFetchUser(reactQueryOptions?: {}) {

        return useQuery<UserModel | undefined>(
            ["user", userId],
            () => fetchUser(), {
            ...reactQueryOptions, refetchOnWindowFocus: false,
            onError: (err) => errorSuccessActions.throwError(err),
            onSuccess: (data) => {
                queryClient.setQueryData(['user'], data);
            },
            initialData: () => {
                const user: UserModel | undefined = queryClient.getQueryData('user')
                if (user) {
                    return user
                }
                return undefined
            }
        })
    }
</code>```

This expects userId that I get from ´auth´ state. Problem is that I actually don't get it after signin function fires. I only get the state updated if I reload the page or i refocus on the tab.
I have a console.log that should log the userId but it always returns undefined. Only when I refocus on the window will it return the userId prompting to fetch the user.

I am not sure what am I missing to get the updated auth state and to get the userId right after I sign in.

Title: React-query is not updating the state

Body:
I recently started to use react query, but I don't quite understand yet how the state works under the hood.

I have a query function that logs in the user:

async function signin(
        model: AuthenticationControllerSignInRequest | null
    ): Promise<any> {
        if (model) {
            queryClient.invalidateQueries()
            const response = await CalyxApi.authApi().authenticationControllerSignIn(
                model
            );
            LocalStorage.set(LOCAL_STORAGE_KEY.AUTH, response.data.authToken);
            return response.data.authToken
        }
        return loadFromStorage()
    }

Inside I use loadFromStorage function that gets authToken from local storage.

async function loadFromStorage(): Promise<AuthTokenModel | undefined> {
        const storedAuth = LocalStorage.get(LOCAL_STORAGE_KEY.AUTH);
        if (storedAuth) {
            if (new Date(storedAuth.validUntil) < new Date()) {
                LocalStorage.remove(LOCAL_STORAGE_KEY.AUTH)
                return undefined;
            }
            return storedAuth;

        } else {
            return undefined;
        }
    }

In my Login components I use the query hook passing in signin function and formik that refetches on submit:

...
const { data: auth, refetch, isLoading: authLoading } = useQuery(['auth', signinModel], () => authActions.signin(signinModel), { enabled: false });

const formik = useFormik({
        validateOnChange: false,
        validateOnBlur: false,
        initialValues: {
            email: '',
            password: '',
        },
        validationSchema: loginFormSchema,
        onSubmit: async (values) => {
            await setSigninModel({
                email: values.email,
                password: values.password
            })
            await refetch()
        }
    });
...

This works just fine. I am able to authenticate the user which should prompt another function that fetches the user from DB:

const { data: auth } = useQuery(['auth'], () => authActions.signin(null))
const userId = auth?.userId;

console.log('useUserActions: ', userId)

async function fetchUser(): Promise<UserModel | undefined> {
        if (!userId) {
            errorSuccessActions.throwError('USER ID IS UNDEFINED');
            return
        }

        const result = await CalyxApi.userApi().userControllerGetUser(userId)
        if (result.data) {
            const user = result.data.user
            return user
        }
        errorSuccessActions.throwError('USER NOT FOUND IN DB');
        return
    }
    function useFetchUser(reactQueryOptions?: {}) {

        return useQuery<UserModel | undefined>(
            ["user", userId],
            () => fetchUser(), {
            ...reactQueryOptions, refetchOnWindowFocus: false,
            onError: (err) => errorSuccessActions.throwError(err),
            onSuccess: (data) => {
                queryClient.setQueryData(['user'], data);
            },
            initialData: () => {
                const user: UserModel | undefined = queryClient.getQueryData('user')
                if (user) {
                    return user
                }
                return undefined
            }
        })
    }

This expects userId that I get from ´auth´ state. Problem is that I actually don't get it after signin function fires. I only get the state updated if I reload the page or i refocus on the tab.
I have a console.log that should log the userId but it always returns undefined. Only when I refocus on the window will it return the userId prompting to fetch the user.

I am not sure what am I missing to get the updated auth state and to get the userId right after I sign in.


来源: stackexchange

问:
Unable to start receiver com.google.android.finsky.instantapps.PhenotypeUpdateReceiver: java.lang.IllegalStateException
I have released my game to play console which is made using Unity. The Pre-launch report, reported the following crash issues during internal testing.

```<code>java.lang.RuntimeException: Unable to start receiver com.google.android.finsky.instantapps.PhenotypeUpdateReceiver: java.lang.IllegalStateException: Not allowed to start service Intent { act=com.google.android.gms.phenotype.UPDATE cmp=com.android.vending/com.google.android.finsky.instantapps.PhenotypeUpdateService }: app is in background uid UidRecord{46dceb4 u0a249 TRNB bg:+10m41s432ms idle change:uncached procs:4 proclist:29801,29978,30388,30591, seq(0,0,0)}
</code>```

AND

```<code>Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if some functionality depends on the PendingIntent being mutable, e.g. if it needs to be used with inline replies or bubbles.
</code>```

I am not sure, where exactly the error is and why?

Full trace for the first issue:

```<code>FATAL EXCEPTION: main
Process: com.android.vending:instant_app_installer, PID: 19323
java.lang.RuntimeException: Unable to start receiver com.google.android.finsky.instantapps.PhenotypeUpdateReceiver: android.app.BackgroundServiceStartNotAllowedException: Not allowed to start service Intent { act=com.google.android.gms.phenotype.UPDATE cmp=com.android.vending/com.google.android.finsky.instantapps.PhenotypeUpdateService }: app is in background uid UidRecord{64ad173 u0a135 TRNB bg:+13m22s373ms idle change:uncached procs:0 seq(0,0,0)}
    at android.app.ActivityThread.handleReceiver(ActivityThread.java:4317)
    at android.app.ActivityThread.access$1600(ActivityThread.java:247)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2064)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loopOnce(Looper.java:201)
    at android.os.Looper.loop(Looper.java:288)
    at android.app.ActivityThread.main(ActivityThread.java:7839)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
Caused by: android.app.BackgroundServiceStartNotAllowedException: Not allowed to start service Intent { act=com.google.android.gms.phenotype.UPDATE cmp=com.android.vending/com.google.android.finsky.instantapps.PhenotypeUpdateService }: app is in background uid UidRecord{64ad173 u0a135 TRNB bg:+13m22s373ms idle change:uncached procs:0 seq(0,0,0)}
    at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1861)
    at android.app.ContextImpl.startService(ContextImpl.java:1817)
    at android.content.ContextWrapper.startService(ContextWrapper.java:774)
    at alj.a(PG:2)
    at alm.a(PG:3)
    at wnv.a(PG:2)
    at com.google.android.finsky.instantapps.PhenotypeUpdateReceiver.onReceive(PG:6)
    at android.app.ActivityThread.handleReceiver(ActivityThread.java:4308)
    ... 9 more
</code>```

Full trace for the second issue:

```<code>FATAL EXCEPTION: pool-3-thread-1
Process: com.HefazSofts.AayaanTheRunner, PID: 19257
java.lang.IllegalArgumentException: com.HefazSofts.AayaanTheRunner: Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.
Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if some functionality depends on the PendingIntent being mutable, e.g. if it needs to be used with inline replies or bubbles.
    at android.app.PendingIntent.checkFlags(PendingIntent.java:375)
    at android.app.PendingIntent.getBroadcastAsUser(PendingIntent.java:645)
    at android.app.PendingIntent.getBroadcast(PendingIntent.java:632)
    at androidx.work.impl.utils.ForceStopRunnable.getPendingIntent(ForceStopRunnable.java:174)
    at androidx.work.impl.utils.ForceStopRunnable.isForceStopped(ForceStopRunnable.java:108)
    at androidx.work.impl.utils.ForceStopRunnable.run(ForceStopRunnable.java:86)
    at androidx.work.impl.utils.SerialExecutor$Task.run(SerialExecutor.java:75)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
    at java.lang.Thread.run(Thread.java:920)
</code>```

ContentLicense: CC BY-SA 4.0

Body:
I have released my game to play console which is made using Unity. The Pre-launch report, reported the following crash issues during internal testing.

java.lang.RuntimeException: Unable to start receiver com.google.android.finsky.instantapps.PhenotypeUpdateReceiver: java.lang.IllegalStateException: Not allowed to start service Intent { act=com.google.android.gms.phenotype.UPDATE cmp=com.android.vending/com.google.android.finsky.instantapps.PhenotypeUpdateService }: app is in background uid UidRecord{46dceb4 u0a249 TRNB bg:+10m41s432ms idle change:uncached procs:4 proclist:29801,29978,30388,30591, seq(0,0,0)}

AND

Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if some functionality depends on the PendingIntent being mutable, e.g. if it needs to be used with inline replies or bubbles.

I am not sure, where exactly the error is and why?

Full trace for the first issue:

FATAL EXCEPTION: main
Process: com.android.vending:instant_app_installer, PID: 19323
java.lang.RuntimeException: Unable to start receiver com.google.android.finsky.instantapps.PhenotypeUpdateReceiver: android.app.BackgroundServiceStartNotAllowedException: Not allowed to start service Intent { act=com.google.android.gms.phenotype.UPDATE cmp=com.android.vending/com.google.android.finsky.instantapps.PhenotypeUpdateService }: app is in background uid UidRecord{64ad173 u0a135 TRNB bg:+13m22s373ms idle change:uncached procs:0 seq(0,0,0)}
    at android.app.ActivityThread.handleReceiver(ActivityThread.java:4317)
    at android.app.ActivityThread.access$1600(ActivityThread.java:247)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2064)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loopOnce(Looper.java:201)
    at android.os.Looper.loop(Looper.java:288)
    at android.app.ActivityThread.main(ActivityThread.java:7839)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
Caused by: android.app.BackgroundServiceStartNotAllowedException: Not allowed to start service Intent { act=com.google.android.gms.phenotype.UPDATE cmp=com.android.vending/com.google.android.finsky.instantapps.PhenotypeUpdateService }: app is in background uid UidRecord{64ad173 u0a135 TRNB bg:+13m22s373ms idle change:uncached procs:0 seq(0,0,0)}
    at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1861)
    at android.app.ContextImpl.startService(ContextImpl.java:1817)
    at android.content.ContextWrapper.startService(ContextWrapper.java:774)
    at alj.a(PG:2)
    at alm.a(PG:3)
    at wnv.a(PG:2)
    at com.google.android.finsky.instantapps.PhenotypeUpdateReceiver.onReceive(PG:6)
    at android.app.ActivityThread.handleReceiver(ActivityThread.java:4308)
    ... 9 more

Full trace for the second issue:

FATAL EXCEPTION: pool-3-thread-1
Process: com.HefazSofts.AayaanTheRunner, PID: 19257
java.lang.IllegalArgumentException: com.HefazSofts.AayaanTheRunner: Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.
Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if some functionality depends on the PendingIntent being mutable, e.g. if it needs to be used with inline replies or bubbles.
    at android.app.PendingIntent.checkFlags(PendingIntent.java:375)
    at android.app.PendingIntent.getBroadcastAsUser(PendingIntent.java:645)
    at android.app.PendingIntent.getBroadcast(PendingIntent.java:632)
    at androidx.work.impl.utils.ForceStopRunnable.getPendingIntent(ForceStopRunnable.java:174)
    at androidx.work.impl.utils.ForceStopRunnable.isForceStopped(ForceStopRunnable.java:108)
    at androidx.work.impl.utils.ForceStopRunnable.run(ForceStopRunnable.java:86)
    at androidx.work.impl.utils.SerialExecutor$Task.run(SerialExecutor.java:75)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
    at java.lang.Thread.run(Thread.java:920)


问:
RXStomp WebSocket Client not receiving data sometimes
Here is my configuration for RXStomp on frontend;

```<code>import { RxStompConfig } from '@stomp/rx-stomp';
import { environment } from '../../../environments/environment';

export const myRxStompConfig: RxStompConfig = {

  reconnectDelay: 20000,

  debug: (msg: string): void => {
    if (!environment.production) {
      console.log(msg);
    }
  },
};

</code>```

Here is the code for the rxStompService;

```<code>import { Injectable } from "@angular/core";
import { RxStomp } from "@stomp/rx-stomp";
import SockJS from "sockjs-client";
import { environment } from "../../../environments/environment";
import { myRxStompConfig } from "../configurations/rx-stomp.config";

@Injectable({
  providedIn: "root",
})
export class RxStompService extends RxStomp {
  public currentRetry  = 0;

  public resetRetry() {
    this.currentRetry = 0;
  }
}

export function rxStompServiceFactory() {
  const rxStomp = new RxStompService();
  myRxStompConfig.webSocketFactory = function () {
    return new SockJS(`${environment.baseUrl}/public/chatsocket`);

  };
  rxStomp.resetRetry();
  myRxStompConfig.beforeConnect = (): Promise<void> => {
    return new Promise<void>((resolve, reject) => {
      if (rxStomp.currentRetry <= 5) {
        rxStomp.currentRetry++;
        resolve();
      }
    });
  };
  rxStomp.configure(myRxStompConfig);
  rxStomp.activate();
  return rxStomp;
}

</code>```

The websocket was working fine until a couple of days ago when the socket broke on the production server and then we changed the URL of the websocket on the backend from public/websocket to public/chatsocket. The socket gets connected and then I subscribe to the required channel using

```<code>this.rxStompService.watch(`/user/${id}/message`).subscribe((message) => {
   console.log(message.body);
};
</code>```

The messages send correctly on the backend (Springboot) using this code;

```<code>private void sendWebMessageToConversation(MessageResponseDto messageResponseDto, String destinationId) {
        try{
            simpMessagingTemplate.convertAndSendToUser(destinationId, "/message", messageResponseDto);
        }
        catch (Exception e){
            logger.error(e.getMessage(), e);
        }
    }
</code>```

After debugging we found that the message gets filtered correctly and sent to all the users in a particular conversation via simpMessagingTemplate.convertAndSendToUser but the message does not get received on the frontend socket client RXStomp, even though the socket connection is established and the client is subscribed/watching the correct channel.

This feature works correctly on all of the test environments but for some reason there is an inconsistency when working on the production server. Sometimes one user subscribed to the channel will receive messages but the other won't. Or both users won't receive messages, or the feature works correctly and both receive messages properly. How do I fix this to make it work correctly all the time?

Body:
Here is my configuration for RXStomp on frontend;

import { RxStompConfig } from '@stomp/rx-stomp';
import { environment } from '../../../environments/environment';

export const myRxStompConfig: RxStompConfig = {

  reconnectDelay: 20000,

  debug: (msg: string): void => {
    if (!environment.production) {
      console.log(msg);
    }
  },
};

Here is the code for the rxStompService;

import { Injectable } from "@angular/core";
import { RxStomp } from "@stomp/rx-stomp";
import SockJS from "sockjs-client";
import { environment } from "../../../environments/environment";
import { myRxStompConfig } from "../configurations/rx-stomp.config";

@Injectable({
  providedIn: "root",
})
export class RxStompService extends RxStomp {
  public currentRetry  = 0;

  public resetRetry() {
    this.currentRetry = 0;
  }
}

export function rxStompServiceFactory() {
  const rxStomp = new RxStompService();
  myRxStompConfig.webSocketFactory = function () {
    return new SockJS(`${environment.baseUrl}/public/chatsocket`);

  };
  rxStomp.resetRetry();
  myRxStompConfig.beforeConnect = (): Promise<void> => {
    return new Promise<void>((resolve, reject) => {
      if (rxStomp.currentRetry <= 5) {
        rxStomp.currentRetry++;
        resolve();
      }
    });
  };
  rxStomp.configure(myRxStompConfig);
  rxStomp.activate();
  return rxStomp;
}

The websocket was working fine until a couple of days ago when the socket broke on the production server and then we changed the URL of the websocket on the backend from public/websocket to public/chatsocket. The socket gets connected and then I subscribe to the required channel using

this.rxStompService.watch(`/user/${id}/message`).subscribe((message) => {
   console.log(message.body);
};

The messages send correctly on the backend (Springboot) using this code;

private void sendWebMessageToConversation(MessageResponseDto messageResponseDto, String destinationId) {
        try{
            simpMessagingTemplate.convertAndSendToUser(destinationId, "/message", messageResponseDto);
        }
        catch (Exception e){
            logger.error(e.getMessage(), e);
        }
    }

After debugging we found that the message gets filtered correctly and sent to all the users in a particular conversation via simpMessagingTemplate.convertAndSendToUser but the message does not get received on the frontend socket client RXStomp, even though the socket connection is established and the client is subscribed/watching the correct channel.

This feature works correctly on all of the test environments but for some reason there is an inconsistency when working on the production server. Sometimes one user subscribed to the channel will receive messages but the other won't. Or both users won't receive messages, or the feature works correctly and both receive messages properly. How do I fix this to make it work correctly all the time?


问:
Troubleshooting issue with updating and displaying random quotes on interactive website using JavaScript and Node.js
I am building an interactive website using JavaScript and a Node.js app that generates random messages when the website page is refreshed. This website displays random quotes, predictions, and fun facts for each zodiac sign. However, I am having trouble updating and displaying the random quotes, predictions, and fun facts on the HTML page. I have imported the displayQuote, displayPrediction, and displayFunFact functions from the display.js module and am using a updateResults function to modify the text of the li elements for each zodiac sign. The updateResults function iterates over a list of zodiac signs and uses the imported functions to update the text of the li elements for each sign.

https://github.com/vetheve/Group-Project-Mixed-Messages.git

```<code>.
├── data
│   ├── funfacts.json
│   ├── predictions.json
│   └── quotes.json
├── index.html
├── index.js
├── modules
│   └── display.js
├── node_modules
│   └── ...
├── package.json
├── package-lock.json
├── README.md
├── style.css
├── test
    └── test.js
</code>```

The data directory contains three JSON files: funfacts.json,
predictions.json, and quotes.json.

The index.html file is the main HTML file for the project.

The index.js file contains JavaScript code for the project.

The modules directory contains a single file called display.js, which contains additional JavaScript code for the project.

The package.json and package-lock.json files are related to dependencies and package management in Node.js.

HTML code index.html

```<code>
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width">
        <title>Astrological Insights for a Better Life</title>
        <link href="style.css" rel="stylesheet" type="text/css" />
      </head>
      <body>
        <script src="index.js"  type="module"></script>
        <header>
          <h1>Astrological Insights for a Better Life</h1>
        </header>
        <aside>"Welcome to the world's most accurate astrology website! ..."</aside>
        <hr>
        <h2 class="zodiac-sign">Bélier</h2>
        <ul  id="belier">
          <li>...</li>
          <li>...</li>
          <li>...</li>
        </ul>
        <hr>
        <h2 class="zodiac-sign">Poissons</h2>
        <ul id="poissons">
          <li>...</li>
          <li>...</li>
          <li>...</li>
        </ul>
      </body>
    </html>

</code>```

JS code index.js

```<code>
    /**
     * Update the text of the li elements for each zodiac sign.
     **/

    // Import the displayQuote, displayPrediction, and displayFunFact functions from the display.js module
    import {
        displayQuote,
        displayPrediction,
        displayFunFact
    } from './modules/display.js';

    //function that updates the text of the li elements for each zodiac sign.
    function updateResults() {
        // List of zodiac signs
        const zodiacSigns = ['belier', 'taureau', 'gemeaux', 'cancer', 'lion', 'vierge', 'balance', 'scorpion', 'sagittaire', 'capricorne', 'verseau', 'poissons'];

        // Iterate over each zodiac sign
        for (let sign of zodiacSigns) {
            // Get the ul element for the current zodiac sign
            const ulElement = document.getElementById(sign);

            // Get the first li element
            const firstLi = ulElement.children[0];

            // Modify the text of the first li element using the displayPrediction function
            firstLi.innerText = displayPrediction();

            // Get the second li element
            const secondLi = ulElement.children[1];

            // Modify the text of the second li element using the displayQuote function
            secondLi.innerText = displayQuote();

            // Get the third li element
            const thirdLi = ulElement.children[2];

            // Modify the text of the third li element using the displayFunFact function
            thirdLi.innerText = displayFunFact();
        }
    }

</code>```

JS code display.js

```<code>
    // Import the 'fs' module for reading and writing files
    import fs from 'fs';

    // displayQuote is a function that returns a randomly selected quote from the quotes.json file along with the corresponding author.
    export const displayQuote = () => {
        // Read the quotes.json file and parse the JSON data
        const quotes = JSON.parse(fs.readFileSync('./data/quotes.json', 'utf8'));

        // Select a random index from the quotes array
        // The upper bound for the random number is the length of the quotes array minus 1 to prevent the possibility of an out-of-bounds index.
        const randomIndexQuote = Math.round(Math.random() * (quotes.length - 1));

        // Destructure the quote and author from the selected quote object
        const {
            quote,
            author
        } = quotes[randomIndexQuote];

        // Return the quote and author as a string
        return `"${quote}", ${author}`;
    };

    // displayPrediction is a function that returns a randomly selected prediction from the predictions.json file
    export const displayPrediction = () => {

        // Read the predictions.json file and parse the JSON data
        const predictions = JSON.parse(fs.readFileSync('./data/predictions.json', 'utf8'));

        // Select a random index from the quotes array
        // The upper bound for the random number is the length of the quotes array minus 1 to prevent the possibility of an out-of-bounds index.
        const prediction = predictions.quotes[Math.round(Math.random() * (predictions.quotes.length - 1))];

        // Return the prediction as a string
        return `${prediction}`;
    };

    // displayFunFact is a function that returns a randomly selected fun fact from the funfacts.json file
    export const displayFunFact = () => {
        // Read the funfacts.json file and parse the JSON data
        const funfacts = JSON.parse(fs.readFileSync('./data/funfacts.json', 'utf8'));

        // Select a random index from the facts array
        // The upper bound for the random number is the length of the facts array minus 1 to prevent the possibility of an out-of-bounds index.
        const funfact = funfacts.facts[Math.round(Math.random() * (funfacts.facts.length - 1))];

        // Return the fun fact as a string
        return `${funfact}`;
    };

</code>```

Body:
I am building an interactive website using JavaScript and a Node.js app that generates random messages when the website page is refreshed. This website displays random quotes, predictions, and fun facts for each zodiac sign. However, I am having trouble updating and displaying the random quotes, predictions, and fun facts on the HTML page. I have imported the displayQuote, displayPrediction, and displayFunFact functions from the display.js module and am using a updateResults function to modify the text of the li elements for each zodiac sign. The updateResults function iterates over a list of zodiac signs and uses the imported functions to update the text of the li elements for each sign.

https://github.com/vetheve/Group-Project-Mixed-Messages.git

.
├── data
│   ├── funfacts.json
│   ├── predictions.json
│   └── quotes.json
├── index.html
├── index.js
├── modules
│   └── display.js
├── node_modules
│   └── ...
├── package.json
├── package-lock.json
├── README.md
├── style.css
├── test
    └── test.js

The data directory contains three JSON files: funfacts.json,
predictions.json, and quotes.json.

The index.html file is the main HTML file for the project.

The index.js file contains JavaScript code for the project.

The modules directory contains a single file called display.js, which contains additional JavaScript code for the project.

The package.json and package-lock.json files are related to dependencies and package management in Node.js.

HTML code index.html

    <!DOCTYPE html>

        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width">
        <title>Astrological Insights for a Better Life</title>
        <link href="style.css" rel="stylesheet" type="text/css" />

Astrological Insights for a Better Life

        "Welcome to the world's most accurate astrology website! ..."

Bélier

...

...

...

Poissons

...

...

...

JS code index.js

    /**
     * Update the text of the li elements for each zodiac sign.
     **/

    // Import the displayQuote, displayPrediction, and displayFunFact functions from the display.js module
    import {
        displayQuote,
        displayPrediction,
        displayFunFact
    } from './modules/display.js';

    //function that updates the text of the li elements for each zodiac sign.
    function updateResults() {
        // List of zodiac signs
        const zodiacSigns = ['belier', 'taureau', 'gemeaux', 'cancer', 'lion', 'vierge', 'balance', 'scorpion', 'sagittaire', 'capricorne', 'verseau', 'poissons'];

        // Iterate over each zodiac sign
        for (let sign of zodiacSigns) {
            // Get the ul element for the current zodiac sign
            const ulElement = document.getElementById(sign);

            // Get the first li element
            const firstLi = ulElement.children[0];

            // Modify the text of the first li element using the displayPrediction function
            firstLi.innerText = displayPrediction();

            // Get the second li element
            const secondLi = ulElement.children[1];

            // Modify the text of the second li element using the displayQuote function
            secondLi.innerText = displayQuote();

            // Get the third li element
            const thirdLi = ulElement.children[2];

            // Modify the text of the third li element using the displayFunFact function
            thirdLi.innerText = displayFunFact();
        }
    }

JS code display.js

    // Import the 'fs' module for reading and writing files
    import fs from 'fs';

    // displayQuote is a function that returns a randomly selected quote from the quotes.json file along with the corresponding author.
    export const displayQuote = () => {
        // Read the quotes.json file and parse the JSON data
        const quotes = JSON.parse(fs.readFileSync('./data/quotes.json', 'utf8'));

        // Select a random index from the quotes array
        // The upper bound for the random number is the length of the quotes array minus 1 to prevent the possibility of an out-of-bounds index.
        const randomIndexQuote = Math.round(Math.random() * (quotes.length - 1));

        // Destructure the quote and author from the selected quote object
        const {
            quote,
            author
        } = quotes[randomIndexQuote];

        // Return the quote and author as a string
        return `"${quote}", ${author}`;
    };

    // displayPrediction is a function that returns a randomly selected prediction from the predictions.json file
    export const displayPrediction = () => {

        // Read the predictions.json file and parse the JSON data
        const predictions = JSON.parse(fs.readFileSync('./data/predictions.json', 'utf8'));

        // Select a random index from the quotes array
        // The upper bound for the random number is the length of the quotes array minus 1 to prevent the possibility of an out-of-bounds index.
        const prediction = predictions.quotes[Math.round(Math.random() * (predictions.quotes.length - 1))];

        // Return the prediction as a string
        return `${prediction}`;
    };

    // displayFunFact is a function that returns a randomly selected fun fact from the funfacts.json file
    export const displayFunFact = () => {
        // Read the funfacts.json file and parse the JSON data
        const funfacts = JSON.parse(fs.readFileSync('./data/funfacts.json', 'utf8'));

        // Select a random index from the facts array
        // The upper bound for the random number is the length of the facts array minus 1 to prevent the possibility of an out-of-bounds index.
        const funfact = funfacts.facts[Math.round(Math.random() * (funfacts.facts.length - 1))];

        // Return the fun fact as a string
        return `${funfact}`;
    };


问:
Adaptive Stepsize Runge Kutta Method
```<code>
</code>```
```<code>def runge_kutta(f, x0, dt, T):
    n = int(T / dt)

    t = np.zeros(n + 1)
    if isinstance(x0, (int, float)):
        x = np.zeros(n + 1)
    else:
        neqns = len(x0)
        x = np.zeros((n + 1, neqns))
    x[0] = x0
    t[0] = 0

    for i in range(n):
        t[i + 1] = t[i] + dt

        k1 = np.dot(dt, f.f(x[i], t[i]))
        k2 = np.dot(dt, f.f(x[i] + 0.5 * k1, t[i] + dt / 2))
        k3 = np.dot(dt, f.f(x[i] + 0.5 * k2, t[i] + dt / 2))
        k4 = np.dot(dt, f.f(x[i] + k3, t[i] + dt))

        x[i + 1] = x[i] + np.dot((1/6), (k1 + 2 * k2 + 2 * k3 + k4))

    return x, t
</code>```
```<code>
</code>```

This is my code for a fourth order Runge Kutta method. How can I implement an adaptive stepsize tool that takes in an error e and an initial stepsize dt, and estimates the error in the first term. If the error is less than e, the code uses dt to approximate the solution. And if the error is greater than e, set dt = dt/2 and do the process again.

This is the goal for what the code should do but I have no clue on how to implement it. Could someone tell me how I can do it?

Title: Adaptive Stepsize Runge Kutta Method

Body:
def runge_kutta(f, x0, dt, T):
    n = int(T / dt)

    t = np.zeros(n + 1)
    if isinstance(x0, (int, float)):
        x = np.zeros(n + 1)
    else:
        neqns = len(x0)
        x = np.zeros((n + 1, neqns))
    x[0] = x0
    t[0] = 0

    for i in range(n):
        t[i + 1] = t[i] + dt

        k1 = np.dot(dt, f.f(x[i], t[i]))
        k2 = np.dot(dt, f.f(x[i] + 0.5 * k1, t[i] + dt / 2))
        k3 = np.dot(dt, f.f(x[i] + 0.5 * k2, t[i] + dt / 2))
        k4 = np.dot(dt, f.f(x[i] + k3, t[i] + dt))

        x[i + 1] = x[i] + np.dot((1/6), (k1 + 2 * k2 + 2 * k3 + k4))

    return x, t

This is my code for a fourth order Runge Kutta method. How can I implement an adaptive stepsize tool that takes in an error e and an initial stepsize dt, and estimates the error in the first term. If the error is less than e, the code uses dt to approximate the solution. And if the error is greater than e, set dt = dt/2 and do the process again.

This is the goal for what the code should do but I have no clue on how to implement it. Could someone tell me how I can do it?


问:
<ReactTooltip> component in IE
I am currently facing and issue that is driving me crazy. Currently Using React (v17.0.1).

It is working in Chrome, Firefox, Edge, but for IE10 and IE11 doesn't work.

Here the error screens-shot

Here is the reference link that I have gone through far: -
Internet Explorer throws SCRIPT5022: HierarchyRequestError when trying to appendChild an HTML object from another window,
React: Unknown component error. IE,
https://github.com/Financial-Times/polyfill-service/issues/1428,https://github.com/storybookjs/storybook/issues/15384

Title: <ReactTooltip> component in IE


问:
Column wise clustering instead of row wise clustering
How to do columns wise clustering based on the variables characteristics.if I go with kmeans or hierarchical algorithm etc it's taking row wise. I don't want row wise clustering.

I tried with clustering algorithms but it performing only on row wise.
So I need to perform on column wise


问:
Kibana not saving query with space properly
I am trying to save a query of the form

```<code>"Released Hold without any captures"
</code>```

After saving whenever I am trying load the saved query the double quotes are getting dropped and the query is becoming like below

```<code>Released Hold without any captures
</code>```

Can someone let me know how can I save query with double quotes properly?

Body:
I am trying to save a query of the form

"Released Hold without any captures"

After saving whenever I am trying load the saved query the double quotes are getting dropped and the query is becoming like below

Released Hold without any captures

Can someone let me know how can I save query with double quotes properly?


问:
How does Android binder transfer hidl_pointer and std::function between processes
There is an binderized interface called IAllocator which can be used by a client process to request new files from server process. And it has the following method (it is simplified, just for illustration purpose):

```<code>allocate(std::function< void (hidl_pointer<buffer_handle>& buffer) > hidl_cb)
</code>```

hidl_ponter is Android defined data structure template, and buffer_handle is a user defined data structure.

the question is: I don't know how Android binder transfer the hidl_ponter and std::function between different processes, especially the hidl_pointer which is only a wrapper of raw pointer as shown below:

```<code>template<typename T>
struct hidl_pointer
{
public: ...
private:
    union {
    T* mPointer;
    uint64_t _pad;
    }
}
</code>```

Doesn't a process own its own virtual address space? How can binder transfer a pointer between different processes?

to be more specific, here is an example when the interface is used:

Client process code:

```<code>// get a proxy object of IAllocator
IAllocator* allocator = IAllocator::getService();

// invoke the method
mAllocator->allocate([&](const auto& buffer){
// code which will use the buffer
...
});
</code>```

Server process code:

```<code>// implementation of "allocate" method
IAllocator::allocate(std::function< void (hidl_pointer<buffer_handle>& buffers) > hidl_cb)
{
// first allocate file buffer
AllocateBuffer(...);

// then make a "buffer_handle" to manage the buffer
buffer_handle* handle = malloc(...);

// then use a "hidl_pointer" to wrap that raw pointer
hidl_pointer<buffer_handle> hidl_ptr{handle};

// then invoke the lambda passed by client process
hidl_cb(hidl_ptr);
}
</code>```

By the way, is there any book or blog which deep dives into the binder mechanism?

Body:
There is an binderized interface called IAllocator which can be used by a client process to request new files from server process. And it has the following method (it is simplified, just for illustration purpose):

allocate(std::function< void (hidl_pointer<buffer_handle>& buffer) > hidl_cb)

hidl_ponter is Android defined data structure template, and buffer_handle is a user defined data structure.

the question is: I don't know how Android binder transfer the hidl_ponter and std::function between different processes, especially the hidl_pointer which is only a wrapper of raw pointer as shown below:

template<typename T>
struct hidl_pointer
{
public: ...
private:
    union {
    T* mPointer;
    uint64_t _pad;
    }
}

Doesn't a process own its own virtual address space? How can binder transfer a pointer between different processes?

to be more specific, here is an example when the interface is used:

Client process code:

// get a proxy object of IAllocator
IAllocator* allocator = IAllocator::getService();

// invoke the method
mAllocator->allocate([&](const auto& buffer){
// code which will use the buffer
...
});

Server process code:

// implementation of "allocate" method
IAllocator::allocate(std::function< void (hidl_pointer<buffer_handle>& buffers) > hidl_cb)
{
// first allocate file buffer
AllocateBuffer(...);

// then make a "buffer_handle" to manage the buffer
buffer_handle* handle = malloc(...);

// then use a "hidl_pointer" to wrap that raw pointer
hidl_pointer<buffer_handle> hidl_ptr{handle};

// then invoke the lambda passed by client process
hidl_cb(hidl_ptr);
}

By the way, is there any book or blog which deep dives into the binder mechanism?


问:
pnpm / yarn configure different version of dependency based on OS platforms
I am using sharp for image processing in an Electron app, the app needs to run on Windows 7 32-bits and above, macOS 10.11 and above.

In order to let it run on Windows 7 32-bits, I need to install sharp@0.27.2 which is an old version of the library. While on macOS I would like to install the new version sharp@0.31.1.

The problem is, package.json in npm doesn't seem allow me to define platform specific dependencies, I know I can work it around by using npm scripts, I can do npm run install to run a install.js file and within it, install different version of sharp based on OS platform.

However, nobody knows npm run install, everybody uses npm install.

I am wondering if pnpm or yarn can do a better job on this, if so, I might want to move away from npm.


问:
How to disable third parties spell checker like Grammarly in MUI TextField?
I'm struggling to disable third parties spell checker like Grammarly in MUI TextField which is implemented in a next.js app. I've tried data-gramm:false but it's not working. Below is my TextField component and code what I've tried...

```<code><TextField
    id={`${question.id}`}
    label="Type your answer here"
    multiline
    name={`answer_${question.id}`}
    rows={12}
    spellCheck={false}
    autoCapitalize="off"
    autoComplete="off"
    autoCorrect="off"
    InputProps={{
        'data-gramm': 'false',
        'data-gramm_editor': 'false',
    }}
    variant="outlined"
    defaultValue={value}
    fullWidth
    focused
    helperText={`Words Count: ${wordsCount}`}
    onChange={(e) => {
        handleInputChange(question.id, e.target.value);
        setWordsCount(e.target.value.trim().split(/\s+/).length);
    }}
/>
</code>```

Browsers inbuilt spell checker is not working using this code but when Grammarly is installed in browser then it's not working.

Body:
I'm struggling to disable third parties spell checker like Grammarly in MUI TextField which is implemented in a next.js app. I've tried data-gramm:false but it's not working. Below is my TextField component and code what I've tried...

<TextField
    id={`${question.id}`}
    label="Type your answer here"
    multiline
    name={`answer_${question.id}`}
    rows={12}
    spellCheck={false}
    autoCapitalize="off"
    autoComplete="off"
    autoCorrect="off"
    InputProps={{
        'data-gramm': 'false',
        'data-gramm_editor': 'false',
    }}
    variant="outlined"
    defaultValue={value}
    fullWidth
    focused
    helperText={`Words Count: ${wordsCount}`}
    onChange={(e) => {
        handleInputChange(question.id, e.target.value);
        setWordsCount(e.target.value.trim().split(/\s+/).length);
    }}
/>

Browsers inbuilt spell checker is not working using this code but when Grammarly is installed in browser then it's not working.


问:
Flutter - Going to previous page and same page the value retains
```<code>class HomeScreen extends StatefulWidget {
  final userName;
  HomeScreen(this.userName);

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

Future<ClientDashboardModel?>? _meterReadingResponse;
BatchSummaryModel? _batchResponse;
AMRDashboardModel? _amrDashboardResponse;
String _userName = '';
int? qcAssignedReads = 0;
int? qcMrCompleted = 0;
int? qcCompletedReads = 0;
int? qcPendingReads = 0;
int? qcApprovedReads = 0;
int? qcRejectedReads = 0;
bool isFirstTimeCalled = false;
Timer? _timer;

int _currentIndex = 0;

final pages = [
  const MDMScreen(),
  const AMRDashboard(whichScreen: 0),
  const AMRDashboard(whichScreen: 1),
  const AMRDashboard(whichScreen: 2)
];

class _HomeScreenState extends State<HomeScreen> {
  @override
  void initState() {
    setUpTimedFetch();
    super.initState();
    if (widget.userName != null) _userName = (widget.userName!);
  }

  @override
  void dispose() {
    isFirstTimeCalled = false;
    _timer?.cancel();
    super.dispose();
  }

  void setUpTimedFetch() {
    if (!isFirstTimeCalled) {
      _meterReadingResponse = _getDashboardData();
    }
    isFirstTimeCalled = true;
  }

  Future<ClientDashboardModel?> _getDashboardData() async {
    ClientDashboardModel? meterReadingResponse;

    SharedPreferences prefs = await SharedPreferences.getInstance();
    String token = prefs.getString('token')!;

    var responseData = await Dashboard().getClientDashboard(token);
    if (responseData.statusCode == 200) {
      String data = responseData.body;

      var decodedData = jsonDecode(data);
      meterReadingResponse = null;
      meterReadingResponse = ClientDashboardModel.fromJson(decodedData);

      return meterReadingResponse;
    }
    return null;
  }

  void logout() async {
    SharedPreferences.getInstance().then((value) {
      value.remove('token');
      value.remove('userName');
    });
    Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) {
      return const LoginScreen();
    }));
  }

  Future<void> _showMyDialog() async {
    return showDialog<void>(
        context: context,
        barrierDismissible: false,
        builder: (BuildContext context) {
          return AlertDialog(
            title: const Text(Strings.kLogoutLabel),
            content: const Text(Strings.kConfirmLogout),
            actions: <Widget>[
              TextButton(
                child: const Text(Strings.kCancelLabel),
                onPressed: () {
                  Navigator.of(context).pop();
                },
              ),
              TextButton(
                child: const Text(Strings.kOKLabel),
                onPressed: () {
                  Navigator.of(context).pop();
                  logout();
                },
              )
            ],
          );
        });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        bottomNavigationBar: BottomNavigationBar(
          type: BottomNavigationBarType.fixed,
          currentIndex: _currentIndex,
          backgroundColor: const Color(0XFF116AFF),
          unselectedItemColor: Colors.white,
          selectedLabelStyle: const TextStyle(color: Colors.white),
          showUnselectedLabels: false,
          onTap: (value) {
            setState(() => _currentIndex = value);
          },
          items: [
            BottomNavigationBarItem(
              label: 'MDM',
              icon: Container(
                decoration: BoxDecoration(
                    color:
                        _currentIndex == 0 ? Colors.white : Colors.transparent,
                    shape: BoxShape.circle),
                child: const Padding(
                  padding: EdgeInsets.all(10.0),
                  child: Icon(Icons.electric_meter_outlined),
                ),
              ),
            ),
            BottomNavigationBarItem(
              label: 'Site Survey',
              icon: Container(
                decoration: BoxDecoration(
                    color:
                        _currentIndex == 1 ? Colors.white : Colors.transparent,
                    shape: BoxShape.circle),
                child: const Padding(
                  padding: EdgeInsets.all(10.0),
                  child: Icon(Icons.location_city_outlined),
                ),
              ),
            ),
            BottomNavigationBarItem(
              label: 'Meter Replace',
              icon: Container(
                decoration: BoxDecoration(
                    color:
                        _currentIndex == 2 ? Colors.white : Colors.transparent,
                    shape: BoxShape.circle),
                child: const Padding(
                  padding: EdgeInsets.all(10.0),
                  child: Icon(Icons.library_books_outlined),
                ),
              ),
            ),
            BottomNavigationBarItem(
              label: 'TroubleShoot',
              icon: Container(
                decoration: BoxDecoration(
                    color:
                        _currentIndex == 3 ? Colors.white : Colors.transparent,
                    shape: BoxShape.circle),
                child: const Padding(
                  padding: EdgeInsets.all(10.0),
                  child: Icon(Icons.info_outline),
                ),
              ),
            ),
          ],
        ),
        appBar: AppBar(
          automaticallyImplyLeading: false,
          title: const Text(Strings.kMRDLabel),
          actions: [
            IconButton(
                onPressed: () {
                  _showMyDialog();
                },
                icon: const Icon(Icons.power_settings_new))
          ],
        ),
        body: childView());
  }

  Widget childView() {
    return SingleChildScrollView(
        scrollDirection: Axis.vertical,
        child: Padding(
          padding: const EdgeInsets.all(20.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: <Widget>[
              Row(
                mainAxisAlignment: MainAxisAlignment.start,
                crossAxisAlignment: CrossAxisAlignment.center,
                children: [
                  Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: <Widget>[
                      Text(
                        Strings.kWelcome2Label,
                        style: TextStyle(
                            color: Colors.amber.shade700,
                            fontSize: 16.0,
                            fontWeight: FontWeight.w600),
                      ),
                      Text(
                        _userName.toTitleCase(),
                        style: const TextStyle(
                            color: Colors.black,
                            fontSize: 16.0,
                            fontWeight: FontWeight.w400),
                      )
                    ],
                  ),
                  const Spacer(),
                  ClipRRect(
                    borderRadius: BorderRadius.circular(10),
                    child: Container(
                      padding: const EdgeInsets.all(10),
                      decoration: BoxDecoration(color: Colors.grey.shade200),
                      child: SvgPicture.asset(
                        'images/profile.svg',
                        height: 54.0,
                        width: 54.0,
                      ),
                    ),
                  ),
                ],
              ),
              const SizedBox(
                height: 30,
              ),
              Column(
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: [pages[_currentIndex]],
              ),
            ],
          ),
        ));
  }
}
</code>```
```<code>import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:manager/components/dotted_line.dart';
import 'package:manager/model/lookup_cycle.dart';
import 'package:manager/model/mr_report_model.dart';
import 'package:manager/services/dashboard_service.dart';
import 'package:manager/utils/debouncer.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:manager/utils/string_captialize.dart';

class MRPerformance extends StatefulWidget {
  const MRPerformance({super.key});

  @override
  State<MRPerformance> createState() => _MRPerformanceState();
}

bool isFilter = false;
bool isPerformingRequest = false;
int pageNumber = 0;
String _chosenValue = '';
List<MRReportResult> users = [];
Future<List<String>?>? dropDownValue;
ScrollController _scrollController = ScrollController();
final _debouncer = Debouncer(milliseconds: 500);

class _MRPerformanceState extends State<MRPerformance> {
  @override
  void initState() {
    super.initState();

    _getMoreData(_chosenValue);
    dropDownValue = getAllCategory();

    _scrollController.addListener(() {
      if (_scrollController.position.pixels ==
          _scrollController.position.maxScrollExtent) {
        pageNumber++;

        _getMoreData(_chosenValue);
      }
    });
  }

  Future<List<String>?>? getAllCategory() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    String token = prefs.getString('token')!;

    var cycleResponse = await Dashboard().getAllCycle(token);
    try {
      if (cycleResponse.statusCode == 200) {
        List<String> items = [];
        var jsonData = json.decode(cycleResponse.body) as List;
        List<LookUpCycle> lookupCycle = jsonData
            .map<LookUpCycle>((json) => LookUpCycle.fromJson(json))
            .toList();
        items.add('Select');
        for (var element in lookupCycle) {
          if (element.name != null) {
            items.add(element.name!);
          }
        }
        return items;
      }
    } catch (ex) {
      throw (ex.toString());
    }
    return null;
  }

  @override
  void dispose() {
    super.dispose();
    _scrollController.dispose();
  }

  void _getMoreData(String searchCycle) async {
    List<MRReportResult>? resultResponse = [];
    if (!isPerformingRequest) {
      setState(() {
        isPerformingRequest = true;
      });
      SharedPreferences prefs = await SharedPreferences.getInstance();
      String token = prefs.getString('token')!;
      debugPrint(token);
      var responseData =
          await Dashboard().getMRReport(token, pageNumber, 10, searchCycle);
      if (responseData.statusCode == 200) {
        String data = responseData.body;
        var decodedData = jsonDecode(data);
        MRReportModel newEntries = MRReportModel.fromJson(decodedData);
        if (newEntries.result == null) {
          if (newEntries.result!.isEmpty) {
            double edge = 50.0;
            double offsetFromBottom =
                _scrollController.position.maxScrollExtent -
                    _scrollController.position.pixels;
            if (offsetFromBottom < edge) {
              _scrollController.animateTo(
                  _scrollController.offset - (edge - offsetFromBottom),
                  duration: const Duration(milliseconds: 500),
                  curve: Curves.easeOut);
            }
          }
        }
        setState(() {
          users.addAll(newEntries.result!);
          isPerformingRequest = false;
        });
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        resizeToAvoidBottomInset: false,
        appBar: AppBar(title: const Text('MR Performance')),
        body: filterView());
  }

  void setFilterState() {
    setState(() {
      if (isFilter == true) {
        isFilter = false;
      } else {
        isFilter = true;
      }
    });
  }

  Widget _buildProgressIndicator() {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: Center(
        child: Opacity(
          opacity: isPerformingRequest ? 1.0 : 0.0,
          child: const CircularProgressIndicator(),
        ),
      ),
    );
  }

  Widget filterView() {
    return Column(
      children: [
        Row(
          children: [
            Visibility(
              visible: isFilter ? true : false,
              child: Flexible(
                child: Card(
                  shape: RoundedRectangleBorder(
                      side: const BorderSide(color: Color(0XFFDCDCDC)),
                      borderRadius: BorderRadius.circular(10)),
                  elevation: 2,
                  child: Column(
                    children: [
                      Row(
                        children: [
                          Expanded(
                            child: TextField(
                              textInputAction: TextInputAction.search,
                              decoration: const InputDecoration(
                                border: InputBorder.none,
                                prefixIcon: InkWell(
                                  child: Icon(Icons.search),
                                ),
                                contentPadding: EdgeInsets.all(8.0),
                                hintText: 'Search ',
                              ),
                              onChanged: (string) {
                                _debouncer.run(() {});
                              },
                            ),
                          ),
                        ],
                      ),
                    ],
                  ),
                ),
              ),
            ),
            Visibility(
              visible: isFilter ? false : true,
              child: Flexible(
                child: Card(
                  elevation: 4,
                  shape: RoundedRectangleBorder(
                      side: const BorderSide(color: Color(0XFFDCDCDC)),
                      borderRadius: BorderRadius.circular(10)),
                  child: Padding(
                      padding: const EdgeInsets.only(
                        left: 10,
                      ),
                      child: FutureBuilder<List<String>?>(
                        future: dropDownValue,
                        builder: (context, snapshot) {
                          if (snapshot.connectionState ==
                              ConnectionState.done) {
                            if (snapshot.hasError) {
                              return const Text('Something wrong');
                            } else if (snapshot.hasData) {
                              var data = snapshot.data!;
                              return DropdownButtonHideUnderline(
                                child: DropdownButton<String>(
                                  icon: const Icon(
                                    Icons.expand_more_outlined,
                                    size: 35,
                                    color: Color(0XFF116AFF),
                                  ),
                                  borderRadius: BorderRadius.circular(10),
                                  isExpanded: true,
                                  // value: _chosenValue.isNotEmpty ? _chosenValue : null,
                                  elevation: 16,
                                  style: const TextStyle(
                                      color: Colors.black,
                                      fontSize: 14,
                                      fontWeight: FontWeight.w400),
                                  items: data.map((String value) {
                                    return DropdownMenuItem(
                                        value: value, child: Text(value));
                                  }).toList(),
                                  hint: Padding(
                                    padding: const EdgeInsets.all(15),
                                    child: Text(
                                      _chosenValue.isEmpty
                                          ? 'Cycle'
                                          : _chosenValue,
                                      style: const TextStyle(
                                          color: Colors.black,
                                          fontSize: 16,
                                          fontWeight: FontWeight.w400),
                                    ),
                                  ),
                                  onChanged: (String? value) {
                                    setState(() {
                                      if (value != null) {
                                        pageNumber = 0;
                                        users.clear();
                                        if (value == 'Select') {
                                          _chosenValue = '';
                                        } else {
                                          _chosenValue = value;
                                        }
                                        _getMoreData(_chosenValue);
                                      }
                                    });
                                  },
                                ),
                              );
                            }
                          }
                          return const CircularProgressIndicator();
                        },
                      )),
                ),
              ),
            ),
            InkWell(
              onTap: () => {setFilterState()},
              child: Card(
                elevation: 4,
                shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(10)),
                child: Padding(
                  padding: const EdgeInsets.all(10.0),
                  child: isFilter
                      ? const Icon(Icons.filter_alt, color: Color(0XFF116AFF))
                      : const Icon(
                          Icons.search,
                          color: Color(0XFF116AFF),
                        ),
                ),
              ),
            ),
          ],
        ),
        Expanded(
          child: ListView.builder(
              shrinkWrap: true,
              scrollDirection: Axis.vertical,
              itemCount: users.length + 1,
              controller: _scrollController,
              itemBuilder: (BuildContext context, int index) {
                if (index == users.length) {
                  return _buildProgressIndicator();
                } else {
                  return cardView(users, index);
                }
              }),
        ),
      ],
    );
  }

  Widget cardView(List<MRReportResult>? users, int index) {
    return Card(
      shape: RoundedRectangleBorder(
          side: const BorderSide(color: Color(0XFFDCDCDC)),
          borderRadius: BorderRadius.circular(10)),
      margin: const EdgeInsets.all(8),
      child: Padding(
        padding: const EdgeInsets.all(10.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          children: [
            Container(
              decoration: BoxDecoration(
                  border: Border.all(
                    color: Colors.orange,
                  ),
                  borderRadius: const BorderRadius.all(Radius.circular(20))),
              margin: const EdgeInsets.all(10),
              padding: const EdgeInsets.all(10),
              child: Row(
                children: [
                  Text(
                    '${users?[index].mRNumber}: ',
                    style: const TextStyle(
                        color: Colors.orange,
                        fontSize: 10,
                        fontWeight: FontWeight.w600),
                  ),
                  Text(
                    '${users?[index].meterReaderName}'.toTitleCase(),
                    style: const TextStyle(
                        color: Colors.black,
                        fontSize: 10,
                        fontWeight: FontWeight.w400),
                  ),
                ],
              ),
            ),
            Padding(
              padding: const EdgeInsets.only(left: 20),
              child: Row(
                children: [
                  const Text(
                    'Supervisor: ',
                    style: TextStyle(
                        color: Color(0XFF004AC6),
                        fontSize: 10,
                        fontWeight: FontWeight.w600),
                  ),
                  Expanded(
                    child: Text(
                      '${users?[index].supervisor}'.toTitleCase(),
                      overflow: TextOverflow.fade,
                      style: const TextStyle(
                          color: Colors.black,
                          fontSize: 10,
                          fontWeight: FontWeight.w400),
                    ),
                  ),
                ],
              ),
            ),
            const SizedBox(height: 10),
            const MySeparator(),
            const SizedBox(height: 10),
            Padding(
              padding: const EdgeInsets.only(left: 30, right: 30),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  Row(
                    children: [
                      Column(
                        children: [
                          Text(
                            '${users?[index].unreadPercenatge}%',
                            style: const TextStyle(
                                color: Colors.orange,
                                fontSize: 10,
                                fontWeight: FontWeight.w600),
                          ),
                          const Text(
                            'Unread',
                            style: TextStyle(
                                color: Color(0XFF004AC6),
                                fontSize: 12,
                                fontWeight: FontWeight.w400),
                          )
                        ],
                      )
                    ],
                  ),
                  Row(
                    children: [
                      Column(
                        children: [
                          Text(
                            '${users?[index].readPercenatge}%',
                            style: const TextStyle(
                                color: Colors.green,
                                fontSize: 10,
                                fontWeight: FontWeight.w600),
                          ),
                          const Text(
                            'Read',
                            style: TextStyle(
                                color: Color(0XFF004AC6),
                                fontSize: 12,
                                fontWeight: FontWeight.w400),
                          )
                        ],
                      )
                    ],
                  ),
                  Row(
                    children: [
                      Column(
                        children: [
                          Text(
                            '${users?[index].plusorMinusTwoReadPercentage}%',
                            style: const TextStyle(
                                color: Colors.green,
                                fontSize: 10,
                                fontWeight: FontWeight.w600),
                          ),
                          const Text(
                            '+/- 2',
                            style: TextStyle(
                                color: Color(0XFF004AC6),
                                fontSize: 12,
                                fontWeight: FontWeight.w400),
                          )
                        ],
                      )
                    ],
                  ),
                  Row(
                    children: [
                      Column(
                        children: [
                          Text(
                            '${users?[index].above32ReadPercentage}%',
                            style: const TextStyle(
                                color: Colors.orange,
                                fontSize: 10,
                                fontWeight: FontWeight.w600),
                          ),
                          const Text(
                            '>32',
                            style: TextStyle(
                                color: Color(0XFF004AC6),
                                fontSize: 12,
                                fontWeight: FontWeight.w400),
                          )
                        ],
                      )
                    ],
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}
</code>```
<p>════════ Exception caught by widgets library ═══════════════════════════════════
The following assertion was thrown building Builder:
A ScrollController was used after being disposed.</p>
<p>Once you have called dispose() on a ScrollController, it can no longer be used.
The relevant error-causing widget was
MaterialApp
lib/main.dart:13
When the exception was thrown, this was the stack</p>

Body:
class HomeScreen extends StatefulWidget {
  final userName;
  HomeScreen(this.userName);

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

Future<ClientDashboardModel?>? _meterReadingResponse;
BatchSummaryModel? _batchResponse;
AMRDashboardModel? _amrDashboardResponse;
String _userName = '';
int? qcAssignedReads = 0;
int? qcMrCompleted = 0;
int? qcCompletedReads = 0;
int? qcPendingReads = 0;
int? qcApprovedReads = 0;
int? qcRejectedReads = 0;
bool isFirstTimeCalled = false;
Timer? _timer;

int _currentIndex = 0;

final pages = [
  const MDMScreen(),
  const AMRDashboard(whichScreen: 0),
  const AMRDashboard(whichScreen: 1),
  const AMRDashboard(whichScreen: 2)
];

class _HomeScreenState extends State<HomeScreen> {
  @override
  void initState() {
    setUpTimedFetch();
    super.initState();
    if (widget.userName != null) _userName = (widget.userName!);
  }

  @override
  void dispose() {
    isFirstTimeCalled = false;
    _timer?.cancel();
    super.dispose();
  }

  void setUpTimedFetch() {
    if (!isFirstTimeCalled) {
      _meterReadingResponse = _getDashboardData();
    }
    isFirstTimeCalled = true;
  }

  Future<ClientDashboardModel?> _getDashboardData() async {
    ClientDashboardModel? meterReadingResponse;

    SharedPreferences prefs = await SharedPreferences.getInstance();
    String token = prefs.getString('token')!;

    var responseData = await Dashboard().getClientDashboard(token);
    if (responseData.statusCode == 200) {
      String data = responseData.body;

      var decodedData = jsonDecode(data);
      meterReadingResponse = null;
      meterReadingResponse = ClientDashboardModel.fromJson(decodedData);

      return meterReadingResponse;
    }
    return null;
  }

  void logout() async {
    SharedPreferences.getInstance().then((value) {
      value.remove('token');
      value.remove('userName');
    });
    Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) {
      return const LoginScreen();
    }));
  }

  Future<void> _showMyDialog() async {
    return showDialog<void>(
        context: context,
        barrierDismissible: false,
        builder: (BuildContext context) {
          return AlertDialog(
            title: const Text(Strings.kLogoutLabel),
            content: const Text(Strings.kConfirmLogout),
            actions: <Widget>[
              TextButton(
                child: const Text(Strings.kCancelLabel),
                onPressed: () {
                  Navigator.of(context).pop();
                },
              ),
              TextButton(
                child: const Text(Strings.kOKLabel),
                onPressed: () {
                  Navigator.of(context).pop();
                  logout();
                },
              )
            ],
          );
        });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        bottomNavigationBar: BottomNavigationBar(
          type: BottomNavigationBarType.fixed,
          currentIndex: _currentIndex,
          backgroundColor: const Color(0XFF116AFF),
          unselectedItemColor: Colors.white,
          selectedLabelStyle: const TextStyle(color: Colors.white),
          showUnselectedLabels: false,
          onTap: (value) {
            setState(() => _currentIndex = value);
          },
          items: [
            BottomNavigationBarItem(
              label: 'MDM',
              icon: Container(
                decoration: BoxDecoration(
                    color:
                        _currentIndex == 0 ? Colors.white : Colors.transparent,
                    shape: BoxShape.circle),
                child: const Padding(
                  padding: EdgeInsets.all(10.0),
                  child: Icon(Icons.electric_meter_outlined),
                ),
              ),
            ),
            BottomNavigationBarItem(
              label: 'Site Survey',
              icon: Container(
                decoration: BoxDecoration(
                    color:
                        _currentIndex == 1 ? Colors.white : Colors.transparent,
                    shape: BoxShape.circle),
                child: const Padding(
                  padding: EdgeInsets.all(10.0),
                  child: Icon(Icons.location_city_outlined),
                ),
              ),
            ),
            BottomNavigationBarItem(
              label: 'Meter Replace',
              icon: Container(
                decoration: BoxDecoration(
                    color:
                        _currentIndex == 2 ? Colors.white : Colors.transparent,
                    shape: BoxShape.circle),
                child: const Padding(
                  padding: EdgeInsets.all(10.0),
                  child: Icon(Icons.library_books_outlined),
                ),
              ),
            ),
            BottomNavigationBarItem(
              label: 'TroubleShoot',
              icon: Container(
                decoration: BoxDecoration(
                    color:
                        _currentIndex == 3 ? Colors.white : Colors.transparent,
                    shape: BoxShape.circle),
                child: const Padding(
                  padding: EdgeInsets.all(10.0),
                  child: Icon(Icons.info_outline),
                ),
              ),
            ),
          ],
        ),
        appBar: AppBar(
          automaticallyImplyLeading: false,
          title: const Text(Strings.kMRDLabel),
          actions: [
            IconButton(
                onPressed: () {
                  _showMyDialog();
                },
                icon: const Icon(Icons.power_settings_new))
          ],
        ),
        body: childView());
  }

  Widget childView() {
    return SingleChildScrollView(
        scrollDirection: Axis.vertical,
        child: Padding(
          padding: const EdgeInsets.all(20.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: <Widget>[
              Row(
                mainAxisAlignment: MainAxisAlignment.start,
                crossAxisAlignment: CrossAxisAlignment.center,
                children: [
                  Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: <Widget>[
                      Text(
                        Strings.kWelcome2Label,
                        style: TextStyle(
                            color: Colors.amber.shade700,
                            fontSize: 16.0,
                            fontWeight: FontWeight.w600),
                      ),
                      Text(
                        _userName.toTitleCase(),
                        style: const TextStyle(
                            color: Colors.black,
                            fontSize: 16.0,
                            fontWeight: FontWeight.w400),
                      )
                    ],
                  ),
                  const Spacer(),
                  ClipRRect(
                    borderRadius: BorderRadius.circular(10),
                    child: Container(
                      padding: const EdgeInsets.all(10),
                      decoration: BoxDecoration(color: Colors.grey.shade200),
                      child: SvgPicture.asset(
                        'images/profile.svg',
                        height: 54.0,
                        width: 54.0,
                      ),
                    ),
                  ),
                ],
              ),
              const SizedBox(
                height: 30,
              ),
              Column(
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: [pages[_currentIndex]],
              ),
            ],
          ),
        ));
  }
}

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:manager/components/dotted_line.dart';
import 'package:manager/model/lookup_cycle.dart';
import 'package:manager/model/mr_report_model.dart';
import 'package:manager/services/dashboard_service.dart';
import 'package:manager/utils/debouncer.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:manager/utils/string_captialize.dart';

class MRPerformance extends StatefulWidget {
  const MRPerformance({super.key});

  @override
  State<MRPerformance> createState() => _MRPerformanceState();
}

bool isFilter = false;
bool isPerformingRequest = false;
int pageNumber = 0;
String _chosenValue = '';
List<MRReportResult> users = [];
Future<List<String>?>? dropDownValue;
ScrollController _scrollController = ScrollController();
final _debouncer = Debouncer(milliseconds: 500);

class _MRPerformanceState extends State<MRPerformance> {
  @override
  void initState() {
    super.initState();

    _getMoreData(_chosenValue);
    dropDownValue = getAllCategory();

    _scrollController.addListener(() {
      if (_scrollController.position.pixels ==
          _scrollController.position.maxScrollExtent) {
        pageNumber++;

        _getMoreData(_chosenValue);
      }
    });
  }

  Future<List<String>?>? getAllCategory() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    String token = prefs.getString('token')!;

    var cycleResponse = await Dashboard().getAllCycle(token);
    try {
      if (cycleResponse.statusCode == 200) {
        List<String> items = [];
        var jsonData = json.decode(cycleResponse.body) as List;
        List<LookUpCycle> lookupCycle = jsonData
            .map<LookUpCycle>((json) => LookUpCycle.fromJson(json))
            .toList();
        items.add('Select');
        for (var element in lookupCycle) {
          if (element.name != null) {
            items.add(element.name!);
          }
        }
        return items;
      }
    } catch (ex) {
      throw (ex.toString());
    }
    return null;
  }

  @override
  void dispose() {
    super.dispose();
    _scrollController.dispose();
  }

  void _getMoreData(String searchCycle) async {
    List<MRReportResult>? resultResponse = [];
    if (!isPerformingRequest) {
      setState(() {
        isPerformingRequest = true;
      });
      SharedPreferences prefs = await SharedPreferences.getInstance();
      String token = prefs.getString('token')!;
      debugPrint(token);
      var responseData =
          await Dashboard().getMRReport(token, pageNumber, 10, searchCycle);
      if (responseData.statusCode == 200) {
        String data = responseData.body;
        var decodedData = jsonDecode(data);
        MRReportModel newEntries = MRReportModel.fromJson(decodedData);
        if (newEntries.result == null) {
          if (newEntries.result!.isEmpty) {
            double edge = 50.0;
            double offsetFromBottom =
                _scrollController.position.maxScrollExtent -
                    _scrollController.position.pixels;
            if (offsetFromBottom < edge) {
              _scrollController.animateTo(
                  _scrollController.offset - (edge - offsetFromBottom),
                  duration: const Duration(milliseconds: 500),
                  curve: Curves.easeOut);
            }
          }
        }
        setState(() {
          users.addAll(newEntries.result!);
          isPerformingRequest = false;
        });
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        resizeToAvoidBottomInset: false,
        appBar: AppBar(title: const Text('MR Performance')),
        body: filterView());
  }

  void setFilterState() {
    setState(() {
      if (isFilter == true) {
        isFilter = false;
      } else {
        isFilter = true;
      }
    });
  }

  Widget _buildProgressIndicator() {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: Center(
        child: Opacity(
          opacity: isPerformingRequest ? 1.0 : 0.0,
          child: const CircularProgressIndicator(),
        ),
      ),
    );
  }

  Widget filterView() {
    return Column(
      children: [
        Row(
          children: [
            Visibility(
              visible: isFilter ? true : false,
              child: Flexible(
                child: Card(
                  shape: RoundedRectangleBorder(
                      side: const BorderSide(color: Color(0XFFDCDCDC)),
                      borderRadius: BorderRadius.circular(10)),
                  elevation: 2,
                  child: Column(
                    children: [
                      Row(
                        children: [
                          Expanded(
                            child: TextField(
                              textInputAction: TextInputAction.search,
                              decoration: const InputDecoration(
                                border: InputBorder.none,
                                prefixIcon: InkWell(
                                  child: Icon(Icons.search),
                                ),
                                contentPadding: EdgeInsets.all(8.0),
                                hintText: 'Search ',
                              ),
                              onChanged: (string) {
                                _debouncer.run(() {});
                              },
                            ),
                          ),
                        ],
                      ),
                    ],
                  ),
                ),
              ),
            ),
            Visibility(
              visible: isFilter ? false : true,
              child: Flexible(
                child: Card(
                  elevation: 4,
                  shape: RoundedRectangleBorder(
                      side: const BorderSide(color: Color(0XFFDCDCDC)),
                      borderRadius: BorderRadius.circular(10)),
                  child: Padding(
                      padding: const EdgeInsets.only(
                        left: 10,
                      ),
                      child: FutureBuilder<List<String>?>(
                        future: dropDownValue,
                        builder: (context, snapshot) {
                          if (snapshot.connectionState ==
                              ConnectionState.done) {
                            if (snapshot.hasError) {
                              return const Text('Something wrong');
                            } else if (snapshot.hasData) {
                              var data = snapshot.data!;
                              return DropdownButtonHideUnderline(
                                child: DropdownButton<String>(
                                  icon: const Icon(
                                    Icons.expand_more_outlined,
                                    size: 35,
                                    color: Color(0XFF116AFF),
                                  ),
                                  borderRadius: BorderRadius.circular(10),
                                  isExpanded: true,
                                  // value: _chosenValue.isNotEmpty ? _chosenValue : null,
                                  elevation: 16,
                                  style: const TextStyle(
                                      color: Colors.black,
                                      fontSize: 14,
                                      fontWeight: FontWeight.w400),
                                  items: data.map((String value) {
                                    return DropdownMenuItem(
                                        value: value, child: Text(value));
                                  }).toList(),
                                  hint: Padding(
                                    padding: const EdgeInsets.all(15),
                                    child: Text(
                                      _chosenValue.isEmpty
                                          ? 'Cycle'
                                          : _chosenValue,
                                      style: const TextStyle(
                                          color: Colors.black,
                                          fontSize: 16,
                                          fontWeight: FontWeight.w400),
                                    ),
                                  ),
                                  onChanged: (String? value) {
                                    setState(() {
                                      if (value != null) {
                                        pageNumber = 0;
                                        users.clear();
                                        if (value == 'Select') {
                                          _chosenValue = '';
                                        } else {
                                          _chosenValue = value;
                                        }
                                        _getMoreData(_chosenValue);
                                      }
                                    });
                                  },
                                ),
                              );
                            }
                          }
                          return const CircularProgressIndicator();
                        },
                      )),
                ),
              ),
            ),
            InkWell(
              onTap: () => {setFilterState()},
              child: Card(
                elevation: 4,
                shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(10)),
                child: Padding(
                  padding: const EdgeInsets.all(10.0),
                  child: isFilter
                      ? const Icon(Icons.filter_alt, color: Color(0XFF116AFF))
                      : const Icon(
                          Icons.search,
                          color: Color(0XFF116AFF),
                        ),
                ),
              ),
            ),
          ],
        ),
        Expanded(
          child: ListView.builder(
              shrinkWrap: true,
              scrollDirection: Axis.vertical,
              itemCount: users.length + 1,
              controller: _scrollController,
              itemBuilder: (BuildContext context, int index) {
                if (index == users.length) {
                  return _buildProgressIndicator();
                } else {
                  return cardView(users, index);
                }
              }),
        ),
      ],
    );
  }

  Widget cardView(List<MRReportResult>? users, int index) {
    return Card(
      shape: RoundedRectangleBorder(
          side: const BorderSide(color: Color(0XFFDCDCDC)),
          borderRadius: BorderRadius.circular(10)),
      margin: const EdgeInsets.all(8),
      child: Padding(
        padding: const EdgeInsets.all(10.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          children: [
            Container(
              decoration: BoxDecoration(
                  border: Border.all(
                    color: Colors.orange,
                  ),
                  borderRadius: const BorderRadius.all(Radius.circular(20))),
              margin: const EdgeInsets.all(10),
              padding: const EdgeInsets.all(10),
              child: Row(
                children: [
                  Text(
                    '${users?[index].mRNumber}: ',
                    style: const TextStyle(
                        color: Colors.orange,
                        fontSize: 10,
                        fontWeight: FontWeight.w600),
                  ),
                  Text(
                    '${users?[index].meterReaderName}'.toTitleCase(),
                    style: const TextStyle(
                        color: Colors.black,
                        fontSize: 10,
                        fontWeight: FontWeight.w400),
                  ),
                ],
              ),
            ),
            Padding(
              padding: const EdgeInsets.only(left: 20),
              child: Row(
                children: [
                  const Text(
                    'Supervisor: ',
                    style: TextStyle(
                        color: Color(0XFF004AC6),
                        fontSize: 10,
                        fontWeight: FontWeight.w600),
                  ),
                  Expanded(
                    child: Text(
                      '${users?[index].supervisor}'.toTitleCase(),
                      overflow: TextOverflow.fade,
                      style: const TextStyle(
                          color: Colors.black,
                          fontSize: 10,
                          fontWeight: FontWeight.w400),
                    ),
                  ),
                ],
              ),
            ),
            const SizedBox(height: 10),
            const MySeparator(),
            const SizedBox(height: 10),
            Padding(
              padding: const EdgeInsets.only(left: 30, right: 30),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  Row(
                    children: [
                      Column(
                        children: [
                          Text(
                            '${users?[index].unreadPercenatge}%',
                            style: const TextStyle(
                                color: Colors.orange,
                                fontSize: 10,
                                fontWeight: FontWeight.w600),
                          ),
                          const Text(
                            'Unread',
                            style: TextStyle(
                                color: Color(0XFF004AC6),
                                fontSize: 12,
                                fontWeight: FontWeight.w400),
                          )
                        ],
                      )
                    ],
                  ),
                  Row(
                    children: [
                      Column(
                        children: [
                          Text(
                            '${users?[index].readPercenatge}%',
                            style: const TextStyle(
                                color: Colors.green,
                                fontSize: 10,
                                fontWeight: FontWeight.w600),
                          ),
                          const Text(
                            'Read',
                            style: TextStyle(
                                color: Color(0XFF004AC6),
                                fontSize: 12,
                                fontWeight: FontWeight.w400),
                          )
                        ],
                      )
                    ],
                  ),
                  Row(
                    children: [
                      Column(
                        children: [
                          Text(
                            '${users?[index].plusorMinusTwoReadPercentage}%',
                            style: const TextStyle(
                                color: Colors.green,
                                fontSize: 10,
                                fontWeight: FontWeight.w600),
                          ),
                          const Text(
                            '+/- 2',
                            style: TextStyle(
                                color: Color(0XFF004AC6),
                                fontSize: 12,
                                fontWeight: FontWeight.w400),
                          )
                        ],
                      )
                    ],
                  ),
                  Row(
                    children: [
                      Column(
                        children: [
                          Text(
                            '${users?[index].above32ReadPercentage}%',
                            style: const TextStyle(
                                color: Colors.orange,
                                fontSize: 10,
                                fontWeight: FontWeight.w600),
                          ),
                          const Text(
                            '>32',
                            style: TextStyle(
                                color: Color(0XFF004AC6),
                                fontSize: 12,
                                fontWeight: FontWeight.w400),
                          )
                        ],
                      )
                    ],
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

════════ Exception caught by widgets library ═══════════════════════════════════
The following assertion was thrown building Builder:
A ScrollController was used after being disposed.

Once you have called dispose() on a ScrollController, it can no longer be used.
The relevant error-causing widget was
MaterialApp
lib/main.dart:13
When the exception was thrown, this was the stack