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
60 changes: 30 additions & 30 deletions TRANSLATIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,34 +19,34 @@ See [Android Translations Converter](https://github.com/Crustack/android-transla
<!-- translations:start -->
| Language | Coverage |
|----------|----------|
| 🇺🇸 English | 100% (336/336) |
| 🇪🇸 Catalan | 19% (65/336) |
| 🇨🇿 Czech | 93% (313/336) |
| 🇩🇰 Danish | 20% (69/336) |
| 🇩🇪 German | 97% (327/336) |
| 🇬🇷 Greek | 21% (72/336) |
| 🇪🇸 Spanish | 93% (314/336) |
| 🇫🇷 French | 97% (327/336) |
| 🇭🇺 Hungarian | 19% (65/336) |
| 🇮🇩 Indonesian | 22% (75/336) |
| 🇮🇹 Italian | 86% (291/336) |
| 🇯🇵 Japanese | 21% (73/336) |
| 🇲🇲 Burmese | 26% (90/336) |
| 🇳🇴 Norwegian Bokmål | 31% (106/336) |
| 🇳🇱 Dutch | 63% (212/336) |
| 🇳🇴 Norwegian Nynorsk | 31% (106/336) |
| 🇵🇱 Polish | 89% (300/336) |
| 🇧🇷 Portuguese (Brazil) | 92% (312/336) |
| 🇵🇹 Portuguese (Portugal) | 21% (71/336) |
| 🇷🇴 Romanian | 89% (301/336) |
| 🇷🇺 Russian | 90% (305/336) |
| 🇸🇰 Slovak | 19% (65/336) |
| 🇸🇮 Slovenian | 32% (109/336) |
| 🇸🇪 Swedish | 18% (63/336) |
| 🇵🇭 Tagalog | 19% (65/336) |
| 🇹🇷 Turkish | 21% (73/336) |
| 🇺🇦 Ukrainian | 97% (326/336) |
| 🇻🇳 Vietnamese | 31% (107/336) |
| 🇨🇳 Chinese (Simplified) | 96% (323/336) |
| 🇹🇼 Chinese (Traditional) | 87% (294/336) |
| 🇺🇸 English | 100% (337/337) |
| 🇪🇸 Catalan | 19% (65/337) |
| 🇨🇿 Czech | 92% (313/337) |
| 🇩🇰 Danish | 20% (69/337) |
| 🇩🇪 German | 97% (327/337) |
| 🇬🇷 Greek | 21% (72/337) |
| 🇪🇸 Spanish | 93% (314/337) |
| 🇫🇷 French | 97% (327/337) |
| 🇭🇺 Hungarian | 19% (65/337) |
| 🇮🇩 Indonesian | 22% (75/337) |
| 🇮🇹 Italian | 86% (291/337) |
| 🇯🇵 Japanese | 21% (73/337) |
| 🇲🇲 Burmese | 26% (90/337) |
| 🇳🇴 Norwegian Bokmål | 31% (106/337) |
| 🇳🇱 Dutch | 62% (212/337) |
| 🇳🇴 Norwegian Nynorsk | 31% (106/337) |
| 🇵🇱 Polish | 89% (300/337) |
| 🇧🇷 Portuguese (Brazil) | 92% (312/337) |
| 🇵🇹 Portuguese (Portugal) | 21% (71/337) |
| 🇷🇴 Romanian | 89% (301/337) |
| 🇷🇺 Russian | 90% (305/337) |
| 🇸🇰 Slovak | 19% (65/337) |
| 🇸🇮 Slovenian | 32% (109/337) |
| 🇸🇪 Swedish | 18% (63/337) |
| 🇵🇭 Tagalog | 19% (65/337) |
| 🇹🇷 Turkish | 21% (73/337) |
| 🇺🇦 Ukrainian | 96% (326/337) |
| 🇻🇳 Vietnamese | 31% (107/337) |
| 🇨🇳 Chinese (Simplified) | 95% (323/337) |
| 🇹🇼 Chinese (Traditional) | 87% (294/337) |
<!-- translations:end -->
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
package com.philkes.notallyx.data.model

import android.content.Context
import android.content.ContextWrapper
import android.content.Intent
import android.net.Uri
import android.text.Html
import android.util.Base64
import androidx.core.content.IntentCompat
import androidx.core.text.toHtml
import com.philkes.notallyx.R
import com.philkes.notallyx.data.dao.BaseNoteDao.Companion.MAX_BODY_CHAR_LENGTH
import com.philkes.notallyx.data.dao.NoteIdReminder
import com.philkes.notallyx.data.imports.markdown.createMarkdownFromBodyAndSpans
import com.philkes.notallyx.data.model.BaseNote.Companion.COLOR_DEFAULT
import com.philkes.notallyx.presentation.applySpans
import com.philkes.notallyx.presentation.showToast
import com.philkes.notallyx.presentation.viewmodel.NotallyModel
import com.philkes.notallyx.utils.decodeToBitmap
import com.philkes.notallyx.utils.getFileName
import com.philkes.notallyx.utils.getMimeType
import com.philkes.notallyx.utils.log
import java.io.File
import java.text.DateFormat
import java.text.SimpleDateFormat
Expand Down Expand Up @@ -560,3 +570,72 @@ fun ColorString.isValid() =
false
}
}

data class SharedNote(
val title: String,
val text: String,
val images: List<FileAttachment>,
val files: List<FileAttachment>,
)

