Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions packages/pluggableWidgets/feedback-native/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

## [Unreleased]

### Added

- Translation support for all widget text through configurable properties in Studio Pro.
- Visible label above feedback input field to ensure WCAG compliance.

### Fixed

- Fixed logo overlap issue where custom logo appeared on top of default icon instead of replacing it.

## [3.4.0] - 2025-3-31

### Changed
Expand Down
2 changes: 1 addition & 1 deletion packages/pluggableWidgets/feedback-native/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "feedback-native",
"widgetName": "Feedback",
"version": "3.4.0",
"version": "3.4.1",
"license": "Apache-2.0",
"repository": {
"type": "git",
Expand Down
44 changes: 29 additions & 15 deletions packages/pluggableWidgets/feedback-native/src/Feedback.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,17 @@ export class Feedback extends Component<FeedbackProps<FeedbackStyle>, State> {
return this.state.status === "initial" ? (
<View style={floatingButtonContainer(this.state.deviceHeight)}>
<View style={this.styles.floatingButton}>
<TouchableOpacity onPress={this.onFeedbackButtonPressHandler} testID={`${this.props.name}$button`}>
<TouchableOpacity
onPress={this.onFeedbackButtonPressHandler}
testID={`${this.props.name}$button`}
accessibilityRole="button"
accessibilityLabel={this.props.accessibilityLabelFeedbackButton?.value ?? "Open feedback form"}
>
{this.props.logo && this.props.logo.value ? (
<Image style={imageStyle as StyleProp<SvgImageStyle>} source={this.props.logo.value} />
) : null}
<RNImage style={imageStyle} source={commentIcon} />
) : (
<RNImage style={imageStyle} source={commentIcon} />
)}
</TouchableOpacity>
</View>
</View>
Expand All @@ -120,19 +126,27 @@ export class Feedback extends Component<FeedbackProps<FeedbackStyle>, State> {
}}
{...this.dialogContainerProps}
>
<Dialog.Title style={this.styles.title}>Send Feedback</Dialog.Title>
<Dialog.Title style={this.styles.title}>
{this.props.titleSendFeedback?.value ?? "Send Feedback"}
</Dialog.Title>
<Text style={{ marginTop: 12, marginBottom: 8, fontSize: 14 }}>
Comment thread
stelselim marked this conversation as resolved.
{this.props.labelFeedbackInput?.value ?? "Type your feedback here"}
</Text>
<TextInput
testID={`${this.props.name}$input`}
multiline
style={this.processedStyles.textAreaInputStyles}
value={this.state.feedbackMessage}
onChangeText={this.onChangeTextHandler}
placeholder="Type your feedback here"
placeholder={this.props.placeholderFeedback?.value ?? "Type your feedback here"}
accessibilityLabel={this.props.labelFeedbackInput?.value ?? "Type your feedback here"}
{...this.processedStyles.textAreaInputProps}
/>
{this.props.allowScreenshot && (
<View style={switchContainer}>
<Text style={this.styles.switchLabel}>Include Screenshot</Text>
<Text style={this.styles.switchLabel}>
{this.props.labelIncludeScreenshot?.value ?? "Include Screenshot"}
</Text>
<Switch
testID={`${this.props.name}$switch`}
style={this.processedStyles.switchInputStyles}
Expand All @@ -144,13 +158,13 @@ export class Feedback extends Component<FeedbackProps<FeedbackStyle>, State> {
</View>
)}
<Dialog.Button
label="Cancel"
label={this.props.buttonCancel?.value ?? "Cancel"}
color={this.styles.button.color}
onPress={this.onCancelHandler}
testID={`${this.props.name}$cancel`}
/>
<Dialog.Button
label="Send"
label={this.props.buttonSend?.value ?? "Send"}
disabled={disabled}
color={sendButtonColor}
onPress={this.onSendHandler}
Expand All @@ -163,7 +177,7 @@ export class Feedback extends Component<FeedbackProps<FeedbackStyle>, State> {
private renderInProgressDialog(): JSX.Element {
return (
<Dialog.Container visible={this.state.status === "inprogress"} {...this.dialogContainerProps}>
<Dialog.Title style={this.styles.title}>Sending...</Dialog.Title>
<Dialog.Title style={this.styles.title}>{this.props.titleSending?.value ?? "Sending..."}</Dialog.Title>
<ActivityIndicator
color={this.styles.activityIndicator.color}
size="large"
Expand All @@ -176,12 +190,12 @@ export class Feedback extends Component<FeedbackProps<FeedbackStyle>, State> {
private renderDoneDialog(): JSX.Element {
return (
<Dialog.Container visible={this.state.status === "done"} {...this.dialogContainerProps}>
<Dialog.Title style={this.styles.title}>Result</Dialog.Title>
<Dialog.Title style={this.styles.title}>{this.props.titleResult?.value ?? "Result"}</Dialog.Title>
<Dialog.Description style={this.processedStyles.descriptionStyle} testID={`${this.props.name}$success`}>
Feedback successfully sent
{this.props.messageSuccess?.value ?? "Feedback successfully sent"}
</Dialog.Description>
<Dialog.Button
label="OK"
label={this.props.buttonOk?.value ?? "OK"}
onPress={this.onCancelHandler}
color={this.styles.button.color}
testID={`${this.props.name}$success$ok`}
Expand All @@ -193,12 +207,12 @@ export class Feedback extends Component<FeedbackProps<FeedbackStyle>, State> {
private renderErrorDialog(): JSX.Element {
return (
<Dialog.Container visible={this.state.status === "error"} {...this.dialogContainerProps}>
<Dialog.Title style={this.styles.title}>Result</Dialog.Title>
<Dialog.Title style={this.styles.title}>{this.props.titleResult?.value ?? "Result"}</Dialog.Title>
<Dialog.Description style={this.processedStyles.descriptionStyle} testID={`${this.props.name}$error`}>
Error sending feedback
{this.props.messageError?.value ?? "Error sending feedback"}
</Dialog.Description>
<Dialog.Button
label="OK"
label={this.props.buttonOk?.value ?? "OK"}
onPress={this.onCancelHandler}
color={this.styles.button.color}
testID={`${this.props.name}$error$ok`}
Expand Down
125 changes: 109 additions & 16 deletions packages/pluggableWidgets/feedback-native/src/Feedback.xml
Original file line number Diff line number Diff line change
@@ -1,24 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8" ?>
<widget id="com.mendix.widget.native.feedback.Feedback" supportedPlatform="Native" needsEntityContext="true" offlineCapable="true" pluginWidget="true" xmlns="http://www.mendix.com/widget/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mendix.com/widget/1.0/ ../../../node_modules/mendix/custom_widget.xsd">
<name>Feedback</name>
<description>Allow users to submit feedback directly into the app project.</description>
<studioProCategory>Add-ons</studioProCategory>
<studioCategory>Add-ons</studioCategory>
<properties>
<property key="sprintrapp" type="string">
<caption>App ID</caption>
<category>General</category>
<description>The App ID is a hash that uniquely identifies your app project. You can find this ID in Settings > General in the Developer Portal.</description>
</property>
<property key="allowScreenshot" type="boolean" defaultValue="true">
<caption>Allow screenshots</caption>
<category>General</category>
<description>If you are not allowed to send screenshots when submitting feedback for legal reasons, set this to ‘No’.</description>
</property>
<property key="logo" type="image" required="false">
<caption>Logo</caption>
<category>General</category>
<description>For customized branding, add a logo to the widget. The recommended size of the image is 90 by 90 pixels.</description>
</property>
<propertyGroup caption="General">
<property key="sprintrapp" type="string">
<caption>App ID</caption>
<description>The App ID is a hash that uniquely identifies your app project. You can find this ID in Settings > General in the Developer Portal.</description>
</property>
<property key="allowScreenshot" type="boolean" defaultValue="true">
<caption>Allow screenshots</caption>
<description>If you are not allowed to send screenshots when submitting feedback for legal reasons, set this to ‘No’.</description>
</property>
<property key="logo" type="image" required="false">
<caption>Logo</caption>
<description>For customized branding, add a logo to the widget. The recommended size of the image is 90 by 90 pixels.</description>
</property>
</propertyGroup>
<propertyGroup caption="Localization">
<propertyGroup caption="Dialog Titles">
<property key="titleSendFeedback" type="textTemplate" required="false">
<caption>Send feedback title</caption>
<description>Title shown when composing feedback</description>
<translations>
<translation lang="en_US">Send Feedback</translation>
</translations>
</property>
<property key="titleSending" type="textTemplate" required="false">
<caption>Sending title</caption>
<description>Title shown while sending feedback</description>
<translations>
<translation lang="en_US">Sending...</translation>
</translations>
</property>
<property key="titleResult" type="textTemplate" required="false">
<caption>Result title</caption>
<description>Title shown in result dialogs (success/error)</description>
<translations>
<translation lang="en_US">Result</translation>
</translations>
</property>
</propertyGroup>
<propertyGroup caption="Input Labels">
<property key="labelFeedbackInput" type="textTemplate" required="false">
<caption>Feedback input label</caption>
<description>Visible label shown above the feedback text field</description>
<translations>
<translation lang="en_US">Type your feedback here</translation>
</translations>
</property>
<property key="placeholderFeedback" type="textTemplate" required="false">
<caption>Feedback placeholder</caption>
<description>Placeholder text for feedback input field</description>
<translations>
<translation lang="en_US">Type your feedback here</translation>
</translations>
</property>
<property key="labelIncludeScreenshot" type="textTemplate" required="false">
<caption>Screenshot label</caption>
<description>Label for screenshot toggle switch</description>
<translations>
<translation lang="en_US">Include Screenshot</translation>
</translations>
</property>
</propertyGroup>
<propertyGroup caption="Buttons">
<property key="buttonCancel" type="textTemplate" required="false">
<caption>Cancel button</caption>
<description>Label for cancel button</description>
<translations>
<translation lang="en_US">Cancel</translation>
</translations>
</property>
<property key="buttonSend" type="textTemplate" required="false">
<caption>Send button</caption>
<description>Label for send button</description>
<translations>
<translation lang="en_US">Send</translation>
</translations>
</property>
<property key="buttonOk" type="textTemplate" required="false">
<caption>OK button</caption>
<description>Label for OK button in result dialogs</description>
<translations>
<translation lang="en_US">OK</translation>
</translations>
</property>
<property key="accessibilityLabelFeedbackButton" type="textTemplate" required="false">
<caption>Feedback button accessibility label</caption>
<description>Label announced by screen readers for the feedback button (not visible on screen)</description>
<translations>
<translation lang="en_US">Open feedback form</translation>
</translations>
</property>
</propertyGroup>
<propertyGroup caption="Messages">
<property key="messageSuccess" type="textTemplate" required="false">
<caption>Success message</caption>
<description>Message shown when feedback is sent successfully</description>
<translations>
<translation lang="en_US">Feedback successfully sent</translation>
</translations>
</property>
<property key="messageError" type="textTemplate" required="false">
<caption>Error message</caption>
<description>Message shown when feedback fails to send</description>
<translations>
<translation lang="en_US">Error sending feedback</translation>
</translations>
</property>
</propertyGroup>
</propertyGroup>
</properties>
</widget>
Loading
Loading