diff --git a/.github/workflows/android-test.yml b/.github/workflows/android-test.yml
new file mode 100644
index 00000000..e499e2f5
--- /dev/null
+++ b/.github/workflows/android-test.yml
@@ -0,0 +1,99 @@
+name: Android Emulator Tests
+on: [ push, pull_request ]
+
+jobs:
+ check-if-tests-exist:
+ runs-on: ubuntu-latest
+ outputs:
+ status: ${{ steps.check-androidTest.outputs.NOT_EMPTY }}
+ min-sdk-version: ${{ steps.get-sdk-version.outputs.MIN_SDK_VERSION }}
+ target-sdk-version: ${{ steps.get-sdk-version.outputs.TARGET_SDK_VERSION }}
+ app-id: ${{ steps.get-app-id.outputs.APP_ID }}
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+ with:
+ submodules: "recursive"
+ - name: Check if androidTest folder is not empty
+ run: |
+ echo "NOT_EMPTY=$([ "$(ls -A app/src/androidTest)" ] && echo 'true' || echo 'false')"
+ echo "NOT_EMPTY=$([ "$(ls -A app/src/androidTest)" ] && echo 'true' || echo 'false')" >> $GITHUB_OUTPUT
+ id: check-androidTest
+ - name: Get min and target sdk
+ if: steps.check-androidTest.outputs.NOT_EMPTY == 'true'
+ id: get-sdk-version
+ run: |
+ echo "MIN_SDK_VERSION=$(cat app/build.gradle | grep minSdkVersion | rev | cut -d' ' -f 1 | rev)" >> $GITHUB_OUTPUT
+ echo "TARGET_SDK_VERSION=$(cat app/build.gradle | grep targetSdkVersion | rev | cut -d' ' -f 1 | rev)" >> $GITHUB_OUTPUT
+ - name: Get app ID
+ id: get-app-id
+ run: |
+ echo "APP_ID=$(cat app/build.gradle | grep applicationId | rev | cut -d' ' -f 1 | rev | tr -d '"')" >> $GITHUB_OUTPUT
+
+ test:
+ needs: check-if-tests-exist
+ if: needs.check-if-tests-exist.outputs.status == 'true'
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ api-level: [34, "${{ needs.check-if-tests-exist.outputs.min-sdk-version }}", "${{ needs.check-if-tests-exist.outputs.target-sdk-version }}"]
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+ with:
+ submodules: 'recursive'
+
+ - name: Enable KVM group perms
+ run: |
+ echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
+ sudo udevadm control --reload-rules
+ sudo udevadm trigger --name-match=kvm
+
+ - name: Gradle cache
+ uses: gradle/gradle-build-action@v3
+
+ - name: AVD cache
+ uses: actions/cache@v4
+ id: avd-cache
+ with:
+ path: |
+ ~/.android/avd/*
+ ~/.android/adb*
+ key: avd-${{ matrix.api-level }}
+
+ - name: Set up JDK environment
+ uses: actions/setup-java@v3
+ with:
+ distribution: 'zulu'
+ java-version: 17
+
+ - name: create AVD and generate snapshot for caching
+ if: steps.avd-cache.outputs.cache-hit != 'true'
+ uses: reactivecircus/android-emulator-runner@v2
+ with:
+ api-level: ${{ matrix.api-level }}
+ target: ${{ matrix.api-level >= 30 && 'google_apis' || 'default' }}
+ arch: ${{ matrix.api-level < 21 && 'x86' || 'x86_64' }}
+ force-avd-creation: false
+ emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
+ disable-animations: false
+ script: echo "Generated AVD snapshot for caching."
+
+ - name: Run connected tests
+ uses: ReactiveCircus/android-emulator-runner@v2
+ with:
+ api-level: ${{ matrix.api-level }}
+ target: ${{ matrix.api-level >= 30 && 'google_apis' || 'default' }}
+ arch: ${{ matrix.api-level < 21 && 'x86' || 'x86_64' }}
+ force-avd-creation: false
+ emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
+ disable-animations: true
+ script: |
+ adb uninstall ${{needs.check-if-tests-exist.outputs.app-id}} || true
+ adb uninstall ${{needs.check-if-tests-exist.outputs.app-id}}.test || true
+ adb uninstall ${{needs.check-if-tests-exist.outputs.app-id}}.androidTest || true
+ chmod +x gradlew
+ ./gradlew :app:connectedCheck --stacktrace
+ adb uninstall ${{needs.check-if-tests-exist.outputs.app-id}} || true
+ adb uninstall ${{needs.check-if-tests-exist.outputs.app-id}}.test || true
+ adb uninstall ${{needs.check-if-tests-exist.outputs.app-id}}.androidTest || true
diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml
index b20a40da..6e50db11 100644
--- a/.github/workflows/changelog.yml
+++ b/.github/workflows/changelog.yml
@@ -2,7 +2,7 @@ name: Changelog Generation
on:
release:
- types: [released]
+ types: [published]
workflow_dispatch:
jobs:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 694228ee..fe5b0a92 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,55 +1,32 @@
-name: Continuous integration
-
+name: Continuous Integration
on: [push, pull_request]
jobs:
test:
- name: Unit Tests
runs-on: ubuntu-20.04
steps:
- name: Checkout
uses: actions/checkout@v3
with:
submodules: "recursive"
+
- name: Set up JDK environment
uses: actions/setup-java@v3
with:
distribution: "zulu"
java-version: 17
+
- name: Make gradlew executable
run: chmod +x ./gradlew
+
- name: Setup Gradle
uses: gradle/gradle-build-action@v2
+
- name: Run local unit tests
run: bash ./gradlew test --stacktrace
- - name: Android Test Report
- uses: asadmansr/android-test-report-action@v1.2.0
-
- #androidTest:
- # name: Instrumented Tests
- # runs-on: macOS-latest
- # steps:
- # - uses: actions/checkout@v2
- # with:
- # submodules: 'recursive'
- # - name: Set up JDK 1.8
- # uses: actions/setup-java@v1
- # with:
- # java-version: 1.8
- # - name: Make gradlew executable
- # run: chmod +x ./gradlew
- # - name: Run Instrumented Tests
- # uses: reactivecircus/android-emulator-runner@v1
- # with:
- # api-level: 29
- # arch: x86
- # disable-animations: true
- # script: ./gradlew connectedAndroidTest --stacktrace
- apk:
- name: Build APK
+ build:
runs-on: ubuntu-20.04
-
steps:
- name: Checkout
uses: actions/checkout@v3
@@ -68,5 +45,23 @@ jobs:
- name: Setup Gradle
uses: gradle/gradle-build-action@v2
- - name: Build debug APK
- run: ./gradlew assembleDebug
+ - name: Run lint check
+ run: bash ./gradlew lint
+
+ - name: Upload lint result
+ uses: actions/upload-artifact@v4
+ with:
+ name: lint-results-debug
+ path: app/build/reports/lint-results-debug.html
+
+ - name: Build the app
+ run: bash ./gradlew build --stacktrace
+
+ - name: Build debug apk
+ run: bash ./gradlew assembleDebug
+
+ - name: Upload debug apk
+ uses: actions/upload-artifact@v4
+ with:
+ name: debug-apk
+ path: app/build/outputs/apk/debug/*.apk
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index 185b8a90..ae8e3c3f 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -24,8 +24,8 @@ android {
minSdkVersion 21
compileSdk 34
targetSdkVersion 34
- versionCode 19
- versionName "2.0.0"
+ versionCode 20
+ versionName "2.0.1"
}
applicationVariants.configureEach { variant ->
@@ -58,6 +58,10 @@ android {
jvmTarget = JavaVersion.VERSION_17.toString()
}
+ lint {
+ lintConfig = file("lint.xml")
+ }
+
room {
schemaDirectory "$projectDir/schemas"
}
@@ -82,6 +86,7 @@ dependencies {
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation "androidx.constraintlayout:constraintlayout:2.1.4"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.1'
+ implementation 'com.github.bumptech.glide:glide:4.11.0'
def work_version = "2.8.1"
implementation "androidx.work:work-runtime:$work_version"
diff --git a/app/lint.xml b/app/lint.xml
new file mode 100644
index 00000000..1b66a254
--- /dev/null
+++ b/app/lint.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/org/secuso/privacyfriendlynotes/ui/RecycleActivity.kt b/app/src/main/java/org/secuso/privacyfriendlynotes/ui/RecycleActivity.kt
index 823ff7b2..5174d802 100644
--- a/app/src/main/java/org/secuso/privacyfriendlynotes/ui/RecycleActivity.kt
+++ b/app/src/main/java/org/secuso/privacyfriendlynotes/ui/RecycleActivity.kt
@@ -14,7 +14,6 @@
package org.secuso.privacyfriendlynotes.ui
import android.os.Bundle
-import androidx.preference.PreferenceManager
import android.view.ContextThemeWrapper
import android.view.Menu
import android.view.MenuItem
@@ -24,6 +23,7 @@ import androidx.lifecycle.Lifecycle
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.flowWithLifecycle
import androidx.lifecycle.lifecycleScope
+import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
@@ -43,7 +43,7 @@ import org.secuso.privacyfriendlynotes.ui.main.MainActivityViewModel
class RecycleActivity : AppCompatActivity() {
private val mainActivityViewModel: MainActivityViewModel by lazy { ViewModelProvider(this)[MainActivityViewModel::class.java] }
private val searchView: SearchView by lazy { findViewById(R.id.searchViewFilterRecycle) }
- private val adapter: NoteAdapter by lazy { NoteAdapter(mainActivityViewModel, true) }
+ private val adapter: NoteAdapter by lazy { NoteAdapter(this, mainActivityViewModel, true) }
private val trashedNotes by lazy {
mainActivityViewModel.trashedNotes.flowWithLifecycle(lifecycle, Lifecycle.State.STARTED).stateIn(lifecycleScope, SharingStarted.Lazily, listOf())
}
diff --git a/app/src/main/java/org/secuso/privacyfriendlynotes/ui/adapter/NoteAdapter.kt b/app/src/main/java/org/secuso/privacyfriendlynotes/ui/adapter/NoteAdapter.kt
index de0a76f6..b96fd394 100644
--- a/app/src/main/java/org/secuso/privacyfriendlynotes/ui/adapter/NoteAdapter.kt
+++ b/app/src/main/java/org/secuso/privacyfriendlynotes/ui/adapter/NoteAdapter.kt
@@ -13,8 +13,8 @@
*/
package org.secuso.privacyfriendlynotes.ui.adapter
+import android.app.Activity
import android.graphics.Color
-import android.preference.PreferenceManager
import android.text.Html
import android.util.TypedValue
import android.view.LayoutInflater
@@ -22,12 +22,16 @@ import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
+import androidx.appcompat.content.res.AppCompatResources
+import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.RecyclerView
+import com.bumptech.glide.Glide
import org.secuso.privacyfriendlynotes.R
import org.secuso.privacyfriendlynotes.room.DbContract
import org.secuso.privacyfriendlynotes.room.model.Note
import org.secuso.privacyfriendlynotes.ui.main.MainActivityViewModel
import org.secuso.privacyfriendlynotes.ui.util.DarkModeUtil
+import java.io.File
/**
* Adapter that provides a binding for notes
@@ -36,6 +40,7 @@ import org.secuso.privacyfriendlynotes.ui.util.DarkModeUtil
* @see org.secuso.privacyfriendlynotes.ui.RecycleActivity
*/
class NoteAdapter(
+ private val activity: Activity,
private val mainActivityViewModel: MainActivityViewModel,
var colorCategory: Boolean,
) : RecyclerView.Adapter() {
@@ -62,7 +67,8 @@ class NoteAdapter(
holder.textViewTitle.text = currentNote.name
holder.textViewDescription.text = ""
val pref = PreferenceManager.getDefaultSharedPreferences(holder.itemView.context)
- holder.textViewDescription.visibility = if (pref.getBoolean("settings_show_preview", true)) View.VISIBLE else View.GONE
+ val showPreview = pref.getBoolean("settings_show_preview", true)
+ holder.textViewDescription.visibility = if (showPreview) View.VISIBLE else View.GONE
holder.textViewExtraText.visibility = View.GONE
holder.textViewExtraText.text = null
holder.imageViewcategory.visibility = View.GONE
@@ -94,45 +100,50 @@ class NoteAdapter(
}
}
- when (currentNote.type) {
- DbContract.NoteEntry.TYPE_TEXT -> {
- holder.textViewDescription.text = Html.fromHtml(currentNote.content)
- holder.textViewDescription.maxLines = 3
- }
+ when (currentNote.type) {
+ DbContract.NoteEntry.TYPE_TEXT -> {
+ if (showPreview) {
+ holder.textViewDescription.text = Html.fromHtml(currentNote.content)
+ holder.textViewDescription.maxLines = 3
+ }
+ }
- DbContract.NoteEntry.TYPE_AUDIO -> {
- holder.imageViewcategory.visibility = View.VISIBLE
- holder.imageViewcategory.setImageResource(R.drawable.ic_mic_icon_24dp)
- }
+ DbContract.NoteEntry.TYPE_AUDIO -> {
+ holder.imageViewcategory.visibility = View.VISIBLE
+ holder.imageViewcategory.setImageResource(R.drawable.ic_mic_icon_24dp)
+ }
- DbContract.NoteEntry.TYPE_SKETCH -> {
- holder.imageViewcategory.visibility = View.VISIBLE
- holder.imageViewcategory.setBackgroundColor(run {
- val value = TypedValue()
- holder.itemView.context.theme.resolveAttribute(R.attr.colorSurfaceVariantLight, value, true)
- value.data
- })
- if (pref.getBoolean("settings_show_preview", true)) {
- val bitmap = mainActivityViewModel.sketchPreview(currentNote, 200)
- if (bitmap != null) {
- holder.imageViewcategory.setImageBitmap(mainActivityViewModel.sketchPreview(currentNote, 200))
+ DbContract.NoteEntry.TYPE_SKETCH -> {
+ holder.imageViewcategory.visibility = View.VISIBLE
+ if (showPreview) {
+ holder.imageViewcategory.setBackgroundColor(run {
+ val value = TypedValue()
+ holder.itemView.context.theme.resolveAttribute(R.attr.colorSurfaceVariantLight, value, true)
+ value.data
+ })
+ holder.imageViewcategory.minimumHeight = 200; holder.imageViewcategory.minimumWidth = 200
+ Glide.with(activity).load(File("${activity.application.filesDir.path}/sketches${currentNote.content}"))
+ .placeholder(AppCompatResources.getDrawable(activity, R.drawable.ic_photo_icon_24dp))
+ .into(holder.imageViewcategory)
} else {
holder.imageViewcategory.setImageResource(R.drawable.ic_photo_icon_24dp)
}
- } else {
- holder.imageViewcategory.setImageResource(R.drawable.ic_photo_icon_24dp)
}
- }
- DbContract.NoteEntry.TYPE_CHECKLIST -> {
- val preview = mainActivityViewModel.checklistPreview(currentNote)
- holder.textViewExtraText.text = "${preview.filter { it.first }.count()}/${preview.size}"
- holder.textViewExtraText.visibility = View.VISIBLE
- holder.imageViewcategory.visibility = View.GONE
- holder.textViewDescription.text = preview.take(3).joinToString(System.lineSeparator()) { it.second }
- holder.textViewDescription.maxLines = 3
+ DbContract.NoteEntry.TYPE_CHECKLIST -> {
+ holder.imageViewcategory.visibility = View.GONE
+ holder.textViewExtraText.visibility = View.VISIBLE
+
+ if (showPreview) {
+ val preview = mainActivityViewModel.checklistPreview(currentNote)
+ holder.textViewExtraText.text = "${preview.filter { it.first }.count()}/${preview.size}"
+ holder.textViewDescription.text = preview.take(3).joinToString(System.lineSeparator()) { it.second }
+ holder.textViewDescription.maxLines = 3
+ } else {
+ holder.textViewExtraText.text = "-/-"
+ }
+ }
}
- }
// if the Description is empty, don't show it
if (holder.textViewDescription.text.toString().isEmpty()) {
diff --git a/app/src/main/java/org/secuso/privacyfriendlynotes/ui/main/MainActivity.kt b/app/src/main/java/org/secuso/privacyfriendlynotes/ui/main/MainActivity.kt
index 9459c026..493f6666 100644
--- a/app/src/main/java/org/secuso/privacyfriendlynotes/ui/main/MainActivity.kt
+++ b/app/src/main/java/org/secuso/privacyfriendlynotes/ui/main/MainActivity.kt
@@ -91,7 +91,7 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
ActivityResultContracts.StartActivityForResult()
) { result: ActivityResult ->
val data = result.data
- if (result.resultCode == RESULT_OK && data != null) {
+ if (result.resultCode == RESULT_OK && data != null && data.hasExtra(BaseNoteActivity.EXTRA_CATEGORY)) {
mainActivityViewModel.setCategory(data.getIntExtra(BaseNoteActivity.EXTRA_CATEGORY, CAT_ALL))
}
fab.close()
@@ -103,7 +103,7 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
if (className == MainFABFragment::class.java.name) {
this@MainActivity.fab = MainFABFragment {
Log.d("Received", "$it")
- Intent(
+ val i = Intent(
application, when (it) {
DbContract.NoteEntry.TYPE_TEXT -> TextNoteActivity::class.java
DbContract.NoteEntry.TYPE_CHECKLIST -> ChecklistNoteActivity::class.java
@@ -111,7 +111,9 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
DbContract.NoteEntry.TYPE_SKETCH -> SketchActivity::class.java
else -> throw NotImplementedError("Note of type $it cannot be created")
}
- ).let { intent -> setCategoryResultAfter.launch(intent) }
+ )
+ i.putExtra(BaseNoteActivity.EXTRA_CATEGORY, mainActivityViewModel.getCategory())
+ setCategoryResultAfter.launch(i)
fab.close()
}
return fab
@@ -137,6 +139,7 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
recyclerView.layoutManager = LinearLayoutManager(this)
recyclerView.setHasFixedSize(true)
adapter = NoteAdapter(
+ this,
mainActivityViewModel,
PreferenceManager.getDefaultSharedPreferences(this).getBoolean("settings_color_category", true)
&& mainActivityViewModel.getCategory() == CAT_ALL
@@ -327,25 +330,7 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
return true
}
- /**
- * Handles when notes are added.
- * @param v
- */
override fun onClick(v: View) {
- val intent =
- Function { activity: Class? ->
- val i = Intent(application, activity)
- i.putExtra(BaseNoteActivity.EXTRA_CATEGORY, mainActivityViewModel.getCategory())
- i
- }
- var i: Intent? = null
- when (v.id) {
- R.id.fab_text -> i = intent.apply(TextNoteActivity::class.java)
- R.id.fab_checklist -> i = intent.apply(ChecklistNoteActivity::class.java)
- R.id.fab_audio -> i = intent.apply(AudioNoteActivity::class.java)
- R.id.fab_sketch -> i = intent.apply(SketchActivity::class.java)
- }
- setCategoryResultAfter.launch(i)
}
override fun onPause() {
diff --git a/app/src/main/java/org/secuso/privacyfriendlynotes/ui/main/MainActivityViewModel.kt b/app/src/main/java/org/secuso/privacyfriendlynotes/ui/main/MainActivityViewModel.kt
index c8bfcd41..521780f8 100644
--- a/app/src/main/java/org/secuso/privacyfriendlynotes/ui/main/MainActivityViewModel.kt
+++ b/app/src/main/java/org/secuso/privacyfriendlynotes/ui/main/MainActivityViewModel.kt
@@ -54,7 +54,9 @@ class MainActivityViewModel(application: Application) : AndroidViewModel(applica
private val repository: NoteDatabase = NoteDatabase.getInstance(application)
private var filter: MutableStateFlow = MutableStateFlow("")
private var ordering: MutableStateFlow = MutableStateFlow(
- SortingOrder.valueOf(prefManager.getString(PreferenceKeys.SP_NOTES_ORDERING, SortingOrder.AlphabeticalAscending.name)!!)
+ kotlin.runCatching {
+ SortingOrder.valueOf(prefManager.getString(PreferenceKeys.SP_NOTES_ORDERING, SortingOrder.AlphabeticalAscending.name)!!)
+ }.getOrElse { SortingOrder.AlphabeticalAscending }
)
private var reversed: MutableStateFlow = MutableStateFlow(
prefManager.getBoolean(PreferenceKeys.SP_NOTES_REVERSED, false)
@@ -161,16 +163,16 @@ class MainActivityViewModel(application: Application) : AndroidViewModel(applica
private fun Flow>.filterNotes(): Flow> {
return this.map {
it.filter { note ->
- if (note.name.contains(filter.value)) {
+ if (note.name.contains(filter.value, ignoreCase = true)) {
return@filter true
}
when (note.type) {
DbContract.NoteEntry.TYPE_TEXT -> {
- return@filter Html.fromHtml(note.content).toString().contains(filter.value)
+ return@filter Html.fromHtml(note.content).toString().contains(filter.value, ignoreCase = true)
}
DbContract.NoteEntry.TYPE_CHECKLIST -> {
- return@filter ChecklistUtil.parse(note.content).joinToString(System.lineSeparator()).contains(filter.value)
+ return@filter ChecklistUtil.parse(note.content).joinToString(System.lineSeparator()).contains(filter.value, ignoreCase = true)
}
else -> return@filter false
@@ -185,7 +187,11 @@ class MainActivityViewModel(application: Application) : AndroidViewModel(applica
private fun Flow>.filterCategories(): Flow> {
return this.map {
- it.filter { note -> note.category == category.value || category.value == CAT_ALL }
+ it.filter { note ->
+ note.category == category.value // Note matches current category
+ || category.value == CAT_ALL // We're in the all notes category
+ || (category.value == 0 && note.category == -1) // Note is still in old default category (-1). Should still show in new default category (0)
+ }
}
}
@@ -239,7 +245,7 @@ class MainActivityViewModel(application: Application) : AndroidViewModel(applica
throw IllegalArgumentException("Only checklist notes allowed")
}
return ChecklistUtil.parse(note.content).map { (checked, name) ->
- return@map Pair(checked, String.format("[%s] $name", if (checked) "x" else " "))
+ return@map Pair(checked, "[${if (checked) "x" else " "}] $name")
}
}
diff --git a/app/src/main/java/org/secuso/privacyfriendlynotes/ui/notes/BaseNoteActivity.kt b/app/src/main/java/org/secuso/privacyfriendlynotes/ui/notes/BaseNoteActivity.kt
index e4fc22af..8e9e76ca 100644
--- a/app/src/main/java/org/secuso/privacyfriendlynotes/ui/notes/BaseNoteActivity.kt
+++ b/app/src/main/java/org/secuso/privacyfriendlynotes/ui/notes/BaseNoteActivity.kt
@@ -36,7 +36,14 @@ import android.view.MotionEvent
import android.view.View
import android.view.WindowManager
import android.view.inputmethod.InputMethodManager
-import android.widget.*
+import android.widget.ArrayAdapter
+import android.widget.AutoCompleteTextView
+import android.widget.DatePicker
+import android.widget.EditText
+import android.widget.PopupMenu
+import android.widget.TextView
+import android.widget.TimePicker
+import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
@@ -47,6 +54,7 @@ import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.coroutines.launch
+import kotlinx.coroutines.runBlocking
import org.secuso.privacyfriendlynotes.R
import org.secuso.privacyfriendlynotes.preference.PreferenceKeys
import org.secuso.privacyfriendlynotes.room.DbContract
@@ -59,7 +67,8 @@ import org.secuso.privacyfriendlynotes.ui.helper.NotificationHelper.removeNotifi
import org.secuso.privacyfriendlynotes.ui.helper.NotificationHelper.showAlertScheduledToast
import org.secuso.privacyfriendlynotes.ui.manageCategories.ManageCategoriesActivity
import java.io.OutputStream
-import java.util.*
+import java.util.Calendar
+import java.util.Date
/**
* A abstract note.
@@ -159,12 +168,13 @@ abstract class BaseNoteActivity(noteType: Int) : AppCompatActivity(), View.OnCli
}
- val intent = intent
currentCat = intent.getIntExtra(EXTRA_CATEGORY, 0)
savedCat = currentCat
// Return the given intent as result to return to the same category as started
- setResult(Activity.RESULT_OK, intent)
+ val resultIntent = Intent()
+ resultIntent.putExtra(EXTRA_CATEGORY, currentCat)
+ setResult(Activity.RESULT_OK, resultIntent)
createEditNoteViewModel.getCategoryNameFromId(currentCat).observe(this) { s ->
catSelection.setText(s ?: getString(R.string.default_category), false)
@@ -463,7 +473,14 @@ abstract class BaseNoteActivity(noteType: Int) : AppCompatActivity(), View.OnCli
}
if (isLoadedNote) {
note._id = id
- createEditNoteViewModel.update(note)
+ if (showNotSaved) {
+ //Wait for job to complete
+ runBlocking {
+ createEditNoteViewModel.update(note).join()
+ }
+ } else {
+ createEditNoteViewModel.update(note)
+ }
Toast.makeText(applicationContext, R.string.toast_updated, Toast.LENGTH_SHORT).show()
} else {
id = createEditNoteViewModel.insert(note)
diff --git a/app/src/main/java/org/secuso/privacyfriendlynotes/ui/notes/CreateEditNoteViewModel.kt b/app/src/main/java/org/secuso/privacyfriendlynotes/ui/notes/CreateEditNoteViewModel.kt
index e091a453..115953e9 100644
--- a/app/src/main/java/org/secuso/privacyfriendlynotes/ui/notes/CreateEditNoteViewModel.kt
+++ b/app/src/main/java/org/secuso/privacyfriendlynotes/ui/notes/CreateEditNoteViewModel.kt
@@ -21,6 +21,7 @@ import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@@ -111,8 +112,8 @@ class CreateEditNoteViewModel(application: Application) : AndroidViewModel(appli
return id
}
- fun update(note: Note) {
- viewModelScope.launch(Dispatchers.Default) {
+ fun update(note: Note): Job {
+ return viewModelScope.launch(Dispatchers.Default) {
database.noteDao().update(note)
}
}
diff --git a/gradlew b/gradlew
old mode 100644
new mode 100755