Skip to content
Merged
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 @@ -387,13 +387,15 @@ class MethodHandler : FlutterPlugin,
val device = map["device"] as String? ?: ""
val model = map["model"] as String? ?: ""
val logFilePath = map["logFilePath"] as String? ?: ""
val attachmentsJson = reportIssueAttachmentsJson(map["attachments"])
Mobile.reportIssue(
email,
issueType,
description,
device,
model,
logFilePath
logFilePath,
attachmentsJson
)
withContext(Dispatchers.Main) {
success("ok")
Expand Down Expand Up @@ -1325,6 +1327,21 @@ private fun writeAppIconToCache(ctx: Context, packageName: String): String {
return file.absolutePath
}

private fun reportIssueAttachmentsJson(raw: Any?): String {
val attachments = raw as? List<*> ?: emptyList<Any?>()
val arr = JSONArray()
attachments.forEach { item ->
val attachment = item as? Map<*, *> ?: return@forEach
arr.put(JSONObject().apply {
put("name", attachment["name"] as? String ?: "")
put("path", attachment["path"] as? String ?: "")
put("mimeType", attachment["mimeType"] as? String ?: "")
put("sizeBytes", (attachment["sizeBytes"] as? Number)?.toLong() ?: 0L)
})
}
return arr.toString()
}

private fun drawableToBitmap(drawable: Drawable): Bitmap {
if (drawable is BitmapDrawable && drawable.bitmap != null) return drawable.bitmap
val w = drawable.intrinsicWidth.coerceAtLeast(1)
Expand Down
24 changes: 24 additions & 0 deletions assets/locales/en.po
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,30 @@ msgstr "Settings"
msgid "report_an_issue"
msgstr "Report an Issue"

msgid "report_issue_add_screenshots"
msgstr "Add screenshots"

msgid "report_issue_screenshot_helper"
msgstr "PNG, JPG, or GIF — 15 MB max total"

msgid "report_issue_add_images"
msgstr "Add images"

msgid "report_issue_attachments_unsupported_type"
msgstr "Only PNG, JPG, and GIF images are supported."

msgid "report_issue_attachments_too_many"
msgstr "You can attach up to 3 images."

msgid "report_issue_attachments_total_size_exceeded"
msgstr "Attachments must stay under 15 MB total."

msgid "report_issue_attachments_duplicate"
msgstr "That image is already attached."

msgid "report_issue_attachments_unreadable"
msgstr "We could not read one of those files."

msgid "lantern_projects"
msgstr "Lantern Projects:"

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ replace github.com/quic-go/qpack => github.com/quic-go/qpack v0.5.1
require (
github.com/alecthomas/assert/v2 v2.3.0
github.com/getlantern/lantern-server-provisioner v0.0.0-20251031121934-8ea031fccfa9
github.com/getlantern/radiance v0.0.0-20260507173456-dad58a121727
github.com/getlantern/radiance v0.0.0-20260507175635-a63194a7c5af
github.com/sagernet/sing-box v1.12.22
golang.org/x/mobile v0.0.0-20250711185624-d5bb5ecc55c0
golang.org/x/sys v0.41.0
Expand Down
8 changes: 6 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,10 @@ github.com/getlantern/algeneva v0.0.0-20250307163401-1824e7b54f52 h1:w2/RqYPw7Pb
github.com/getlantern/algeneva v0.0.0-20250307163401-1824e7b54f52/go.mod h1:PrNR8tMXO26YNs8K9653XCUH7u2Kv4OdfFC3Ke1GsX0=
github.com/getlantern/amp v0.0.0-20260305201851-782bc8045e58 h1:3wxMKw90adxiEzsJmAmMHqBJQr/P/9Goqy/U2a1l/sg=
github.com/getlantern/amp v0.0.0-20260305201851-782bc8045e58/go.mod h1:p6WdG48YAz5SCUpiMSGLy616A6YghKToc63y3NP7avI=
github.com/getlantern/broflake v0.0.0-20260421172440-caea0799b63a h1:WQ11Ms5jGvBaH6v/u1QBvmnnzRY0ckMiifCnDM/x6TI=
github.com/getlantern/broflake v0.0.0-20260421172440-caea0799b63a/go.mod h1:bZGGfTwne9NIsy3Kc1avcXNWn/yA8ghUwlXdS2z+AlA=
github.com/getlantern/broflake v0.0.0-20260501210609-ce5f75aa2054 h1:nrRMiRRjzR43yihrVxdnmmt66ZqjRhHE73TyHW1ySgg=
github.com/getlantern/broflake v0.0.0-20260501210609-ce5f75aa2054/go.mod h1:bZGGfTwne9NIsy3Kc1avcXNWn/yA8ghUwlXdS2z+AlA=
github.com/getlantern/broflake v0.0.0-20260504215251-ed3cf75062d1 h1:3WYvObOo8gpKwjcLrV6O/vRp+ubKdjpvJwZrRkbbDWw=
github.com/getlantern/broflake v0.0.0-20260504215251-ed3cf75062d1/go.mod h1:bZGGfTwne9NIsy3Kc1avcXNWn/yA8ghUwlXdS2z+AlA=
github.com/getlantern/common v1.2.1-0.20260326210434-cb69537aaf46 h1:Ab2esudqgFz2K1WYQKtX+58kaiVMX0UohjW2XmdEgf4=
Expand Down Expand Up @@ -261,8 +265,8 @@ github.com/getlantern/pluriconfig v0.0.0-20251126214241-8cc8bc561535 h1:rtDmW8YL
github.com/getlantern/pluriconfig v0.0.0-20251126214241-8cc8bc561535/go.mod h1:WKJEdjMOD4IuTRYwjQHjT4bmqDl5J82RShMLxPAvi0Q=
github.com/getlantern/publicip v0.0.0-20260328175246-2c460fe80c6b h1:gMYJzEhLrmIqQ+JnjiYNm+UyUDalK3WUmVyecFwmV5g=
github.com/getlantern/publicip v0.0.0-20260328175246-2c460fe80c6b/go.mod h1:NpfXdK4ldEKkjQ4P1R+DBF4ua5VFOlxmgHROTnYrApg=
github.com/getlantern/radiance v0.0.0-20260507173456-dad58a121727 h1:YJB2XYsEXdp/unsj/gSBiIvaQPyWqMNUZQSw7Vkscy4=
github.com/getlantern/radiance v0.0.0-20260507173456-dad58a121727/go.mod h1:oBXKRBE6qxdBmxnjV9NI3CSOSy4zDlm1f7haUVWpwBQ=
github.com/getlantern/radiance v0.0.0-20260507175635-a63194a7c5af h1:3nAaW6knhgnaTTg4qLCx3aXAiUdyfCzPOFYPKkDM1Gk=
github.com/getlantern/radiance v0.0.0-20260507175635-a63194a7c5af/go.mod h1:oBXKRBE6qxdBmxnjV9NI3CSOSy4zDlm1f7haUVWpwBQ=
github.com/getlantern/samizdat v0.0.3-0.20260327203406-ef7323341974 h1:k+/qNo5YNO+8M8LVUp6G5Evm1OQdEs3Z4ye8top4AhI=
github.com/getlantern/samizdat v0.0.3-0.20260327203406-ef7323341974/go.mod h1:uEeykQSW2/6rTjfPlj3MTTo59poSHXfAHTGgzYDkbr0=
github.com/getlantern/semconv v0.0.0-20260327040646-21845dda05cb h1:c5YM7b3a4r2J8Eh89KkI6M/iTFe6Bi+b8AJlfkKdFq4=
Expand Down
23 changes: 22 additions & 1 deletion ios/Runner/Handlers/MethodHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1006,9 +1006,20 @@ class MethodHandler {
let device = data["device"] as? String ?? ""
let model = data["model"] as? String ?? ""
let logFilePath = data["logFilePath"] as? String ?? ""
let attachments = data["attachments"] as? [[String: Any]] ?? []
let attachmentsJSON = reportIssueAttachmentsJSON(attachments)

var error: NSError?
MobileReportIssue(email, issueType, description, device, model, logFilePath, &error)
MobileReportIssue(
email,
issueType,
description,
device,
model,
logFilePath,
attachmentsJSON,
&error
)
if let error {
await self.handleFlutterError(error, result: result, code: "REPORT_ISSUE_ERROR")
return
Expand All @@ -1019,6 +1030,16 @@ class MethodHandler {
}
}

private func reportIssueAttachmentsJSON(_ attachments: [[String: Any]]) -> String {
guard JSONSerialization.isValidJSONObject(attachments),
let data = try? JSONSerialization.data(withJSONObject: attachments),
let json = String(data: data, encoding: .utf8)
else {
return "[]"
}
return json
}

func diagnosticLogFiles(result: @escaping FlutterResult) {
Task {
let logDirectory = FilePath.logsDirectory
Expand Down
15 changes: 12 additions & 3 deletions lantern-core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/getlantern/lantern/lantern-core/apps"
privateserver "github.com/getlantern/lantern/lantern-core/private-server"
"github.com/getlantern/lantern/lantern-core/utils"
"github.com/getlantern/lantern/lantern-core/utils/reportissue"
"github.com/getlantern/lantern/lantern-core/vpn_tunnel"
)

Expand Down Expand Up @@ -53,7 +54,9 @@ var (

type App interface {
AvailableFeatures() []byte
ReportIssue(email, issueType, description, device, model, logFilePath string) error
ReportIssue(
email, issueType, description, device, model, logFilePath, attachmentsJSON string,
) error
IsRadianceConnected() bool
IsVPNRunning() (bool, error)
GetAvailableServers() []byte
Expand Down Expand Up @@ -659,7 +662,7 @@ func (lc *LanternCore) GetEnabledApps() (string, error) {
// Issue Report //
/////////////////

func (lc *LanternCore) ReportIssue(email, issueType, description, device, model, logFilePath string) error {
func (lc *LanternCore) ReportIssue(email, issueType, description, device, model, logFilePath, attachmentsJSON string) error {
it := parseIssueType(issueType)
var attachments []string
// Windows + Linux have separate UI and daemon logDirs, so the daemon's
Expand All @@ -673,7 +676,13 @@ func (lc *LanternCore) ReportIssue(email, issueType, description, device, model,
if logFilePath != "" {
attachments = append(attachments, logFilePath)
}
return lc.client.ReportIssue(lc.ctx, it, description, email, attachments)

firstClassAttachments, err := reportissue.LoadAttachments(attachmentsJSON)
if err != nil {
return fmt.Errorf("load issue attachments: %w", err)
}

return lc.client.ReportIssue(lc.ctx, it, description, email, attachments, firstClassAttachments)
}

// collectLocalLogs returns every *.log directly under dir, with paths shaped
Expand Down
28 changes: 20 additions & 8 deletions lantern-core/ffi/ffi.go
Original file line number Diff line number Diff line change
Expand Up @@ -316,19 +316,31 @@ func getDataCapInfo() *C.char {
}

//export reportIssue
func reportIssue(emailC, typeC, descC, deviceC, modelC, logPathC *C.char) *C.char {
email := C.GoString(emailC)
issueType := C.GoString(typeC)
desc := C.GoString(descC)
device := C.GoString(deviceC)
model := C.GoString(modelC)
logPath := C.GoString(logPathC)
func reportIssue(
emailC, typeC, descC, deviceC, modelC, logPathC, attachmentsJSONC *C.char,
) *C.char {
return runOnGoStack(func() *C.char {
c, errStr := requireCore()
if errStr != nil {
return errStr
}
if err := c.ReportIssue(email, issueType, desc, device, model, logPath); err != nil {
email := C.GoString(emailC)
issueType := C.GoString(typeC)
desc := C.GoString(descC)
device := C.GoString(deviceC)
model := C.GoString(modelC)
logPath := C.GoString(logPathC)
attachmentsJSON := C.GoString(attachmentsJSONC)

if err := c.ReportIssue(
email,
issueType,
desc,
device,
model,
logPath,
attachmentsJSON,
); err != nil {
return C.CString(fmt.Sprintf("error reporting issue: %v", err))
}
return C.CString("ok")
Expand Down
14 changes: 12 additions & 2 deletions lantern-core/mobile/mobile.go
Original file line number Diff line number Diff line change
Expand Up @@ -437,9 +437,19 @@ func IsSplitTunnelingEnabled() bool {
return ok
}

func ReportIssue(email, issueType, description, device, model, logFilePath string) error {
func ReportIssue(
email, issueType, description, device, model, logFilePath, attachmentsJSON string,
) error {
return withCore(func(c lanterncore.Core) error {
return c.ReportIssue(email, issueType, description, device, model, logFilePath)
return c.ReportIssue(
email,
issueType,
description,
device,
model,
logFilePath,
attachmentsJSON,
)
})
}

Expand Down
Loading
Loading