Skip to content

Commit 5aae486

Browse files
authored
Merge pull request #557 from jorgeblacio/delete_labels
Now you can delete labels.
2 parents efbd500 + df4464a commit 5aae486

File tree

28 files changed

+367
-8
lines changed

28 files changed

+367
-8
lines changed
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
package com.criptext.mail.scenes.settings.data
2+
3+
import androidx.test.rule.ActivityTestRule
4+
import androidx.test.runner.AndroidJUnit4
5+
import com.criptext.mail.Config
6+
import com.criptext.mail.androidtest.TestActivity
7+
import com.criptext.mail.androidtest.TestDatabase
8+
import com.criptext.mail.api.HttpClient
9+
import com.criptext.mail.db.KeyValueStorage
10+
import com.criptext.mail.db.SettingsLocalDB
11+
import com.criptext.mail.db.models.Account
12+
import com.criptext.mail.db.models.ActiveAccount
13+
import com.criptext.mail.db.models.Contact
14+
import com.criptext.mail.db.models.Label
15+
import com.criptext.mail.scenes.settings.labels.data.LabelsResult
16+
import com.criptext.mail.scenes.settings.labels.workers.CreateCustomLabelWorker
17+
import com.criptext.mail.scenes.settings.labels.workers.DeleteCustomLabelWorker
18+
import com.criptext.mail.utils.ExpectedRequest
19+
import com.criptext.mail.utils.MockedResponse
20+
import com.criptext.mail.utils.assertSentRequests
21+
import com.criptext.mail.utils.enqueueResponses
22+
import io.mockk.mockk
23+
import okhttp3.mockwebserver.MockWebServer
24+
import org.amshove.kluent.shouldBe
25+
import org.amshove.kluent.shouldEqual
26+
import org.amshove.kluent.shouldNotBe
27+
import org.junit.After
28+
import org.junit.Before
29+
import org.junit.Rule
30+
import org.junit.Test
31+
import org.junit.runner.RunWith
32+
33+
@RunWith(AndroidJUnit4::class)
34+
class DeleteCustomLabelWorkerTest{
35+
36+
@get:Rule
37+
val mActivityRule = ActivityTestRule(TestActivity::class.java)
38+
39+
private lateinit var storage: KeyValueStorage
40+
private lateinit var db: TestDatabase
41+
private lateinit var settingsLocalDB: SettingsLocalDB
42+
private lateinit var mockWebServer: MockWebServer
43+
private val activeAccount = ActiveAccount(name = "Tester", recipientId = "tester",
44+
deviceId = 1, jwt = "__JWTOKEN__", signature = "", refreshToken = "", id = 1,
45+
domain = Contact.mainDomain)
46+
private lateinit var httpClient: HttpClient
47+
48+
@Before
49+
fun setup() {
50+
// mock http requests
51+
mockWebServer = MockWebServer()
52+
mockWebServer.start()
53+
storage = mockk(relaxed = true)
54+
val mockWebServerUrl = mockWebServer.url("/mock").toString()
55+
httpClient = HttpClient.Default(authScheme = HttpClient.AuthScheme.jwt,
56+
baseUrl = mockWebServerUrl, connectionTimeout = 1000L, readTimeout = 1000L)
57+
db = TestDatabase.getInstance(mActivityRule.activity)
58+
db.resetDao().deleteAllData(1)
59+
db.labelDao().insertAll(Label.DefaultItems().toList())
60+
db.accountDao().insert(Account(activeAccount.id, activeAccount.recipientId, activeAccount.deviceId,
61+
activeAccount.name, activeAccount.jwt, activeAccount.refreshToken,
62+
"_KEY_PAIR_", 0, "", "criptext.com",
63+
true, true,
64+
backupPassword = null, autoBackupFrequency = 0, hasCloudBackup = false, wifiOnly = true, lastTimeBackup = null))
65+
settingsLocalDB = SettingsLocalDB.Default(db)
66+
}
67+
68+
@Test
69+
fun test_should_create_and_delete_a_custom_label(){
70+
if (Config.mockCriptextHTTPRequests) {
71+
mockWebServer.enqueueResponses(listOf(
72+
MockedResponse.Ok(""),
73+
MockedResponse.Ok("")
74+
))
75+
}
76+
val labelName = "__LABEL__"
77+
val createWorker = createLabelWorker(labelName)
78+
val createResult = createWorker.work(mockk()) as LabelsResult.CreateCustomLabel.Success
79+
80+
createResult.label.text shouldEqual labelName
81+
82+
db.labelDao().get(labelName, activeAccount.id) shouldNotBe null
83+
84+
val labelUUID = createResult.label.uuid
85+
val deleteWorker = deleteLabelWorker(labelUUID)
86+
val deleteResult = deleteWorker.work(mockk()) as LabelsResult.DeleteCustomLabel.Success
87+
88+
deleteResult.uuid shouldEqual labelUUID
89+
90+
db.labelDao().getByUUID(labelUUID, activeAccount.id) shouldBe null
91+
}
92+
93+
private fun deleteLabelWorker(uuid: String): DeleteCustomLabelWorker =
94+
DeleteCustomLabelWorker(
95+
labelUUID = uuid,
96+
settingsLocalDB = settingsLocalDB,
97+
activeAccount = activeAccount,
98+
httpClient = httpClient,
99+
publishFn = {},
100+
storage = storage)
101+
102+
private fun createLabelWorker(labelName: String): CreateCustomLabelWorker =
103+
CreateCustomLabelWorker(
104+
labelName = labelName,
105+
settingsLocalDB = settingsLocalDB,
106+
activeAccount = activeAccount,
107+
httpClient = httpClient,
108+
publishFn = {},
109+
storage = storage)
110+
111+
@After
112+
fun teardown() {
113+
if (Config.mockCriptextHTTPRequests)
114+
mockWebServer.close()
115+
}
116+
}

