react-native icon indicating copy to clipboard operation
react-native copied to clipboard

Placeholder property included in TextInput Componenent prevents accessibilityLabel and accessibiltyHint from being read by screenreader

Open ryan-henderson-IM opened this issue 5 years ago • 23 comments

When including a placeholder property in a TextInput component, the accessibilityLabel and accessibilityHint properties are not read out in the screen reader. Example:

<TextInput accessible={true} accessibilityLabel={'My Accessibility Label'} accessibilityHint={'My Accessibility Hint')} accessibilityRole={'search'} style={[searchInput, { backgroundColor: searchFocus ? theme.INPUT_FOCUS_COLOR : theme.WHITE_COLOR }]} onFocus={(bool) => {set_searchFocus(bool);}} value={searchKey} inputAccessoryViewID={inputAccessoryViewID} placeholderTextColor={'#767676'} keyboardType= "default" returnKeyType={Platform.OS === 'ios' ? '' : "search"} enablesReturnKeyAutomatically={true} onSubmitEditing={() => {searchOrder();}} placeholder={formatMessageString('My Placeholder Text')} onChangeText={(searchString) =>{setSearchKey(searchString);}} underlineColorAndroid="transparent" />

One would expect the accessibilityLabel and Hint to be read out, and in my experience prior to 0.60 they were, along with the placeholder. Now, only the placeholder text his read out. Removing the placeholder property reads out the Label and Hint.

React Native version:

0.60.5

Steps To Reproduce

  1. Include a TextInput in project with accessibilityLabel, accessibilityHint, and placeholder text.
  2. Open project in device, turn on screenreader (e.g. TalkBack for Android, VoiceOver for iOS), and click the field.
  3. Click on field
  4. Note that screenreader only reads out the placeholder text, and not the accessibilityLabel and accessibilityHint.
  5. Remove placeholder text and reload.
  6. Click on field
  7. Note that accessbilityLabel and accessibilityHint are read out by the screenreader

ryan-henderson-IM avatar Oct 07 '19 00:10 ryan-henderson-IM

I am also facing the same issue. Can you please let me know if any solution or work around is available?

vishweshjoshi avatar Oct 11 '19 11:10 vishweshjoshi

Hey there, it looks like there has been no activity on this issue recently. Has the issue been fixed, or does it still require the community's attention? This issue may be closed if no further activity occurs. You may also label this issue as a "Discussion" or add it to the "Backlog" and I will leave it open. Thank you for your contributions.

stale[bot] avatar Jan 09 '20 12:01 stale[bot]

I can reproduce the issue using React Native 0.61 and TalkBack on Android 10.

fvsch avatar Jan 14 '20 13:01 fvsch

Hi! I am still facing the same issue using RN: 0.61 and TalkBack on Android 9.

smjurek avatar Jan 28 '20 11:01 smjurek

Hey there, it looks like there has been no activity on this issue recently. Has the issue been fixed, or does it still require the community's attention? This issue may be closed if no further activity occurs. You may also label this issue as a "Discussion" or add it to the "Backlog" and I will leave it open. Thank you for your contributions.

stale[bot] avatar Apr 28 '20 04:04 stale[bot]

I'm having the same issue, except it happens any time the component has a value, placeholder or not. The accessiblityLabel only gets read when the field is entirely empty.

RN 0.62.2

some samples with read out verbiage in comments:

{/* "field name" */}
<View accessible={true} accessibilityLabel={"Field Name"}>
	<Paragraph>Field Name</Paragraph>
	<View>
		{/* "six edit box" */}
		<TextInput
			value={"6"}
			keyboardType="numeric"
		/>
	</View>
</View>
{/* "field name the field value is 7" */}
<View accessible={true} accessibilityLabel={"Field Name"} accessibilityValue={{ text: "The field value is 7" }}>
	<Paragraph>Field Name</Paragraph>
	<View>
		{/* "seven edit box" */}
		<TextInput
			value={"7"}
			keyboardType="numeric"
		/>
	</View>
</View>
{/* "field name" */}
<View accessible={true}>
	<Paragraph>Field Name</Paragraph>
	<View>
		{/* "eight edit box" */}
		<TextInput
			value={"8"}
			keyboardType="numeric"
			accessibilityLabel={"Field Name"}
		/>
	</View>
