Skip to content

Commit f38163c

Browse files
authored
feat: implement desktop file sharing and mail functionality (#643)
1 parent c80624b commit f38163c

File tree

1 file changed

+80
-2
lines changed

1 file changed

+80
-2
lines changed

composeApp/src/desktopMain/kotlin/org/ooni/probe/BuildDependencies.kt

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.ooni.probe
22

33
import androidx.datastore.preferences.core.PreferenceDataStoreFactory
4+
import co.touchlab.kermit.Logger
45
import dev.dirs.ProjectDirectories
56
import kotlinx.coroutines.CoroutineScope
67
import kotlinx.coroutines.Dispatchers
@@ -21,7 +22,11 @@ import org.ooni.probe.data.models.RunSpecification
2122
import org.ooni.probe.di.Dependencies
2223
import org.ooni.probe.shared.Platform
2324
import org.ooni.probe.shared.PlatformInfo
25+
import java.awt.Desktop
2426
import java.io.File
27+
import java.net.URI
28+
import java.net.URLEncoder
29+
import java.nio.charset.StandardCharsets
2530

2631
private val projectDirectories = ProjectDirectories.from("org", "OONI", "Probe")
2732

@@ -97,8 +102,81 @@ private fun startDescriptorsUpdate(descriptors: List<InstalledTestDescriptorMode
97102
}
98103

99104
private fun launchAction(action: PlatformAction): Boolean {
100-
// TODO: Desktop - launchAction
101-
return true
105+
return when (action) {
106+
is PlatformAction.FileSharing -> shareFile(action)
107+
is PlatformAction.Mail -> sendMail(action)
108+
is PlatformAction.OpenUrl -> openUrl(action)
109+
is PlatformAction.Share -> shareText(action)
110+
PlatformAction.VpnSettings -> openVpnSettings()
111+
}
112+
}
113+
114+
fun openVpnSettings(): Boolean {
115+
return false
116+
}
117+
118+
fun shareText(action: PlatformAction.Share): Boolean {
119+
return try {
120+
if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.MAIL)) {
121+
val uri = URI.create("mailto:?body=${URLEncoder.encode(action.text, StandardCharsets.UTF_8)}")
122+
Desktop.getDesktop().mail(uri)
123+
true
124+
} else {
125+
false
126+
}
127+
} catch (e: Exception) {
128+
Logger.e(e) { "Failed to share text" }
129+
false
130+
}
131+
}
132+
133+
fun shareFile(action: PlatformAction.FileSharing): Boolean {
134+
return try {
135+
if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.APP_OPEN_FILE)) {
136+
val file = projectDirectories.dataDir.toPath().resolve(action.filePath).toFile()
137+
if (!file.exists()) {
138+
Logger.w("File to share does not exist: $file")
139+
return false
140+
}
141+
Desktop.getDesktop().open(file)
142+
true
143+
} else {
144+
false
145+
}
146+
} catch (e: Exception) {
147+
Logger.e(e) { "Failed to share file" }
148+
false
149+
}
150+
}
151+
152+
fun openUrl(action: PlatformAction.OpenUrl): Boolean {
153+
if (Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) {
154+
Desktop.getDesktop().browse(URI(action.url))
155+
return true
156+
} else {
157+
return false
158+
}
159+
}
160+
161+
fun sendMail(action: PlatformAction.Mail): Boolean {
162+
return try {
163+
if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.MAIL)) {
164+
val mailUri = buildMailUri(action)
165+
Desktop.getDesktop().mail(mailUri)
166+
true
167+
} else {
168+
false
169+
}
170+
} catch (e: Exception) {
171+
Logger.e(e) { "Failed to send mail" }
172+
false
173+
}
174+
}
175+
176+
private fun buildMailUri(action: PlatformAction.Mail): URI {
177+
val subject = URLEncoder.encode(action.subject, StandardCharsets.UTF_8).replace("+", "%20")
178+
val body = URLEncoder.encode(action.body, StandardCharsets.UTF_8).replace("+", "%20").replace("%0A", "%0D%0A")
179+
return URI("mailto:${action.to}?subject=$subject&body=$body")
102180
}
103181

104182
private fun isWebViewAvailable(): Boolean {

0 commit comments

Comments
 (0)