src/main/kotlin/com/criptext/mail/api/models/Event.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ data class Event(val rowid: Long, val recipientId: String, val domain: String, v
5252
const val recoveryEmailChanged = 311
5353
const val recoveryEmailConfirmed = 312
5454
const val profilePictureChanged = 313
55+
const val peerLabelDeleted = 320
5556

5657
//Sync Devices
5758
const val syncBeginRequest = 211
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.criptext.mail.api.models
2+
3+
4+
import org.json.JSONObject
5+
6+
/**
7+
* * data class for per label status updates. This is received as params of a "peer label deleted status update" event (320).
8+
*/
9+
10+
data class PeerLabelDeletedStatusUpdate (val uuid: String) {
11+
companion object {
12+
13+
fun fromJSON(jsonString: String): PeerLabelDeletedStatusUpdate {
14+
val json = JSONObject(jsonString)
15+
return PeerLabelDeletedStatusUpdate(
16+
uuid = json.getString("uuid")
17+
)
18+
}
19+
}
20+
}

src/main/kotlin/com/criptext/mail/db/EventLocalDB.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,13 @@ class EventLocalDB(private val db: AppDatabase, private val filesDir: File, priv
137137
))
138138
}
139139

140+
fun updateDeleteLabel(uuid: String, accountId: Long) {
141+
db.labelDao().deleteByLabelUUID(
142+
uuid = uuid,
143+
accountId = accountId
144+
)
145+
}
146+
140147
fun updateDeleteThreadPermanently(threadIds: List<String>, activeAccount: ActiveAccount) {
141148
if(threadIds.isNotEmpty()){
142149
db.emailDao().getEmailsFromThreadIds(threadIds, activeAccount.id).forEach {

src/main/kotlin/com/criptext/mail/db/dao/LabelDao.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,19 @@ interface LabelDao {
3737
@Delete
3838
fun delete(label: Label)
3939

40+
@Query("""DELETE FROM label
41+
WHERE uuid=:uuid AND accountId = :accountId""")
42+
fun deleteByLabelUUID(uuid: String, accountId: Long)
43+
4044
@Query("""SELECT * FROM label
4145
WHERE text=:labelName AND (accountId IS NULL OR accountId = :accountId)
4246
LIMIT 1""")
4347
fun get(labelName: String, accountId: Long): Label
4448

49+
@Query("""SELECT * FROM label
50+
WHERE uuid=:uuid AND accountId = :accountId""")
51+
fun getByUUID(uuid: String, accountId: Long): Label?
52+
4553
@Query("""select CAST(COUNT(*) AS BIT) FROM label WHERE text=:labelName""")
4654
fun alreadyExists(labelName: String): Boolean
4755

src/main/kotlin/com/criptext/mail/scenes/emaildetail/ui/labels/LabelHolder.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import android.graphics.PorterDuff
55
import androidx.core.content.ContextCompat
66
import androidx.recyclerview.widget.RecyclerView
77
import android.view.View
8+
import android.widget.ImageView
89
import android.widget.LinearLayout
910
import android.widget.TextView
1011
import com.criptext.mail.R

src/main/kotlin/com/criptext/mail/scenes/label_chooser/holders/LabelHolder.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ class LabelHolder(val view: View) : RecyclerView.ViewHolder(view), View.OnClickL
2121
private val nameView : TextView
2222
private val checkBoxView : CheckBox
2323
private val labelColor: ImageView
24+
private val trashImage: ImageView
2425
private val viewSeparator: View
2526

2627
init {
@@ -31,13 +32,15 @@ class LabelHolder(val view: View) : RecyclerView.ViewHolder(view), View.OnClickL
3132
nameView.text = labelThread.text
3233
checkBoxView.isChecked = labelThread.isSelected
3334
viewSeparator.visibility = View.GONE
35+
trashImage.visibility = View.GONE
3436
DrawableCompat.setTint(labelColor.drawable, Color.parseColor("#${labelThread.color}"))
3537
}
3638

3739
init {
3840
nameView = view.findViewById(R.id.label_name) as TextView
3941
checkBoxView = view.findViewById(R.id.label_checkbox) as CheckBox
4042
labelColor = view.findViewById(R.id.label_color)
43+
trashImage = view.findViewById(R.id.label_trash)
4144
viewSeparator = view.findViewById(R.id.viewSeparator)
4245
}
4346

src/main/kotlin/com/criptext/mail/scenes/mailbox/ui/LabelHolder.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ class LabelHolder(val view: View) : RecyclerView.ViewHolder(view){
1919
private val nameView : TextView
2020
private val checkBoxView : CheckBox
2121
private val labelColor: ImageView
22+
private val trashImage: ImageView
2223
private val rootView: View
2324
private val viewSeparator: View
2425

@@ -31,9 +32,11 @@ class LabelHolder(val view: View) : RecyclerView.ViewHolder(view){
3132
nameView = view.findViewById(R.id.label_name) as TextView
3233
checkBoxView = view.findViewById(R.id.label_checkbox) as CheckBox
3334
labelColor = view.findViewById(R.id.label_color)
35+
trashImage = view.findViewById(R.id.label_trash)
3436
rootView = view.findViewById(R.id.rootView)
3537
viewSeparator = view.findViewById(R.id.viewSeparator)
3638
checkBoxView.visibility = View.INVISIBLE
39+
trashImage.visibility = View.GONE
3740
viewSeparator.visibility = View.GONE
3841
}
3942

src/main/kotlin/com/criptext/mail/scenes/settings/labels/LabelsController.kt

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import com.criptext.mail.utils.generaldatasource.data.GeneralDataSource
2525
import com.criptext.mail.utils.generaldatasource.data.GeneralRequest
2626
import com.criptext.mail.utils.generaldatasource.data.GeneralResult
2727
import com.criptext.mail.utils.generaldatasource.data.UserDataWriter
28+
import com.criptext.mail.utils.ui.data.DialogData
2829
import com.criptext.mail.utils.ui.data.DialogResult
2930
import com.criptext.mail.utils.ui.data.DialogType
3031
import com.criptext.mail.websocket.WebSocketEventListener
@@ -61,10 +62,20 @@ class LabelsController(
6162
when(result) {
6263
is LabelsResult.GetCustomLabels -> onGetCustomLabels(result)
6364
is LabelsResult.CreateCustomLabel -> onCreateCustomLabels(result)
65+
is LabelsResult.DeleteCustomLabel -> onDeleteCustomLabel(result)
6466
}
6567
}
6668

6769
private val labelsUIObserver = object: LabelsUIObserver{
70+
override fun onDeleteLabelClicked(label: LabelWrapper) {
71+
model.lastSelectedUUID = label.label.uuid
72+
scene.showLabelDeleteDialog(DialogData.DialogConfirmationData(
73+
title = UIMessage(R.string.title_delete_label),
74+
message = listOf(UIMessage(R.string.message_delete_label, arrayOf(label.text))),
75+
type = DialogType.DeleteLabel()
76+
))
77+
}
78+
6879
override fun onToggleLabelSelection(label: LabelWrapper) {
6980
dataSource.submitRequest(LabelsRequest.ChangeVisibilityLabel(label.id, label.isSelected))
7081
}
@@ -102,6 +113,9 @@ class LabelsController(
102113
}
103114
is DialogType.SignIn ->
104115
host.goToScene(SignInParams(true), true)
116+
is DialogType.DeleteLabel -> {
117+
dataSource.submitRequest(LabelsRequest.DeleteCustomLabel(model.lastSelectedUUID))
118+
}
105119
}
106120
}
107121
}
@@ -241,6 +255,20 @@ class LabelsController(
241255
}
242256
}
243257

258+
private fun onDeleteCustomLabel(result: LabelsResult.DeleteCustomLabel){
259+
model.lastSelectedUUID = ""
260+
when(result) {
261+
is LabelsResult.DeleteCustomLabel.Success -> {
262+
val index = model.labels.indexOfFirst { it.label.uuid == result.uuid }
263+
if(index >= 0)
264+
labelWrapperListController.remove(index)
265+
}
266+
is LabelsResult.DeleteCustomLabel.Failure -> {
267+
scene.showMessage(UIMessage(R.string.error_deleting_label))
268+
}
269+
}
270+
}
271+
244272
private fun onGetCustomLabels(result: LabelsResult.GetCustomLabels){
245273
when(result) {
246274
is LabelsResult.GetCustomLabels.Success -> {

src/main/kotlin/com/criptext/mail/scenes/settings/labels/LabelsModel.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ import com.criptext.mail.scenes.label_chooser.data.LabelWrapper
55

66
class LabelsModel: SceneModel{
77
val labels : ArrayList<LabelWrapper> = ArrayList()
8+
var lastSelectedUUID = ""
89
}

0 commit comments

Comments
 (0)