</View>
{/* "field name" */}
<View>
	<Paragraph>Field Name</Paragraph>
	<View>
		{/* "nine edit box" */}
		<TextInput
			value={"9"}
			keyboardType="numeric"
			accessibilityValue={{ text: "The field value is 9" }}
			accessibilityLabel={"Field Name"}
		/>
	</View>
</View>
{/* "field name" */}
<View accessible={true}>
	<Paragraph>Field Name</Paragraph>
	<View>
		{/* "placeholder edit box" */}
		<TextInput
			value={undefined}
			keyboardType="numeric"
			accessibilityLabel={"Field Name"}
			placeholder="placeholder"
		/>
	</View>
</View>

This one is fun: if the value is empty, the accessibilityValue will get read along with the accessibilityLabel. Which is the behavior I'd expect in all cases.

{/* "field name" */}
<View accessible={true}>
	<Paragraph>Field Name</Paragraph>
	<View>
		{/* "field name the field value is 9 edit box" */}
		<TextInput
			value={undefined}
			keyboardType="numeric"
			accessibilityLabel={"Field Name"}
			accessibilityValue={{ text: "The field value is 9" }}
		/>
	</View>
</View>

hapablap21 avatar May 05 '20 18:05 hapablap21

I'm putting my hat in the ring on this. We've spent the last couple days trying to figure out our field accessibility with Android. Digging into this it is clear that react-native's accessibility on Android is broken, and I've got some evidence of our findings.

Essentially, we were able to discern that there are 4 variables that determine what Android or iOS says - existence of value, accessibilityLabel, accessibilityHint, or placeholder. React-Native on iOS seems to treat all of the scenarios logically, while Android does not. I've created a minimal example demonstrating all 7 combinations of specification of accessibilityLabel / accessibilityHint / placeholder, and you can clear the text box/value to investigate the other 7 combinations (without value). As well, above each example I specify what Android/iOS reads with no value, and below each example I specify what Android/iOS reads with "1" as the value:

import * as React from 'react';
import { AccessibilityInfo, TextInput, TouchableWithoutFeedback, Text, View, StyleSheet } from 'react-native';

const labelText = "Test";

export default class App extends React.Component {
  state = { text: "1" }

  render() {
    const Example = ({title, label, hint, placeholder}) => {
      const accessibilityProps = {
        ...(hint && { accessibilityHint: `${labelText} hint`}),
        ...(placeholder && { placeholder: `${labelText} placeholder`}),
        ...(label && { accessibilityLabel: `${labelText} label`})
      };

      return (
      <React.Fragment>
      <View style={styles.sectionContainer}>
            <Text accessibilityRole='header' style={styles.sectionTitle}>
              {title}
            </Text>
          </View>
          <View style={styles.sectionContainer}>
            <TextInput
                style={{height: 30, borderWidth: 1}}
                keyboardType="phone-pad"
                onChangeText={ text => this.setState({text}) }
                value={this.state.text}

                {...accessibilityProps}
              />
          </View>
        </React.Fragment>
    )};

    return (
    <View >

        <View style={styles.body}>
        
          {/* ANDROID: Test Label, Edit Box */}
          {/* iOS: Test Label, Text Field, .. */}
          <Example title="Label Only" label />
          {/* ANDROID: One, Edit Box */}
          {/* iOS: Test Label, One, Text Field */}
          
          {/* ANDROID: Test Hint, Edit Box */}
          {/* iOS: Test Hint, Text Field, .. */}
          <Example title="Hint Only" hint />
          {/* ANDROID: One, Edit Box */}
          {/* iOS: One, Text Field, Test Hint .. */}
          
          {/* ANDROID: Test Placeholder, Edit Box */}
          {/* iOS: Test Placeholder, Text Field, .. */}
          <Example title="Placeholder Only" placeholder />
          {/* ANDROID: One, Edit Box, Test Placeholder */}
          {/* iOS: One, Text Field .. */}
          
          {/* ANDROID: Test Placeholder, Edit Box */}
          {/* iOS: Test Label, Test Placeholder, Text Field, .. */}
          <Example title="Label, Placeholder" label placeholder />
          {/* ANDROID: One, Edit Box, Test Placeholder */}
          {/* iOS: Test Label, One, Text Field .. */}
          
          {/* ANDROID: Test Label, Test Hint, Edit Box */}
          {/* iOS: Test Label, Text Field, Test Hint.. */}
          <Example title="Label, Hint" label hint />
          {/* ANDROID: One, Edit Box */}
          {/* iOS: Test Label, One, Text Field, Text Hint .. */}

          {/* ANDROID: Test Placeholder, Edit Box */}
          {/* iOS: Test Placeholder, Text Field, Test Hint.. */}
          <Example title="Hint, Placeholder" hint placeholder />
          {/* ANDROID: One, Edit Box, Test Placeholder */}
          {/* iOS: One, Text Field, Test Hint .. */}

          {/* ANDROID: Test Placeholder, Edit Box */}
          {/* iOS: Test Label, Test Placeholder, Text Field, Test Hint.. */}
          <Example title="Label, Hint, Placeholder Only" label hint placeholder />
          {/* ANDROID: One, Edit Box, Test Placeholder */}
          {/* iOS: Test Label, One, Text Field, Text Hint .. */}

        </View>
    </View>
  ); 
 }
}

