Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,7 @@ enum class ApplicationWorkflow {

/** A workflow to launch delete draft questionnaires */
DELETE_DRAFT_QUESTIONNAIRE,

/** A workflow that opens URL in external app (browser, email, etc.) */
OPEN_URL,
}
10 changes: 10 additions & 0 deletions android/engine/src/main/res/drawable/ic_feedback.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M480,600Q497,600 508.5,588.5Q520,577 520,560Q520,543 508.5,531.5Q497,520 480,520Q463,520 451.5,531.5Q440,543 440,560Q440,577 451.5,588.5Q463,600 480,600ZM440,440L520,440L520,200L440,200L440,440ZM80,880L80,160Q80,127 103.5,103.5Q127,80 160,80L800,80Q833,80 856.5,103.5Q880,127 880,160L880,640Q880,673 856.5,696.5Q833,720 800,720L240,720L80,880ZM206,640L800,640Q800,640 800,640Q800,640 800,640L800,160Q800,160 800,160Q800,160 800,160L160,160Q160,160 160,160Q160,160 160,160L160,685L206,640ZM160,640L160,640L160,160Q160,160 160,160Q160,160 160,160L160,160Q160,160 160,160Q160,160 160,160L160,640Q160,640 160,640Q160,640 160,640Z"/>
</vector>
22 changes: 22 additions & 0 deletions android/quest/src/main/assets/configs/app/navigation_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,28 @@
}
]
},
{
"id": "feedback",
"visible": true,
"display": "Feedback",
"menuIconConfig": {
"type": "local",
"reference": "ic_feedback"
},
"actions": [
{
"trigger": "ON_CLICK",
"workflow": "OPEN_URL",
"id": "openFeedback",
"params": [
{
"key": "url",
"value": "https://ona.io/home/"
}
]
}
]
},
{
"id": "settings",
"visible": true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.runtime.snapshots.SnapshotStateMap
import androidx.core.content.ContextCompat
import androidx.core.net.toUri
import androidx.core.os.bundleOf
import androidx.navigation.NavController
import androidx.navigation.NavOptions
Expand Down Expand Up @@ -245,6 +246,18 @@ fun ActionConfig.handleClickEvent(
)
navController.navigate(MainNavigationScreen.AlertDialogFragment.route, args)
}
ApplicationWorkflow.OPEN_URL -> {
val url = interpolatedParams.find { it.key == "url" }?.value
if (!url.isNullOrBlank()) {
try {
val intent = Intent(Intent.ACTION_VIEW, url.toUri())
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
ContextCompat.startActivity(navController.context, intent, null)
} catch (e: Exception) {
context?.showToast("Unable to open url ${e.message}", Toast.LENGTH_SHORT)
Copy link

Copilot AI Sep 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message exposes the raw exception message to users, which may contain technical details that are confusing. Consider using a more user-friendly message like 'Unable to open the URL. Please check the link and try again.'

Suggested change
context?.showToast("Unable to open url ${e.message}", Toast.LENGTH_SHORT)
context?.showToast("Unable to open the URL. Please check the link and try again.", Toast.LENGTH_SHORT)

Copilot uses AI. Check for mistakes.
Comment on lines +252 to +257
Copy link

Copilot AI Sep 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The URL is not validated before being passed to the intent. This could allow malicious URLs to be opened. Consider validating the URL scheme (e.g., only allow http/https) or implementing a URL whitelist to prevent potential security issues.

Suggested change
try {
val intent = Intent(Intent.ACTION_VIEW, url.toUri())
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
ContextCompat.startActivity(navController.context, intent, null)
} catch (e: Exception) {
context?.showToast("Unable to open url ${e.message}", Toast.LENGTH_SHORT)
val uri = Uri.parse(url)
val scheme = uri.scheme?.lowercase()
if (scheme == "http" || scheme == "https") {
try {
val intent = Intent(Intent.ACTION_VIEW, uri)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
ContextCompat.startActivity(navController.context, intent, null)
} catch (e: Exception) {
context?.showToast("Unable to open url ${e.message}", Toast.LENGTH_SHORT)
}
} else {
context?.showToast("Invalid or unsupported URL scheme", Toast.LENGTH_SHORT)

Copilot uses AI. Check for mistakes.
}
}
}
else -> return
}
}
Expand Down
Loading