fun Intent.generateBaseNote(context: ContextWrapper): SharedNote {
val title = getStringExtra(Intent.EXTRA_SUBJECT) ?: data?.let { context.getFileName(it) } ?: ""
val intentFiles =
IntentCompat.getParcelableArrayListExtra(this, Intent.EXTRA_STREAM, Uri::class.java)
?: IntentCompat.getParcelableExtra(this, Intent.EXTRA_STREAM, Uri::class.java)?.let {
listOf(it)
}
val text =
(data?.let { uri ->
context.contentResolver.openInputStream(uri)?.use { inputStream ->
try {
inputStream.bufferedReader().readText()
} catch (e: Exception) {
context.log(
tag = "",
msg = "Reading text contents from intent failed",
throwable = e,
)
null
}
}
?: run {
context.showToast(R.string.cant_load_file)
null
}
} ?: getStringExtra(Intent.EXTRA_TEXT) ?: "")
Comment on lines +589 to +606
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Toast shown prematurely when URI stream is null but fallback exists.

When openInputStream(uri) returns null, a toast is shown (Line 596) and null is returned from the data?.let block. However, the code then falls back to getStringExtra(Intent.EXTRA_TEXT) which may succeed. This results in a confusing UX where the user sees an error toast but the note is still created from EXTRA_TEXT.

Consider restructuring so the toast is only shown when both the URI stream and EXTRA_TEXT are unavailable.

🛠️ Proposed fix
     val text =
-        (data?.let { uri ->
-                context.contentResolver.openInputStream(uri)?.use { inputStream ->
-                    try {
-                        inputStream.bufferedReader().readText()
-                    } catch (e: Exception) {
-                        context.log(
-                            tag = "",
-                            msg = "Reading text contents from intent failed",
-                            throwable = e,
-                        )
-                        null
-                    }
-                }
-                    ?: run {
-                        context.showToast(R.string.cant_load_file)
-                        null
-                    }
-            } ?: getStringExtra(Intent.EXTRA_TEXT) ?: "")
+        (data?.let { uri ->
+                context.contentResolver.openInputStream(uri)?.use { inputStream ->
+                    try {
+                        inputStream.bufferedReader().readText()
+                    } catch (e: Exception) {
+                        context.log(
+                            tag = "",
+                            msg = "Reading text contents from intent failed",
+                            throwable = e,
+                        )
+                        null
+                    }
+                }
+            }
+            ?: getStringExtra(Intent.EXTRA_TEXT)
+            ?: run {
+                if (data != null) {
+                    context.showToast(R.string.cant_load_file)
+                }
+                ""
+            })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/java/com/philkes/notallyx/data/model/ModelExtensions.kt` around
lines 582 - 599, The current intent-text loading logic inside the extension in
ModelExtensions.kt shows a toast as soon as openInputStream(uri) returns null
even though getStringExtra(Intent.EXTRA_TEXT) might still provide content;
change the control flow so you attempt data?.let { uri ->
context.contentResolver.openInputStream(uri)?.use { ... } } and only call
context.showToast(R.string.cant_load_file) if both the input stream result and
getStringExtra(Intent.EXTRA_TEXT) are null/empty. Concretely, preserve the
readText try/catch inside the openInputStream usage, return its result if
non-null, otherwise check getStringExtra(Intent.EXTRA_TEXT) and only when that
is also null show the toast and return null/empty.

.let {
if (it.length > MAX_BODY_CHAR_LENGTH) {
context.showToast(
context.getString(
R.string.note_text_too_long_truncated,
MAX_BODY_CHAR_LENGTH,
)
)
}
it.take(MAX_BODY_CHAR_LENGTH)
}
val (images, files) =
intentFiles?.let {
val filesByType =
it.groupBy { uri ->
context.getMimeType(uri)?.let { mimeType ->
if (mimeType.isImageMimeType) {
NotallyModel.FileType.IMAGE
} else {
NotallyModel.FileType.ANY
}
} ?: NotallyModel.FileType.ANY
}
val images =
filesByType[NotallyModel.FileType.IMAGE]?.let { images ->
images.map { FileAttachment("", it.toString(), "") }
} ?: listOf()
val files =
filesByType[NotallyModel.FileType.ANY]?.let { otherFiles ->
otherFiles.map { FileAttachment("", it.toString(), "") }
} ?: listOf()
Pair(images, files)
} ?: Pair(listOf(), listOf())
return SharedNote(title, text, images, files = files)
}
Original file line number Diff line number Diff line change
Expand Up @@ -225,11 +225,12 @@ fun Menu.add(
drawable: Int,
showAsAction: Int = MenuItem.SHOW_AS_ACTION_IF_ROOM,
groupId: Int = Menu.NONE,
itemId: Int = Menu.NONE,
order: Int = Menu.NONE,
onClick: (item: MenuItem) -> Unit,
): MenuItem {
val menuItem =
add(groupId, Menu.NONE, order, title).setIcon(drawable).setOnMenuItemClickListener { item ->
add(groupId, itemId, order, title).setIcon(drawable).setOnMenuItemClickListener { item ->
onClick(item)
item.isChecked = true
return@setOnMenuItemClickListener false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ abstract class LockedActivity<T : ViewBinding> : AppCompatActivity() {
private lateinit var biometricAuthenticationActivityResultLauncher:
ActivityResultLauncher<Intent>

protected lateinit var binding: T
internal lateinit var binding: T
protected lateinit var preferences: NotallyXPreferences
val baseModel: BaseNoteModel by viewModels()

Expand Down
Loading