const styles = StyleSheet.create({
  body: {
    padding: 48,
    backgroundColor: '#fff',
  },
  sectionContainer: {
    marginTop: 14,
    paddingHorizontal: 24,
  },
  sectionTitle: {
    fontSize: 14,
    fontWeight: '600',
    color: '#000',
  }
});

This is available as a Snack. This is on react-native 0.61 from the Expo 37 SDK, but we've confirmed this in vanilla 0.62.2 in house as well. Furthermore, even if I switch the Snack version to Expo 34, the issue still applies for Android.

Essentially however, the bug is that react-native completely ignores the label if there is either a value or placeholder specified on the field, and if there is not a placeholder specified but a value exists, it only reads the value.

tostringtheory avatar May 07 '20 23:05 tostringtheory

Just commenting that this is still a known issue for our company/app before stalebot comes in and yells at us.

Is there anyone on the react-native project that we should mention to pull them into this issue? Is there any further information needed besides the reproduction JSX/snack above?

tostringtheory avatar Jun 30 '20 21:06 tostringtheory

I used property accessibilityRole="none" for announce accessiblityLable in TextInput, but after that it will announce placeholder also. so we can handle it by check. here is my code -

export default class App extends Component<Props> {
  constructor(props) {
    super(props);
    this.state = {
      email: ''
    }
  }
render() {
    return (
            <TextInput
               placeholder={this.state.email.length > 0 ? ''" : "Enter email"}
               value={this.state.email}
              onChangeText={(text) => this.setState({email: text})}
              accessibilityRole="none"
              accessibilityLabel={this.state.email.length > 0 ? `your email is ${this.state.email}` : "Please enter your email"}
           /> 
    );
  }
}

Akanksha-Thakur avatar Jul 23 '20 07:07 Akanksha-Thakur

@Akanksha-Thakur - that's just meant to be a workaround right? It still seems to me that given the fact that it works (seemingly) correctly on 1 platform (iOS) that it should work correctly/reproducibly on either platform without having to conditionally render some of that information? It also seems hacky to specify that an interactive element has no accessibilityRole?

tostringtheory avatar Jul 23 '20 16:07 tostringtheory

@tostringtheory - accessibilityRole use for announce accessibilityLabel also and yes is it like a hacking code because I don't think there is any other way to shoutout this issue.

Akanksha-Thakur avatar Aug 13 '20 08:08 Akanksha-Thakur

I'm still able to reproduce it on react-native v0.61.5, is this fixed on the last version?

vitorandrietta avatar Sep 10 '20 03:09 vitorandrietta

This is a known issue for our company as well, and we just upgraded to 0.63.2. We rely on props like accessibilityLabel and accessibilityHint for our other components to bind extra context to our input elements, and this behavior is really problematic for us, especially with how important a basic text input is for a form experience. Shoving as much information as we want into a prop that does work, or setting accessibilityRole="none" is really not ideal -- is there any way we can get more visibility on this problem?

jychiao avatar Sep 10 '20 19:09 jychiao

This problem still persists after upgrading to RN 0.63.2.

smjurek avatar Oct 19 '20 08:10 smjurek

Bumping to keep topic alive so bot doesn't close this issue. Any news regarding this problem?

I'm currently working on accessibility for blind people, and they have a hard time understanding "Editing ... 38 29 18 83 ..." as a example.

Would be nice to have a working TextInput with a placeholder for visual indication, and an accessibilityLabel for the visually impaired.

HenrikDK2 avatar Dec 18 '20 01:12 HenrikDK2

@safaiyeh - I hate to directly ping a stranger into an issue, but it seems like this one went under the radar and was never triaged. No tags, nothing specified as needed, no maintainer input. I saw you recently in other issues triaging/reviewing, was hoping you could help bring some attention/tags to this issue to maybe get the ball rolling? If you're not the right person, who should I be trying to tag?

tostringtheory avatar Jan 30 '21 17:01 tostringtheory

Just wanted to bump this as this is now becoming a more urgent blocker for our application. One of the Android devs on our team took some time to dig and we think the underlying issue could be related to https://github.com/facebook/react-native/issues/30847, which has more promising tags. Is there someone who could confirm, deny, or at least take note to verify that this will get fixed in the near future? It would greatly motivate us to upgrade our RN as soon as a fix is included.

jychiao avatar Mar 22 '21 18:03 jychiao

@jychiao, @tostringtheory , @HenrikDK2 and others.

Sorry for the delay on this, I work on Android accessibility, and understand the root cause of this issue, but only recently started working with React Native, so I didn't know about this problem.

Unfortunately, the issue here is on Talkback's side and there isn't much that can be done in RN to resolve it directly, however we can work around the limitations that Talkback has. Let me explain how both iOS and Android work with text inputs, as they have some core differences that will make the problem a bit more clear.

On iOS with VoiceOver, when a text input is focused, VoiceOver will read the accessibilityLabel (if one exists), the accessibilityValue (if one exists and if not, the text input's actual value), and the accessibilityHint (if one exists). The placeholder, being visible text inside the input is the "value" portion of that announcement. Just like when a user enters text, it visibly overrides the placeholder, any entered text will override the placeholder in the announcement as well. iOS's behavior here is likely exactly what you expect when you see these three properties set on a text input.

Android on the other hand, is a bit different. On Android with Talkback, when a text input is focused, Talkback will read the text entered into the input (if any exists), then fallback to reading the placeholder if there us no entered text, and finally fall back to reading the contentDescription (Androids version of iOS's accessibilityLabel) if no entered text or placeholder exists. Because of this fallback behavior, you will never be able to have a text input on Android with both an accessibilityLabel and content inside of it (either placeholder or user entered).

This logic in Talkback is shown in the compositor.json file here:

https://github.com/google/talkback/blob/master/compositor/src/main/res/raw/compositor.json#L1510-L1512

That line $node.text is referencing any entered text into the input, and the "fallback" block around it is saying to try to read that first, and only if it's empty read the next line, which is $node.contentDescription.

So how does this impact accessibiltyHint you may ask? Well, accessibilityHint doesn't actually exist on Android. This is an iOS-specific property that React Native has polyfilled into Android by simply concatenating this string into the contentDescription. Since the contentDescription is ignored in the fallback behavior above, so is the accessibilityHint.

@Akanksha-Thakur posted a workaround above, and the reason this works is that by setting a role of "none" rather than the default role of "edit_text" you are bypassing talkback's edit-text-specific logic here. Unfortunately, that also means you are losing out on other edit-text-specific features, such as telling a user whether "editing mode" or "selection mode" is active.

Not all hope is lost however, as Android does have alternate ways to present this information in text inputs, but right now React Native doesn't yet support them. These approaches have issues open here (#30846) and here (#31056) if you are interested in helping improve RN's accessibility support.

In order to get something like iOS's "accessibiltyLabel" to work on text inputs in Android, RN will need to support Android's "labelFor" property. This is Android-specific and has no iOS counterpart. This property allows you to have one element act as a label for another, and in the example of text input, would allow an external element to label it even if it has content entered inside it. This is what that API could look like (psuedo-code), when built.

<Text labelFor={123}>First Name</Text>
<TextInput value="Brett" placeholder="Enter your first name" id={123}>

On focus, Talkback would announce "Brett, Edit Text for First Name".

To fix the accessibilityHint issue, we'll need to change how accessibilityHint works on Android, and rather than concatenating into the contentDescription instead add it elsewhere, such as the toolTipText property. TooltipText is another Android-specific feature, which is meant to contain text that is inside a tooltip pointing at an element. It can be used as a generic placeholder for secondary content about an element though, similar to iOS's AccessibilityHint. If we changed accessibilityHint to instead set toolTipText on Android, and had the following code:

<Text labelFor={123}>First Name</Text>
<TextInput value="Brett" placeholder="Enter your first name" id={123} accessibilityHint="Be sure not to enter any numbers or spaces.">

on focus Talkback would announce "Brett, Edit Text for First Name. Be sure not to enter any numbers or spaces."

This would be very close to iOS's behavior, missing only the 500ms pause before the accessibilityHint (which is already missing on Android).

I know this was a long comment, but I want to make sure the issue is well understood here, and that it's clear that this isn't a straightforward fix. If anyone wants to work on the two issues I mentioned in order to add support here, I'd be happy to review any and all PRs!

blavalla avatar Mar 23 '21 00:03 blavalla

@blavalla based on your comment, I tried adding support for the labelFor [Android] property in react native. Here are some of my findings and issues I ran into.

In native android, by using the labelFor property of TextViews can be a label for an EditText causing the talkback agent to announce the label text as well.

<TextView android:layout_width="0dp" 
android:layout_height="0dp"
android:labelFor="@+id/edit_item_name"
android:text="Email address" />

<EditText android:id="@+id/edit_item_name" 
android:layout_width="match_parent" 
android:layout_height="wrap_content" />

So, if the edittext is tapped, the talkback would also announce “Edit text for Email address”.

On React native, to add support for the labelFor property: https://github.com/gaurav-jayasawal/react-native/commit/5d31d4f4f264671786b3199b02bb3df1a11d4b1d

There were 2 main things required for this to work:

  1. Set a view id to the EditText for which we need a label
  2. Set this view id in the labelFor property of the label TextView.

View ids to set to EditTexts should be identifiable and more importantly, it has to be a @IDRes integer type, which needs to be added to a predefined ids.xml file.

Problems: Problem 1: RN does not directly support Android view ids. Any form of id props like testID or nativeID use android tags, which cannot be used with the labelFor property. Adding support for view ids got complicated as it needed to be of a @IDRes type. Generating this id dynamically is possible using View.generateViewId(), but this did not work as these dynamic ids were not mentioned in the ids.xml file which seems crucial for react native to use as a @IDRes type. Hardcoding pre-defined view ids in the file and using that as ids worked, but that would not be scalable.

Problem 2: Another major issue is when the accessibilityLabel is set on a TextInput, android assigns it a constant id “accessibility_label” and that would mean that the id property that we set would overwrite this id and cause issues with RN's accessibility logic.

gaurav-jayasawal avatar Apr 13 '21 17:04 gaurav-jayasawal

@gaurav-jayasawal , thanks for investigating! So you're right that the API that Android provides relies on IDs being set, but under the hood these IDs are only used to point to a view itself and are not used for any other purpose. Talkback (or other accessibility services), never even gets a reference to the ID you set, it will only get a reference to the view that has that ID. This means that we could use some other other mechanism to get that view reference, which we could pass along to Talkback. So for example, we could use a viewTag (like we do for other accessibility properties), and then find that view based on the tag.

For some context, here is how the system is working under the hood.

  1. You set an ID in the labelFor property of some TextView, and that same ID on some EditText you want to have be labelled.
  2. When that EditText is rendered, and its AccessibilityNodeInfo is generated, it does a search with its own ID up and down the tree to try to see if any other element has that same ID set on its labelFor property.
  3. If it finds a View in step 2, it sets a reference to the View itself as the AccessibilityNodeInfo's "labeledBy" property.
  4. Talkback parses this labeledBy property when you focus on an element, and parses the label of the view it points to to be presented to the user.

Here are code pointers for all of the above:

Finding the element:

  1. https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/view/View.java;l=10095?q=findLabelForView
  2. https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/view/View.java;drc=master;l=10318?q=findLabelForView
  3. https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/view/View.java;l=25042;drc=master?q=findLabelForView

Setting the view reference on the node info: https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/view/View.java;l=10097?q=findLabelForView

Talkback finding this node based on the view reference: https://github.com/google/talkback/blob/92eb6dd4461e53fc904052b7fbe9b77ddfbf930a/compositor/src/main/java/NodeVariables.java#L494

Talkback using this node for the description: https://github.com/google/talkback/blob/master/compositor/src/main/res/raw/compositor.json#L1064

Since all of this work happens in the base View class, and we are already overriding much of that functionality in BaseViewManager, including setting an AccessibilityDelegate (ReactAccessibilityDelegate) all we should need to do here is:

  1. Set the nativeID on the element you want to be labelled, and set the labelFor property to this same ID.
  2. Add a new findView() variant in ReactFindViewUtil that uses the labelFor tag in its search rather than nativeID tag.
  3. In the onInitializeAccessibilityNodeInfo method of the ReactAccessibilityDelegate if you see that a view has a nativeId set (which means another view might be labelling it) call the new findView method to see if you can find another view that has this same ID in its labelFor property.
  4. If a view is found, call setLabelledBy on the AccessibilityNodeInfo, and pass it in.

That is just one approach that would work here. We could also flip this API around, and instead have it be called "labeledBy" and have it set on the Input itself, which might make some of this more efficient overall, as we wouldn't need to search for a view unless we knew we'd want to use it as a label. Either way, as long as the AccessibilityNodeInfo gets a view reference set on its "labelledBy" property, it'll all work once it gets to Talkback.

Thanks again for looking into this, let me know if any of the above needs any clarification!

blavalla avatar Apr 14 '21 01:04 blavalla

Any updates on this?

frags51 avatar Aug 29 '21 09:08 frags51

Hey there, it looks like there has been no activity on this issue recently. Has the issue been fixed, or does it still require the community's attention? This issue may be closed if no further activity occurs. You may also label this issue as a "Discussion" or add it to the "Backlog" and I will leave it open. Thank you for your contributions.

stale[bot] avatar Jan 09 '22 13:01 stale[bot]

any updates on this? same issue here

rveruna avatar Jul 28 '22 17:07 rveruna

Hi @blavalla

Do you know if the fix mentioned below is being implemented? The accessibilityHint not being announced by TalkBack when a field has a value or placeholder is still an issue.

To fix the accessibilityHint issue, we'll need to change how accessibilityHint works on Android, and rather than concatenating into the contentDescription instead add it elsewhere, such as the toolTipText property. TooltipText is another Android-specific feature, which is meant to contain text that is inside a tooltip pointing at an element. It can be used as a generic placeholder for secondary content about an element though, similar to iOS's AccessibilityHint. If we changed accessibilityHint to instead set toolTipText on Android, and had the following code:

<Text labelFor={123}>First Name</Text> <TextInput value="Brett" placeholder="Enter your first name" id={123} accessibilityHint="Be sure not to enter any numbers or spaces."> on focus Talkback would announce "Brett, Edit Text for First Name. Be sure not to enter any numbers or spaces."

This would be very close to iOS's behavior, missing only the 500ms pause before the accessibilityHint (which is already missing on Android).

nedgip avatar Mar 25 '23 03:03 nedgip

I just came across this issue when writing some tests for an app. I'm utilizing Appium with WebdriverIO on iOS. When inspecting my elements with Appium Inspector I am able to see that changing the multiline prop on the <TextInput /> causes this issue to occur. I hadn't hit this issue until developing a test on a page that includes a TextInput with this prop set to true.

When multiline = true the placeholder text is appended to the accessibility label. When multiline = false this does not occur in my environment. As soon as text is added or the input is focused, the accessibility label adjusts to the correct value and the placeholder text is removed.

I'm assuming this happens because the TextInput node creates a Text components when a placeholder exists and its accessibilityLabel is equal to the text itself. This ends up bubbling up to the Input and appends to the accessibilityLabel of the TextInput. I guess I need to make my own placeholder TextView to prevent this bubbling of the accessibility label. Not sure why it only happens with multiline though.

RN 68.2 Appium v2.0.0 wdio 8.11.2

tristanheilman avatar Aug 16 '23 15:08 tristanheilman

This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 7 days.

github-actions[bot] avatar Feb 13 '24 05:02 github-actions[bot]

This issue was closed because it has been stalled for 7 days with no activity.

github-actions[bot] avatar Feb 20 '24 05:02 github-actions[bot]